<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9013148337555241633</id><updated>2012-01-18T21:55:18.313-08:00</updated><category term='Engin'/><category term='javascript'/><category term='version control systems'/><category term='Adobe Bridge'/><category term='ActionScript'/><category term='SVG'/><category term='PayPal'/><category term='conversion'/><category term='CodeSmith'/><category term='open source'/><category term='instanceof'/><category term='ASP.NET'/><category term='XAML'/><category term='ASP.NET hosting'/><category term='anti-spam'/><category term='scams'/><category term='iPod'/><category term='ExtendScript'/><category term='Adobe BridgeTalk'/><category term='virtual hard disks'/><category term='Microsoft SilverLight'/><category term='performance'/><category term='Adobe Illustrator'/><category term='sleep mode'/><category term='LINQ to SQL'/><category term='MOUSE_OVER'/><category term='GMail'/><category term='SharePod'/><category term='buy-it-now'/><category term='Adobe Creation Suite CS4 Subscription Edition'/><category term='Windows 7'/><category term='flash.display.TextField'/><category term='Remote desktop'/><category term='lsass.exe'/><category term='Adobe Flash'/><category term='SQL Server 2008'/><category term='CSS'/><category term='aspnet_compiler'/><category term='Bazaar'/><category term='libraries'/><category term='PC-Mac interoperation'/><category term='JSFL'/><category term='.NET bugs'/><category term='VoIP'/><category term='vector graphics stroke'/><category term='iPhone'/><category term='.NET framework'/><category term='customer experience'/><category term='SimpleButton'/><category term='GPS'/><category term='Intel SSDs'/><category term='PLINQO'/><category term='ebay iPhone app'/><category term='clipboard'/><category term='XamlTune'/><category term='BAML'/><category term='WPF assembly merging'/><category term='.NET'/><category term='MOUSE_OUT'/><category term='SSDs'/><title type='text'>Self Documenting Code</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>57</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7294818097736446536</id><published>2012-01-18T21:54:00.000-08:00</published><updated>2012-01-18T21:55:18.346-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scams'/><title type='text'>Magnetic Laundry Balls - glad I didn't buy</title><content type='html'>It sounded awesome - never use laundry powder (detergent) again - just place these reusable magnetic balls in the washing machine instead.&lt;br /&gt;&lt;br /&gt;Claimed to alter the surface tension of the water, making it wash more effectively.&lt;br /&gt;&lt;br /&gt;Hmmmm - y'know, sounds cool.  I considered buying.&lt;br /&gt;&lt;br /&gt;But I Googled for more info, 'coz it did seem, well, pretty extraordinary.&lt;br /&gt;&lt;br /&gt;First big clue that something's sus : page after page of search results are almost entirely official websites or resellers.&lt;br /&gt;&lt;br /&gt;Y'know, if I'd found such an awesome product and it worked for me, I'd've blogged about it, right?  So where are the rave testimonials, not from random unknowns who might be company agents, but on blogs that have loads and laods of reviews - some positive, some negative - demonstrating their impartiality?&lt;br /&gt;&lt;br /&gt;In contrast, there are numerous reports that cast these "magnetic laundry balls" in very bad light.  You can find them yourself if you dig &amp;amp; dig through pages of Google search results.  I'll just link to a few here to help improve their Google rank.&lt;br /&gt;&lt;br /&gt;&lt;a href='http://blog.kamens.us/2009/01/04/more-on-the-magnetic-laundry-scam/'&gt;Magnetic laundry ball scam&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.chem1.com/CQ/magscams.html'&gt;Magnetic laundry aids and surface tension reduction&lt;/a&gt; - a critique&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.eco-scams.com/archives/588'&gt;Magnetic laundry scams&lt;/a&gt; - not as detailed, but relevant&lt;br /&gt;&lt;br /&gt;Buyer beware!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7294818097736446536?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7294818097736446536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7294818097736446536' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7294818097736446536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7294818097736446536'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2012/01/magnetic-laundry-balls-glad-i-didnt-buy.html' title='Magnetic Laundry Balls - glad I didn&apos;t buy'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-3632211373749777429</id><published>2012-01-11T16:31:00.000-08:00</published><updated>2012-01-11T16:38:25.478-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GMail'/><title type='text'>Google Apps GMail bug with multiple sign-in and POP3 access</title><content type='html'>&lt;em&gt;The skinny : Trouble with POP3 or forwarding from one GMail or Google Apps account to another?  Make sure you're signed out of all multiple-sign-ins in all browsers for the affected accounts, and don't multiple-sign-in again with the account your trying to get emails from.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;The fat : read on...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;GMail is a very refined product, but unfortunately, its rare bugs tend to be &lt;strong&gt;extremely&lt;/strong&gt; poorly handled, causing wasted time chasing rabbits hither and thither.&lt;br /&gt;&lt;br /&gt;Take my recent challenge of combining a Google Apps email account into my personal GMail account.  Should be easy, right?  And it did seem so.&lt;br /&gt;&lt;br /&gt;I configured my personal GMail account to be able to send as my Google Apps email address - all worked fine.&lt;br /&gt;&lt;br /&gt;And I configured the Google Apps email account to auto-forward to my personal email account and delete - and that was working fine too.&lt;br /&gt;&lt;br /&gt;Then I discovered a cool new feature in GMail (and the wider world of Google) called "multiple sign-in", making it possible to be concurrently signed in to multiple accounts!  Whoohoo!  I tried it, but it wasn't as seamless an experience as I'd hoped for, so I decided to just stick with having everything pouring into my personal GMail account.&lt;br /&gt;&lt;br /&gt;And the world got pretty quiet.&lt;br /&gt;&lt;br /&gt;But hey - it was new year, so I figured everyone was away.&lt;br /&gt;&lt;br /&gt;But I did get a report of an email sent to me, that definitely never arrived.&lt;br /&gt;&lt;br /&gt;And then another report from a different sender.&lt;br /&gt;&lt;br /&gt;Hmmm..........&lt;br /&gt;&lt;br /&gt;I logged into my Google Apps email account, and there were 15 emails that had never been forwarded to my personal GMail account!!!  How did that happen!!!??!!?!!&lt;br /&gt;&lt;br /&gt;I looked at the Google Apps email account's settings, and it had reverted back to not automatically forwarding emails.  I corrected that, telling it once again to forward all emails to my personal GMail account.&lt;br /&gt;&lt;br /&gt;That's not the end of the story - it's just getting started - but on this matter my educated guess is that GMail automatically disabled the auto-forwarding when that Google Apps email account became enabled for concurrent multiple sign-in.  (Whether they would do that generally, or whether they did it because the forward-to email address was associated with the other of the concurrently-signed-in accounts, I don't know.  It would be easy enough to test - you could let us know in the comments if you determine either way.)&lt;br /&gt;&lt;br /&gt;So now my problem was 15 emails sitting in the one account when I wanted them in the other.  I could manually forward each one - not optimal.  Or I could try to use POP3 import that I use successfully in GMail for other accounts.&lt;br /&gt;&lt;br /&gt;Only, every time I try POP3 import from the Google Apps email account to my personal email account, GMail tells me that the username + password combination is not accepted.  Very strange.&lt;br /&gt;&lt;br /&gt;I dig around and manage to confirm that pop.gmail.com is the correct POP3 server name even for Google Apps email accounts.  So no problem there.&lt;br /&gt;&lt;br /&gt;I've definitely set the POP3 port to 995 and set to use encryption.  No problem there.&lt;br /&gt;&lt;br /&gt;I try some other combinations of settings anyway just in case, but the error messages made it clear they weren't the right answer.&lt;br /&gt;&lt;br /&gt;I found the POP3 bulk downloader tool in my personal GMail account, and tried to use that to download the emails from the Google Apps email account.  But it just sat there saying "Connecting" for many minutes, until I closed the window. tried again with equal non-success and gave up on that approach.&lt;br /&gt;&lt;br /&gt;I found a note about using Captcha Unlock for your GMail account, so I tried to use it for the Google Apps account, just in case that would help, but crazily, it kept telling me that the password I'd enterted was incorrect, even though it was correct.  Just in case, I even went ahead and changed the password, which involved entering the current password for verification, and the change password proceeded fine, but even the new password was rejected as incorrect by the Google Captcha Unlock page.&lt;br /&gt;&lt;br /&gt;Bizarre!  Some Google pages knew my password, but others rejected it.  Go figure.&lt;br /&gt;&lt;br /&gt;I even tried multiple browsers - same result.&lt;br /&gt;&lt;br /&gt;So it was no thanks to useless error messages and processes that totally failed me that I finally found what seems to be the solution.&lt;br /&gt;&lt;br /&gt;I document it here for the few travellers encountering the same problem.&lt;br /&gt;&lt;br /&gt;The solution?  I signed out of all Google accounts in all browsers, and then studiously avoided using the multiple-sign-in feature.  That was all it took.  When signed in &lt;strong&gt;only&lt;/strong&gt; to my personal GMail account, I was able to easily add a POP3 download from my Google Apps email account, and it worked flawlessly.&lt;br /&gt;&lt;br /&gt;No thanks Google for the time wastage, but hey, big thanks still for an in-nearly-all-other-respects AWESOME product.  GMail fanboy is me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-3632211373749777429?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/3632211373749777429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=3632211373749777429' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3632211373749777429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3632211373749777429'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2012/01/google-apps-gmail-bug-with-multiple.html' title='Google Apps GMail bug with multiple sign-in and POP3 access'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6867013479746249007</id><published>2011-12-13T21:51:00.000-08:00</published><updated>2011-12-13T21:54:14.584-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='customer experience'/><title type='text'>Google Apps CNAME activation - here be more dragons</title><content type='html'>It used to be you could create a CNAME record to verify your ownership of a domain name, when setting up a Google Apps account.&lt;br /&gt;&lt;br /&gt;To this day, current Google Apps documentation still says you can do it :&lt;br /&gt;&lt;br /&gt;&lt;a href="http://support.google.com/a/bin/answer.py?hl=en&amp;amp;answer=93595"&gt;Troubleshooting CNAME Records&lt;/a&gt; :&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;There are two reasons to create a CNAME record for Google Apps: verifying domain ownership and customizing a URL.&lt;/blockquote&gt;Dig as you might through the user interface, you'll be offered a way to verify using TXT records, but nada for CNAME records.&lt;br /&gt;&lt;br /&gt;Some enterprising folk around 18 months ago figured a &lt;a href="http://www.google.com/support/forum/p/Google%20Apps/thread?tid=5475d2764151eef4&amp;amp;hl=en"&gt;workaround&lt;/a&gt;.&amp;nbsp; But even that no longer works.&lt;br /&gt;&lt;br /&gt;It seems that Google has quietly - nay &lt;i&gt;silently&lt;/i&gt; - axed support for CNAMEs for domain verification.&lt;br /&gt;&lt;br /&gt;Whilst still mentioning in current documentation that you can.&lt;br /&gt;&lt;br /&gt;So the nontrivial effort I've just gone through getting a CNAME record created by an extraordinarily-slow-to-respond IT department, was a waste.&lt;br /&gt;&lt;br /&gt;But not just any kind of waste.&amp;nbsp; A waste for which Google itself is responsible.&lt;br /&gt;&lt;br /&gt;It's one thing to remove a feature.&amp;nbsp; Sure - I have no problem with that.&lt;br /&gt;&lt;br /&gt;After all, it's a free service anyway, so no complaints there.&lt;br /&gt;&lt;br /&gt;But at least &lt;i&gt;tell us&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;The current documentation which says you &lt;b&gt;can&lt;/b&gt; use a CNAME for domain verification, combined with the preponderence of articles throughout the web explaining how to do it, combined with the complete absence of acknowledgement from Google that they've removed the option, combined with (in the first few pages of search results) complete absence of any bloggers like me (that I managed to find) pointing out the omission, was a perfect recipe for getting me - and doubtless many others - to waste time arranging things that Google no longer supports.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Just tell us&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Y'know, a Google blog post or something with all the right keywords : "by the way, kids, we're axing the CNAME option for Google Apps domain name verification".&lt;br /&gt;&lt;br /&gt;By &lt;i&gt;not&lt;/i&gt; telling us, and especially by failing to properly update your documentation, you've wasted my time, and doubtless that of others.&lt;br /&gt;&lt;br /&gt;Not happy.&lt;br /&gt;&lt;br /&gt;Not impressed.&lt;br /&gt;&lt;br /&gt;What is wrong with a little footnote in your other help pages (the ones that do now mention TXT records), that CNAME records &lt;i&gt;used to be&lt;/i&gt; supported but no longer are?&lt;br /&gt;&lt;br /&gt;I mean, if I'd come across one official page (as I did - linked above) on the Google site saying "CNAMEs &lt;b&gt;are&lt;/b&gt; supported" and another one saying "CNAMEs &lt;b&gt;used to be&lt;/b&gt; supported but no longer are", I'd figure the second supersedes the first.&amp;nbsp; But what's with this insistence on not even &lt;i&gt;mentioning&lt;/i&gt; the removal of the CNAME option?&lt;br /&gt;&lt;br /&gt;It makes no sense to me, and it is an exercise in providing a bad customer experience.&amp;nbsp; I'm generally a raving Google fan, but this is certainly one of those big speed bumps you really don't want to be giving even your fans.&lt;br /&gt;&lt;br /&gt;Sure, it wouldn't hurt anywhere near so much if there wasn't an unresponsive IT department in the picture, making all DNS changes take hours of wasted time and days of elapsed time.&amp;nbsp; But at least if Google's information had been more open and accurate about the change of features, I could have ensured we weren't now in for a second round of delay.&lt;br /&gt;&lt;br /&gt;The lesson?&amp;nbsp; When writing documentation, &lt;i&gt;never assume you've correctly updated every place that needs updating&lt;/i&gt;.&amp;nbsp; (Hopefully you have updated everything, but don't &lt;i&gt;assume&lt;/i&gt; it.)&amp;nbsp; Include a note as to the change, so that a) people used to the old system can be less confused; and b) if any bits of doco slipped through the cracks, people will be able to figure out (with the aid of the change note) what information is current vs outdated.&lt;br /&gt;&lt;br /&gt;Thus saith the blogger.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6867013479746249007?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6867013479746249007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6867013479746249007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6867013479746249007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6867013479746249007'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2011/12/google-apps-cname-activation-here-be.html' title='Google Apps CNAME activation - here be more dragons'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-3808936308798746345</id><published>2011-11-02T22:50:00.000-07:00</published><updated>2011-11-02T23:00:54.938-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='open source'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='libraries'/><title type='text'>Best open-source .NET text file differencing library</title><content type='html'>After a fairly thorough search for open-source .NET libraries for text file (e.g. source code) differencing, I've concluded that there are only two serious contenders :&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://code.google.com/p/google-diff-match-patch/'&gt;google-diff-match-patch&lt;/a&gt;; and&lt;/li&gt;&lt;li&gt;&lt;a href='http://diffplex.codeplex.com/'&gt;DiffPlex&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Both look like they would meet my needs.&lt;br /&gt;&lt;br /&gt;DiffPlex is C# only, whereas google-diff-match-patch contains equivalent implementations in Java, Javascript, C++, Objective-C, and more, so if you like the idea of learning an API once and using it e.g. in iOS projects or in web browsers (Javascript) directly, google-diff-match-patch is for you.&lt;br /&gt;&lt;br /&gt;The DiffPlex API seems a little nicer if all you want is a simple diff.&lt;br /&gt;&lt;br /&gt;google-diff-match-patch supports - as its name suggests - producing and processing patch files - so if you need the extra features, google-diff-match-patch wins again.&lt;br /&gt;&lt;br /&gt;DiffPlex contains what appears to be a very nice &amp; simple API to drive diff viewers.  But the google-diff-match-patch does have some similar thing, even if the API is not as nice.&lt;br /&gt;&lt;br /&gt;Both support a line-by-line mode.&lt;br /&gt;&lt;br /&gt;google-diff-match-patch has a nice feature where it can simplify diffs down from "perfect" diffs to more semantically-meaningful diffs.  It calls this a "cleanup" operation, and depending on your needs, that could be a deciding feature.  My immediate needs are so simple that even cleanup isn't relevant, but if its relevant for you, google-diff-match-patch might be the go (unless I missed a similar feature in DiffPlex, but I'm pretty sure I didn't miss &lt;em&gt;that&lt;/em&gt; feature).&lt;br /&gt;&lt;br /&gt;In short, it seems both are suitable.  DiffPlex has a nicer API for the world of .NET (e.g. C#-style naming conventions used throughout) whilst google-diff-match-patch has more features.  For my needs - an open-source, native .NET differencing library - both libraries look very suitable and DiffPlex looks a little easier to learn and use (not that either are hard).  But I think in the end I'm going to start with google-diff-match-patch on account of the multiple platforms it supports with a uniform API, and the cleanup facility which whilst not relevant immediately is perfect for something I'm planning to do in the future...&lt;br /&gt;&lt;br /&gt;If you know of any other serious contenders, let me know, but I'm only interested in native .NET open-source libraries that can be downloaded and used without modification (so that excludes repurposing code in open-source diff viewers).  And I did review a few options on Code Project but nothing there compelled me to believe their performance would be any better than the two projects I shortlisted, whereas I expect that these two shortlisted projects will have much better ongoing support.&lt;br /&gt;&lt;br /&gt;Posted largely for my own future reference, but also to help other wandering developers.  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-3808936308798746345?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/3808936308798746345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=3808936308798746345' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3808936308798746345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3808936308798746345'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2011/11/best-open-source-net-text-file.html' title='Best open-source .NET text file differencing library'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8088364508341957287</id><published>2011-05-24T20:11:00.000-07:00</published><updated>2011-05-24T20:11:15.671-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><title type='text'>aspnet_merge unresolved assembly reference not alllowed in ASP.NET 4</title><content type='html'>Hopefully this'll save someone else some time.&lt;br /&gt;&lt;br /&gt;I have a moderately large VB.NET ASP.NET website, originally created in ASP.NET 2 and recently upgraded to ASP.NET 4.&lt;br /&gt;&lt;br /&gt;I recently built my own packaging scripts that use aspnet_compiler and aspnet_merge.&lt;br /&gt;&lt;br /&gt;I was careful to use the .NET Framework v4 version of aspnet_compiler.&lt;br /&gt;&lt;br /&gt;When running aspnet_merge on the precompiled website, I got a very strange error :&lt;br /&gt;&lt;blockquote&gt;Utility to merge precompiled ASP.NET assemblies. Version 3.5.30729.&lt;br /&gt;Copyright (c) Microsoft Corporation 2007. All rights reserved.&lt;br /&gt;&lt;br /&gt;aspnet_merge: error occurred: An error occurred when merging assemblies: Unresolved assembly reference not allowed: Microsoft.VisualBasic.&lt;/blockquote&gt;The problem was pretty obvious, but stumped me for probably an hour or so : I was using the wrong version of aspnet_merge.exe.&lt;br /&gt;&lt;br /&gt;&lt;a href='http://social.msdn.microsoft.com/Forums/en-US/netfxgeneralprerelease/thread/037c8fe7-1390-42ab-a251-e4810d754753'&gt;This&lt;/a&gt; page helped me find the correct version.  On my computer, that's in :&lt;br /&gt;&lt;br /&gt;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\aspnet_merge.exe&lt;br /&gt;&lt;br /&gt;HTH  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8088364508341957287?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8088364508341957287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8088364508341957287' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8088364508341957287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8088364508341957287'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2011/05/aspnetmerge-unresolved-assembly.html' title='aspnet_merge unresolved assembly reference not alllowed in ASP.NET 4'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-734214895264672917</id><published>2011-04-14T23:53:00.000-07:00</published><updated>2011-04-15T08:21:32.950-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bazaar'/><title type='text'>Bazaar repository bloat - rebase, merge, push, pull</title><content type='html'>&lt;strong&gt;UPDATE : Repository bloat (at least in the merge-then-merge-back scenario) can be solved very easily : "bzr pack --clean-obsolete-packs".  The content of this article is interesting in the things it examines, but somewhat outdated by this update.  Read at own risk...&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Bazaar is awesome.  I say that almost every time I talk about Bazaar.  I love it.&lt;br /&gt;&lt;br /&gt;However, there are some use cases where you can end up with repository bloat, completely unnecessarily.&lt;br /&gt;&lt;br /&gt;Repository bloat occurs when Bazaar decides - for whatever reason - to make a new version of an existing revision, and thereby duplicate data that was in the revision.&lt;br /&gt;&lt;br /&gt;So for example, you have a 5MB file and you add it to a branch, and then merge the branch with the trunk.  Trunk's repository size should increase by roughly 5MB, you say?  Well, &lt;em&gt;should&lt;/em&gt;, you're right, but depending on how you do it, you can actually end up with a 10MB increase instead.&lt;br /&gt;&lt;br /&gt;Repository bloat.&lt;br /&gt;&lt;br /&gt;So how do you avoid it?&lt;br /&gt;&lt;br /&gt;Well, I've noticed repository bloat in two main situations (although there are likely more).  Both situations involve the trunk and branch diverging - so if your workflow is such that the trunk and branch are always sync'ed before divergence happens (i.e. when there are only changes on one side or the other but not both), then repository bloat won't be a problem for you (but rare will be workflows where you can guarantee that!)&lt;br /&gt;&lt;br /&gt;Here are the two repository bloat scenarios I've noticed :&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1) rebase : your revisions get rewritten to your local repository.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;md trunk&lt;br /&gt;cd trunk&lt;br /&gt;bzr init&lt;br /&gt;echo Hi&gt;readme.txt&lt;br /&gt;bzr add&lt;br /&gt;bzr commit -m "trunk commit"&lt;br /&gt;cd..&lt;br /&gt;bzr branch --stacked trunk branch&lt;br /&gt;cd branch&lt;br /&gt;(put 5MB file called BigFile.dat in branch folder)&lt;br /&gt;bzr add&lt;br /&gt;bzr commit -m "Added BigFile.dat in branch"&lt;br /&gt;&lt;br /&gt;So far so good.  And if you rebase at this point, you're fine ('coz nothing will happen).&lt;br /&gt;&lt;br /&gt;But if we continue :&lt;br /&gt;&lt;br /&gt;cd ../trunk&lt;br /&gt;echo A change in trunk&gt;&gt;readme.txt&lt;br /&gt;bzr commit -m "Another trunk commit"&lt;br /&gt;cd ../branch&lt;br /&gt;bzr rebase&lt;br /&gt;&lt;br /&gt;... well, the rebase runs just fine, but if you check the size of the .bzr folder in the branch, it is around 10MB, not 5!&lt;br /&gt;&lt;br /&gt;Repository bloat!&lt;br /&gt;&lt;br /&gt;How to avoid repository bloat when rebasing?&lt;br /&gt;&lt;br /&gt;Well, the conslusion I've come to is : let the repository bloat, and merge or push to trunk, and then follow my instructions on purging stacked branches to remove the bloat.  (The bloat in rebase cases is only in the branch, not the trunk.  And fortunately, it seems that pushing the bloated repository to the trunk only pushes the new versions of the affected revisions instead of pushing both old and new versions - i.e. the bloat is fortunately not propagated back to the trunk in this case.)&lt;br /&gt;&lt;br /&gt;(Not using stacked branches?  Sorry, not my use case, so I haven't investigated further and thus can't tell you for sure what will work - although if you get really really desperate you can make a new branch --no-tree and then delete the .bzr folder in your existing branch and replace it with the .bzr folder in the new branch.  Again - only do that at a point where trunk and branch are in-sync.)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2) merge to branch then merge to trunk&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is a pretty standard operation if you've been working on your branch for a while and the trunk has changed in the meantime.&lt;br /&gt;&lt;br /&gt;You can't pull the trunk changes into the branch.  Once the two are out-of-sync, you're forced to use merge or rebase.  The rebase scenario is covered above, and results in duplication of data in branch revisions from the point of divergence onwards.&lt;br /&gt;&lt;br /&gt;The merge scenario is what we're covering here.  Its repository bloat characteristics are more interesting.  Whereas rebase results in duplication of data in BRANCH revisions from the point of divergence onwards, merge can result in duplication of data in TRUNK revisions from the point of divergence onwards, assuming that you proceed to merge branch back into trunk.  (If you PUSH branch back into trunk, I suspect (but haven't tested) that you'll get away without repository bloat - but then you lose the trunk's unique perspective on the change history - i.e. your log and qlog are thereafter from the branch's perspective instead of from the trunk's perspective.)&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;md trunk&lt;br /&gt;cd trunk&lt;br /&gt;bzr init&lt;br /&gt;echo Hi&gt;test.txt&lt;br /&gt;(add 5MB file into trunk folder)&lt;br /&gt;bzr add&lt;br /&gt;bzr commit -m "Initial commit in trunk"&lt;br /&gt;cd..&lt;br /&gt;bzr branch --stacked trunk branch&lt;br /&gt;cd branch&lt;br /&gt;echo bla&gt;test2.txt&lt;br /&gt;bzr add&lt;br /&gt;bzr commit -m "First commit in branch"&lt;br /&gt;cd ..&lt;br /&gt;cd trunk&lt;br /&gt;(replace 5MB file in trunk folder with a different 5MB file of same name)&lt;br /&gt;bzr commit -m "Modified BigFile.dat"&lt;br /&gt;cd ..&lt;br /&gt;cd branch&lt;br /&gt;&lt;br /&gt;OK - so far so good - but trunk and branch have diverged and now we're at the point we want to make them converge.  Normally we might do :&lt;br /&gt;&lt;br /&gt;bzr merge ../trunk&lt;br /&gt;bzr commit -m "Merged trunk changes into branch"&lt;br /&gt;cd ..&lt;br /&gt;cd trunk&lt;br /&gt;bzr merge ../branch&lt;br /&gt;bzr commit -m "Merged branch into trunk"&lt;br /&gt;&lt;br /&gt;... but if you do that, you'll get our lovely friend Repository Bloat(TM)!&lt;br /&gt;&lt;br /&gt;Why?&lt;br /&gt;&lt;br /&gt;Well, it seems that merging the 5MB file's modification revision in from trunk to branch, which requires a commit, results in that 5MB file's data ending up in a second revision, and when we merge back into trunk, that second revision ends up in the trunk's repository.  (Interestingly, does not happen if the file was &lt;em&gt;newly created&lt;/em&gt; in the trunk - just if it was already known to the branch and was &lt;em&gt;updated&lt;/em&gt; in the trunk.)&lt;br /&gt;&lt;br /&gt;10MB repository growth for a 5MB file.  Baaaaad.&lt;br /&gt;&lt;br /&gt;(To emphasize : the final trunk repository size is &lt;strong&gt;15MB&lt;/strong&gt; : 5MB after initial commit of the 5MB file, then a further 5MB totalling 10MB after second commit to trunk, and finally a third 5MB totalling 15MB after merging in from branch and committing again.)&lt;br /&gt;&lt;br /&gt;We saw how to get around it with the rebase bloat problem.  How to get around it with the merge bloat problem?&lt;br /&gt;&lt;br /&gt;One way is to avoid the merge-then-merge-back entirely.  If trunk has changed and you can't pull the changes into the branch because trunk and branch have diverged, then rebase instead.  You might/will end up with branch repository bloat, but I cover how to deal with that in the preceding section on repository bloat caused by the rebase operation.&lt;br /&gt;&lt;br /&gt;All a bit tedious?  Perhaps.  But easily scriptable.&lt;br /&gt;&lt;br /&gt;Of course, if your workflow relies on the merge process, you might just have to accept the bloat.  Not ideal.  You might be able to avoid the bloat by using the merge -c option when merging back into trunk, to "cherry-pick" only the branch revisions that are not themselves merge-from-trunk commits.  And there are yet more desperate approaches one could take if needed - e.g. export branch changes to a patch set, delete branch, recreate it from trunk and apply patches!!!  Well y'know, it would probably work.......&lt;br /&gt;&lt;br /&gt;And maybe I need my head checked, but even with a few little problems like this, I still absolutely love Bazaar.  (Yes - relatively little.  In practice, does it matter if your repository is twice the size it needs to be?  Sometimes yes, usually no.  For me, it's a little more critical than for others due to certain peculiar circumstances, and hence my investigations in how to avoid/resolve repository bloat.)  Thanks for stopping by!  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-734214895264672917?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/734214895264672917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=734214895264672917' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/734214895264672917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/734214895264672917'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2011/04/bazaar-repository-bloat-rebase-merge.html' title='Bazaar repository bloat - rebase, merge, push, pull'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6653333502411187517</id><published>2011-04-14T23:21:00.000-07:00</published><updated>2011-04-15T08:20:36.012-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bazaar'/><title type='text'>Purging stacked branches in Bazaar</title><content type='html'>Stacked branches are awesome!&lt;br /&gt;&lt;br /&gt;Shared repositories go so far, but don't work so well if the parent and child branches are far away from each other in the file system (nor if they are on different volumes), and shared repositories have the weakness that if you create a revision, it lives on forever, even if you later delete the branch associated with that revision.  (You can't actually get the revision back, not by any way I've found &lt;em&gt;(UPDATE : "bzr heads --all" looks like it lets you find "lost" revisions.)&lt;/em&gt;, but the shared repository's size never goes down - it just keeps accruing more and more data, never letting any of it go.  &lt;em&gt;(UPDATE : I'm no longer entirely sure when the repository's size changes - "bzr pack --clean-obsolete-packs" does wonders)&lt;/em&gt;)&lt;br /&gt;&lt;br /&gt;In contrast, stacked branches can be used at any time both the parent and child branch are simultaneously accessible (even if they're on different hard disks or even one on a URL), and best of all, if you make an experimental branch and decide to kill it, bam! - its history is gone forever and your trunk repository isn't forever bloated by the revisions you decided to nuke.&lt;br /&gt;&lt;br /&gt;And they're extremely useful if you want the same library to be in multiple apps (in different Bazaar repositories) and want to be able to edit the source code in each copy of the library independently but have them all closely associated.&lt;br /&gt;&lt;br /&gt;And did I mention they save a lot of storage space?&lt;br /&gt;&lt;br /&gt;But thence cometh the problem : stacked branches &lt;em&gt;start out&lt;/em&gt; tiny, because they aren't carrying the five decades of history that the trunk contains, but after that they grow.&lt;br /&gt;&lt;br /&gt;And grow.&lt;br /&gt;&lt;br /&gt;What if you just want the stacked branch repositories to stay nice and trim, like they were when you made them?&lt;br /&gt;&lt;br /&gt;There doesn't seem to be any built-in feature in Bazaar to do that.&lt;br /&gt;&lt;br /&gt;push, pull, merge, do whatever you want - the stacked branch's repository only grows.&lt;br /&gt;&lt;br /&gt;So we resort to a little bit of - very effective - skullduggery.&lt;br /&gt;&lt;br /&gt;FIRST UP, ENSURE YOU TRY THIS EXPERIMENTALLY FIRST.  It worked for me, but might destroy you and your world and your company's beautiful source code and get you fired.  THIS USES UNDOCUMENTED TRICKS.  So it could stop working when new versions of Bazaar roll out.  I have and accept no responsibility for what happens to you if you try this yourself!&lt;br /&gt;&lt;br /&gt;1) Purging the stacked branch history obviously needs to be done at times that the stacked branch is in-sync with the trunk.  So make sure you've merged or pushed the branch into the trunk.&lt;br /&gt;&lt;br /&gt;2) In the branch, delete all files in these two folders :&lt;br /&gt;.bzr\repository\indices&lt;br /&gt;.bzr\repository\packs&lt;br /&gt;&lt;br /&gt;3) Still in the branch, locate this file :&lt;br /&gt;.bzr\repository\pack-names&lt;br /&gt;... and change its content to the following five lines :&lt;br /&gt;&lt;br /&gt;B+Tree Graph Index 2&lt;br /&gt;node_ref_lists=0&lt;br /&gt;key_elements=1&lt;br /&gt;len=0&lt;br /&gt;row_lengths=&lt;br /&gt;&lt;br /&gt;Voila!  Do a bzr status or bzr log and the history is all there - its just now coming from the stacked-on branch like you wanted all along.  You have successfully purged the stacked branch's history.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6653333502411187517?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6653333502411187517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6653333502411187517' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6653333502411187517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6653333502411187517'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2011/04/purging-stacked-branches-in-bazaar.html' title='Purging stacked branches in Bazaar'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-3975091987565694149</id><published>2010-12-01T22:46:00.000-08:00</published><updated>2010-12-01T22:46:49.445-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='virtual hard disks'/><title type='text'>WinMount writes VDI files (VirtualBox virtual hard disk files)</title><content type='html'>I was having extraordinary difficulty copying a 4GB file from my host to a virtual machine.&lt;br /&gt;&lt;br /&gt;VirtualBox shared folders weren't working (client add-ons unable to be installed).&lt;br /&gt;&lt;br /&gt;Windows file sharing, which usually did the trick, had frozen due to my host getting its nappy in a knot, and rebooting wasn't a suitable option.&lt;br /&gt;&lt;br /&gt;I had IIS (a web and FTP server) on my host, and tried sharing the file through that, only to discover that just over 2GB into the transfer, the transfer froze - obviously a bug with something somewhere using a 32-bit signed integer and dying at the moment the transfer reached the highest number that can be represented in 31 unsigned bits.&lt;br /&gt;&lt;br /&gt;I tried copying the file onto USB external hard disk, then mapping the external hard disk to the virtual machine via VirtualBox's USB mapping, but that too caused much grief and many hangs (not complete system hangs, but VirtualBox hangs).&lt;br /&gt;&lt;br /&gt;I did finally, FINALLY, manage to get it to work.&lt;br /&gt;&lt;br /&gt;I created a virtual hard disk using the VirtualBox media manager.  I happened to use an auto-expand disk so that it would only use as much of my host's storage as required.&lt;br /&gt;&lt;br /&gt;I then tried a trial version of the commercial WinMount program.  It happily mounted my auto-expanding VDI virtual hard disk, mapped it to a drive letter, and I was able to copy my huge file onto the virtual hard disk.&lt;br /&gt;&lt;br /&gt;Then I exited WinMount, mapped the virtual hard disk as a secondary disk to the virtual machine I was trying to transfer the file to, rebooted the virtual machine, and voila, I was able to copy the file from the temporary second virtual hard disk onto the virtual hard disk I wanted it to be on.&lt;br /&gt;&lt;br /&gt;VERY convoluted, but we got there.&lt;br /&gt;&lt;br /&gt;One weird thing : Norton "security advisor" (or whatever it's called) warned me that the WinMount website is a known source of viruses and/or trojan horses.  So, I dunno, my computer might be laced with baddies now.  But even though Norton warned about the website, it didn't complain about the WinMount program itself.&lt;br /&gt;&lt;br /&gt;In short, if you're wanting to mount a virtual hard disk for read/write access in Windows - &lt;em&gt;especially&lt;/em&gt; if it's an auto-expand virtual hard disk - WinMount commercial edition seems to do a very nice job.  And it was the only tool I found that even &lt;em&gt;claims&lt;/em&gt; to support writing to auto-expand virtual hard disks.  So it seems the authors of this tool have managed to accomplish something pretty special.&lt;br /&gt;&lt;br /&gt;But of course, don't use it in read+write mode on a virtual hard disk you can't afford to lose, just in case it busts it!  i.e. if the virtual hard disk is dear to you, then make a backup before trying ANY 3rd-party tool that purports to provide read+write access!  Or so I advise.  :o)&lt;br /&gt;&lt;br /&gt;Thanks &lt;a href='http://www.winmount.com/'&gt;WinMount&lt;/a&gt; - I'm puzzled by the virus/trojan warnings, and your on-screen instructions are slightly Chinglishy, but aside from that, your product seems to be very good indeed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-3975091987565694149?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/3975091987565694149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=3975091987565694149' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3975091987565694149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3975091987565694149'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/12/winmount-writes-vdi-files-virtualbox.html' title='WinMount writes VDI files (VirtualBox virtual hard disk files)'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-4264088693289737791</id><published>2010-06-09T21:26:00.000-07:00</published><updated>2010-06-09T21:38:15.540-07:00</updated><title type='text'>Telstra NextG USB modem not so good as a backup device</title><content type='html'>I thought a Telstra NextG wireless broadband (internet) USB modem would be perfect for those occasional trips out to the country.&lt;br /&gt;&lt;br /&gt;Keep it in yer bag, recharge at the point of need.&lt;br /&gt;&lt;br /&gt;So it sat around waiting to be needed.&lt;br /&gt;&lt;br /&gt;I needed it just recently.&lt;br /&gt;&lt;br /&gt;But it didn't work.&lt;br /&gt;&lt;br /&gt;I phone Telstra.&lt;br /&gt;&lt;br /&gt;"The USIM has been deactivated. &amp;nbsp;I'll transfer you to the activations and reactivations department so they can reactivate it for you."&lt;br /&gt;&lt;br /&gt;But the lady in the activations + reactivations department gave me the following bad news :&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A Telstra NextG data SIM expires permanently after just ONE MONTH without a current data allowance.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I don't recall reading THAT in the promotional material.&lt;br /&gt;&lt;br /&gt;I expected to be able to go a month here, a few months there, without using it.&lt;br /&gt;&lt;br /&gt;Maybe a permanent expiry after six months of no use would make sense.&lt;br /&gt;&lt;br /&gt;But just ONE MONTH?&lt;br /&gt;&lt;br /&gt;This means that if you want to use the Telstra NextG USB modem, you have to be buying a new data pack every other month at the very least, &lt;i&gt;even if you're not using the service&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;I thought the point of "prepaid" was that you could control exactly what you spent and when!&lt;br /&gt;&lt;br /&gt;Apparently I was wrong.&lt;br /&gt;&lt;br /&gt;Now, it's not all bad, but it kinda gets worse in one sense...&lt;br /&gt;&lt;br /&gt;The lady helpfully informed me that I can just go to a retail outlet and buy another SIM for only $2, then recharge it with whatever denomination I want.&lt;br /&gt;&lt;br /&gt;Well, that's nice in terms of getting up &amp;amp; running again &lt;i&gt;now&lt;/i&gt;, but that's a lot of hassle if I'm intending to recharge just at the point of need.&lt;br /&gt;&lt;br /&gt;I mean, let's keep this in focus : I am willing to pay $20 for a recharge (the minimum recharge amount) for that odd occasion I'm out in the country and suddenly need internet access to provide tech support.&lt;br /&gt;&lt;br /&gt;I won't use anywhere near the data allowance on the $20 recharge, I'll typically only use it for tens of minutes, and then it will sit unused for the remainder of its 30 day expiry period and expire mostly unused.&lt;br /&gt;&lt;br /&gt;In other words, Telstra's profit margin on my occasional $20 recharge would be STUPENDOUS, and I would still feel like I'm getting value, for the sake of being able to provide tech support on a moment's notice at those critical moments.&lt;br /&gt;&lt;br /&gt;But now I'm being told that actually, I need to keep on feedin' the card with recharges, whether I need them or not.&lt;br /&gt;&lt;br /&gt;The value proposition of the Telstra NextG device is now plummeting, because its minimum cost has suddenly gone from $99 (the purchase price), to $99 + $120 per year. &amp;nbsp;Not a huge amount, but that's assuming I accept the major hassle of timing my recharges perfectly, and never muck up and have to go through the hassle of getting yet &lt;i&gt;another&lt;/i&gt;&amp;nbsp;new SIM. &amp;nbsp;If I take the low-brain-power option (automatic monthly $20 recharges), then we're suddenly talking about $240 per year. &amp;nbsp;&lt;i&gt;Minimum&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;As a backup device that would only cost money when needed, and the point of need would justify the cost, it was a valuable proposition.&lt;br /&gt;&lt;br /&gt;But a &lt;i&gt;minimum&lt;/i&gt;&amp;nbsp;of $240 per year, whether I use it or not?&lt;br /&gt;&lt;br /&gt;Sorry, I think I'm going to explore alternatives.&lt;br /&gt;&lt;br /&gt;AND I don't think this was adequately disclosed at the point of sale.&lt;br /&gt;&lt;br /&gt;The device is not fit for the purpose for which I purchased it, yet I purchased it in good faith based on the representations of and impressions made by the sales and marketing material.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;On another note, I was ASTOUNDED by the Telstra phone service! &amp;nbsp;I'm used to SHOCKING service. &amp;nbsp;But I received commendable service.&lt;br /&gt;&lt;br /&gt;For starters, I rang, and the phone was answered by a HUMAN! &amp;nbsp;This has never happened before!&lt;br /&gt;&lt;br /&gt;The human directed my call skillfully.&lt;br /&gt;&lt;br /&gt;I waited only a few minutes at most.&lt;br /&gt;&lt;br /&gt;An operator apologised for the inconvenience of my NextG device expiring (I didn't make a big deal about it to them, even though it is a big deal, so the fact that they apologised without prompting is nice), and one even said "thanks for your patience with Telstra".&lt;br /&gt;&lt;br /&gt;"Thanks for your patience with Telstra"!!! &amp;nbsp;What is the world coming to! &amp;nbsp;A big Telco that understands that &lt;i&gt;we&lt;/i&gt;, its customers, are &lt;i&gt;humans&lt;/i&gt;, and that they have required us to exercise patience! &amp;nbsp;It's like a great big warm heart has been mystically transplanted into what once was the worst of customer service offenders in the country (or at least, the most notable).&lt;br /&gt;&lt;br /&gt;So, I don't know what's happening at Telstra, but something good is happening.&lt;br /&gt;&lt;br /&gt;I'm getting answers when I call.&lt;br /&gt;&lt;br /&gt;I'm speaking with people I don't have too much trouble understanding.&lt;br /&gt;&lt;br /&gt;The list goes on.&lt;br /&gt;&lt;br /&gt;It'll take a while, but if they keep up like this, people might even begin to think highly of Telstra.&lt;br /&gt;&lt;br /&gt;Like I said, it'll take a while...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-4264088693289737791?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/4264088693289737791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=4264088693289737791' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4264088693289737791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4264088693289737791'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/06/telstra-nextg-usb-modem-not-so-good-as.html' title='Telstra NextG USB modem not so good as a backup device'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-5988079680855180007</id><published>2010-04-12T21:32:00.000-07:00</published><updated>2010-04-12T21:32:03.554-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><title type='text'>SQL Server refusing to start</title><content type='html'>Here's a weird one that boggled my brain for a long ol' time.&lt;br /&gt;&lt;br /&gt;SQL Server on my development laptop was refusing to start.&lt;br /&gt;&lt;br /&gt;I hadn't used it for months, but didn't think I'd changed anything that could affect it.&lt;br /&gt;&lt;br /&gt;The error message was plain ol' weird :&lt;br /&gt;&lt;br /&gt;"Windows could not start the SQL Server (SQLEXPRESS) on Local Computer.  For more information, review the System Event Log.  If this is a non-Microsoft service, contact the service vendor, and refer to service-specific error code 3417."&lt;br /&gt;&lt;br /&gt;Well, that wasn't weird, but the associated Event Log entry sure was :&lt;br /&gt;&lt;br /&gt;"The SQL Server (SQLEXPRESS) service terminated with service-specific error WARNING: You have until SQL Server (SQLEXPRESS) to logoff. If you have not logged off at this time, your session will be disconnected, and any open files or devices you have open may lose data."&lt;br /&gt;&lt;br /&gt;Ah - aha?  What's all this log off bizzo?&lt;br /&gt;&lt;br /&gt;No makey sensey.&lt;br /&gt;&lt;br /&gt;Searching the web found only one other website mentioning the problem.  One, in the entire world.  And their solution was basically to uninstall SQL Server, delete the remnants of the installation folder, and reinstall.&lt;br /&gt;&lt;br /&gt;Well, thanks be to God, the answer dawned on me :&lt;br /&gt;&lt;br /&gt;To save space on my SSD (where speed was brilliant but size was cramped), I had compressed all my program files.&lt;br /&gt;&lt;br /&gt;That works a treat - program files are almost entirely read-only, so both with hard disks and with SSDs of all varieties, compressing program files usually brings a speed improvement, and certainly frees up a lot of disk space.&lt;br /&gt;&lt;br /&gt;BUT, I suddenly recalled that SQL Server stores its "master databases" deep inside the Program Files.  By itself, that's not a problem.  But I also recalled from years ago that SQL Server uses a special type of low-level file system access that is incompatible with NTFS compression.  The disk access used by SQL Server is designed to optimise database page caching for uncompressed data files.  But it simply cannot work with NTFS-compressed data files.  Full stop.  (And there are ways to trick it into working, but believe you me, there are substantial write performance implications if you try.)&lt;br /&gt;&lt;br /&gt;So I dug into the SQL Server installation folder, and uncompressed the *.mdf and *.ldf files in the Data folder, and all was merriment once more.&lt;br /&gt;&lt;br /&gt;For the odd sailor out there cutting close to the wind like me, this might prove helpful.  Enjoy!  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-5988079680855180007?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/5988079680855180007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=5988079680855180007' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5988079680855180007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5988079680855180007'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/04/sql-server-refusing-to-start.html' title='SQL Server refusing to start'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-197783272620601460</id><published>2010-04-11T13:53:00.000-07:00</published><updated>2010-04-11T13:59:07.366-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows 7'/><category scheme='http://www.blogger.com/atom/ns#' term='sleep mode'/><title type='text'>The case of the waking laptop</title><content type='html'>My Sony Vaio Z - ah... bliss!  This is a BRILLIANT laptop.&lt;br /&gt;&lt;br /&gt;But it often wakes around 2am.&lt;br /&gt;&lt;br /&gt;When on battery, it runs its battery down and starts hibernating.&lt;br /&gt;&lt;br /&gt;But when its in my bag, the extra drain of running the fan at full speed in the bag (due to the heat in a closed bag) whilst it runs needlessly, means that the hibernation battery threshhold is not sufficient for a full hibernation to occur.  (8GB of RAM takes a while to hibernate.)&lt;br /&gt;&lt;br /&gt;Ergo, the battery drains, and I lose my software state and any unsaved work.&lt;br /&gt;&lt;br /&gt;VERY frustrating, especially when it's supposedly the 21st century and all.&lt;br /&gt;&lt;br /&gt;Windows 7 Ultimate 64-bit.&lt;br /&gt;&lt;br /&gt;I thought it must be the fault of a Sony driver or something.&lt;br /&gt;&lt;br /&gt;But previous attempts to resolve the problem have failed.&lt;br /&gt;&lt;br /&gt;I've had the laptop nearly four months now, and this has been my major issue with it.&lt;br /&gt;&lt;br /&gt;(Lots of people are mentioning very similar problems, and other websites do give answers that work for others, but didn't solve the problem in my case.)&lt;br /&gt;&lt;br /&gt;I think I've found the solution at last :&lt;br /&gt;&lt;br /&gt;Open : Task Scheduler&lt;br /&gt;&lt;br /&gt;Expand : Task Scheduler Library&lt;br /&gt;&lt;br /&gt;Expand : Microsoft&lt;br /&gt;&lt;br /&gt;Expand : Windows&lt;br /&gt;&lt;br /&gt;Select in the LHS tree : Media Center&lt;br /&gt;&lt;br /&gt;Select in the RHS list : mcupdate_scheduled&lt;br /&gt;&lt;br /&gt;Note that it defaults to 2am daily.  2am daily!&lt;br /&gt;&lt;br /&gt;Right-click "mcupdate_scheduled" and select "Properties".&lt;br /&gt;&lt;br /&gt;Go to the fourth tab, and find the checkbox named "Wake the computer to run this task".&lt;br /&gt;&lt;br /&gt;It is checked.&lt;br /&gt;&lt;br /&gt;Yes, can you believe it, checked.&lt;br /&gt;&lt;br /&gt;This particular scheduled task just checks for software updates.&lt;br /&gt;&lt;br /&gt;That's not very critical.&lt;br /&gt;&lt;br /&gt;Some numbskull at Microsoft decided that Media Center software updates are so critical that your computer should be woken from sleep at 2am, EVERY DAY!!!&lt;br /&gt;&lt;br /&gt;This explains another problem.  Whilst I have the laptop docked, I get woken in the middle of the night with my screen turning on, as a result of the laptop turning on.  That'll be why.&lt;br /&gt;&lt;br /&gt;So hopefully I'll have fewer interrupted sleeps.&lt;br /&gt;&lt;br /&gt;Anyhows, this particular scheduled task is set to only start when the computer is plugged into power - which is the case when it's docked and I get the laptop turning on and the screen turning on and waking me in the middle of the night - but it doesn't explain why it wakes at around 2am on battery.&lt;br /&gt;&lt;br /&gt;... or does it?&lt;br /&gt;&lt;br /&gt;Someone else commenting on a similar problem said they noticed that the Windows 7 final release had a bug related specifically to the "Balanced" power profile.  Somehow or other, the bug didn't seem to affect the "Performance" power profile.  And I happen to use the "Balanced" power profile nearly all the time.&lt;br /&gt;&lt;br /&gt;So here's my suspicion : the stupid Media Center scheduled task was causing the laptop to wake at 2am daily, and even though the settings said it should only happen when plugged into power, I suspect a bug somewhere in the Balanced power profile resulted in this scheduled task waking the computer even when it was on battery.&lt;br /&gt;&lt;br /&gt;But of course "the proof is in the pudding".  I definitely have solved at least one problem, but whether it will prove to have solved the main problem, we're yet to see...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-197783272620601460?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/197783272620601460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=197783272620601460' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/197783272620601460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/197783272620601460'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/04/case-of-waking-laptop.html' title='The case of the waking laptop'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-9131109702672642571</id><published>2010-04-07T07:43:00.000-07:00</published><updated>2010-04-07T08:21:39.081-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='buy-it-now'/><category scheme='http://www.blogger.com/atom/ns#' term='ebay iPhone app'/><title type='text'>ebay iPhone buy-it-now issue</title><content type='html'>Are we the only ones in the world affected?&lt;br /&gt;&lt;br /&gt;My wife was on her iPhone using the ebay app, scrolling through a listing, and all of a sudden she was told she had won the item via buy-it-now.&lt;br /&gt;&lt;br /&gt;She did not see any buy-it-now confirmation request either.&lt;br /&gt;&lt;br /&gt;It just happened.&lt;br /&gt;&lt;br /&gt;The iPhone's design inherently means that scrolling requires touching parts of the page you are scrolling through, and from time to time this must inevitably mean the iPhone mistakes an attempted scroll for a click.&lt;br /&gt;&lt;br /&gt;So designing an iPhone app in such manner that an attempted scroll can instantly become a multi-hundred-dollar buying commitment, is ridiculous.&lt;br /&gt;&lt;br /&gt;I also suggest it is illegal - that any attempt to enforce the purchase at law would be void, due to the absence of a contract.  (There was clearly no intention to enter into a contract, nor to represent an intention to enter into a contract - it was a case of poor app design.)&lt;br /&gt;&lt;br /&gt;Now, I don't know ('coz I always use ebay in a browser on a larger computer), but it might be that ebay will turn around and claim that they always present a confirmation request for buy-it-now on the iPhone.  For sure I cannot find any option to enable or disable such confirmations in the app's settings (nor even in my account settings when I log in using a browser - but the account settings are not very intuitive to me, so there is a chance I missed the relevant setting).&lt;br /&gt;&lt;br /&gt;But if the ebay app DID present a confirmation request, it was deemed accepted and dismissed so quickly - probably in the same swipe that triggered the "buy it now" button in the first place - that my wife saw nothing.&lt;br /&gt;&lt;br /&gt;One moment scrolling.&lt;br /&gt;&lt;br /&gt;The next moment on the hook for hundreds of dollars for a product she was just investigating.&lt;br /&gt;&lt;br /&gt;If ebay does not ask for confirmations for "buy it now" on the iPhone, then they are negligent.&lt;br /&gt;&lt;br /&gt;If ebay DOES ask for confirmations for "buy it now" on the iPhone, then they are negligent once again by implementing the confirmation step in such manner as it can be so easily dismissed without even being seen.  They should e.g. have it appear for at least a second with buttons disabled before enabling the buttons.&lt;br /&gt;&lt;br /&gt;But in my attempts to find others with the same problem, and how they resolved it, my Google searching turned up nada, zip, zero.  Are we the only people on the planet who have hit this snag?&lt;br /&gt;&lt;br /&gt;I Googled for things like "ebay iPhone buy-it-now accident", "ebay buy-it-now mistake", and other combinations of words, but no, I'm not finding anyone reporting this particular problem.  And of course the ebay help was useless on the topic.&lt;br /&gt;&lt;br /&gt;Come to think of it, ebay and PayPal are bedfellows, and we had a run in with PayPal's incompetence a few years ago - still partially unresolved despite PayPal's repeated claims that they have completely remedied the problem.&lt;br /&gt;&lt;br /&gt;So I guess it shouldn't surprise me at all if ebay too proves worse than useless in resolving the issue.&lt;br /&gt;&lt;br /&gt;There is an ebay help article on canceling a sale for sellers who find themselves unable to complete the transaction, but nothing it seems for buyers.&lt;br /&gt;&lt;br /&gt;And no mention of the possibility of unintentional buy-it-now activation, anywhere in the help (yet surely that must frequently occur).&lt;br /&gt;&lt;br /&gt;And the "dispute resolution center" gives no useful options at least for the time being - it says we must wait 10 days before even contacting the dispute resolution center!&lt;br /&gt;&lt;br /&gt;We've contacted the seller, explained the situation, and I even offered to cover his lost listing fees.&lt;br /&gt;&lt;br /&gt;So now we're in a situation where, depending on the good graces of the seller, we might :&lt;br /&gt;&lt;br /&gt;a) end up with merely a truckload of wasted time.  Yeah, thanks ebay for facilitating that.&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;b) end up with even a bit more wasted time trying to pay whatever few dollars it turns out to be in compensation (when we were not at fault in the first place) to the seller who is as much a victim in the circumstances as we are - but we don't want ebay's negligence to spiral on and affect others, so we're willing to cover the lost listing fees, even though it is ebay's fault.&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;c) end up with a strong negative feedback with no good opportunity to defend ourselves (so much for due process) when we do very few ebay transactions, have fabulous feedback so far, and thus one strong negative would be a substantial (and unwarranted) mar on our ebay reputation.&lt;br /&gt;&lt;br /&gt;So, we'll see how it turns out, but based on my interactions with PayPal, I'm doubting ebay will have any conscience in this regard.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-9131109702672642571?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/9131109702672642571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=9131109702672642571' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9131109702672642571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9131109702672642571'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/04/ebay-iphone-buy-it-now-issue.html' title='ebay iPhone buy-it-now issue'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-4768258622794016742</id><published>2010-03-31T09:41:00.000-07:00</published><updated>2010-03-31T09:45:09.535-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><category scheme='http://www.blogger.com/atom/ns#' term='GPS'/><title type='text'>You gotta turn, bro!  iPhone hip GPS</title><content type='html'>The iPhone's built-in GPS (via Google Maps) is very helpful.  Not perfect, but definitely very helpful.&lt;br /&gt;&lt;br /&gt;So we use it a lot.&lt;br /&gt;&lt;br /&gt;It pulled a fast one on us this morning though, causing me much amusement.&lt;br /&gt;&lt;br /&gt;"Hang a right".  Are you serious?  The iPhone - so well spoken - now speaks hip?&lt;br /&gt;&lt;br /&gt;"Keep goin' on ..."  Goin'?  Golly goodness!  It's turned Texan!  :o)&lt;br /&gt;&lt;br /&gt;Or this one :&lt;br /&gt;&lt;br /&gt;"ya gotta take the turn off onta ..."&lt;br /&gt;&lt;br /&gt;Holey moley!  My iPhone has truly become trendy!  I don't mean it's trendy to have an iPhone, I mean the iPhone itself has trendiness of its own!!!  :o)&lt;br /&gt;&lt;br /&gt;So, kudos to whoever in Google or Apple gave me this amusement this morning - well done.  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-4768258622794016742?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/4768258622794016742/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=4768258622794016742' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4768258622794016742'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4768258622794016742'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/03/you-gotta-turn-bro-iphone-hip-gps.html' title='You gotta turn, bro!  iPhone hip GPS'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8006155811872465673</id><published>2010-02-18T19:03:00.000-08:00</published><updated>2010-02-18T19:10:47.972-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VoIP'/><title type='text'>Engin voicebox (Sipura SPA 3102) sharing WiFi via LAN cable to Windows 7 laptop</title><content type='html'>My laptop has wireless and LAN.  I only need the wireless.&lt;br /&gt;&lt;br /&gt;My Engin 3102 voicebox (a re-badged Sipura SPA something-or-other) has LAN, but not wireless.&lt;br /&gt;&lt;br /&gt;What if I want to run my VoIP over wireless?&lt;br /&gt;&lt;br /&gt;OK, ok, if you can, it's simplest to just plug the voicebox directly into your broadband router.&lt;br /&gt;&lt;br /&gt;But what if, for whatever reason, you can't, or don't want to?&lt;br /&gt;&lt;br /&gt;Turns out, it is possible to plug the voicebox into the laptop via the LAN port, and have the voicebox piggy-back on the laptop's WiFi connection.&lt;br /&gt;&lt;br /&gt;You beauty!&lt;br /&gt;&lt;br /&gt;Apparently in Windows XP you can do it through Internet Connection Sharing.&lt;br /&gt;&lt;br /&gt;I have Windows 7 Ultimate, and whilst I enabled Internet Connection Sharing, I never managed to get the voicebox to work through the laptop that way.&lt;br /&gt;&lt;br /&gt;After more digging, I discovered that &lt;em&gt;bridging network connections&lt;/em&gt; was the trick I needed.&lt;br /&gt;&lt;br /&gt;Open Control Panel, go to Network And Sharing Center, then on the left-hand-side, choose the "Change adapter settings" option.&lt;br /&gt;&lt;br /&gt;This will list all of your network adapters, including your LAN and WiFi adapters.&lt;br /&gt;&lt;br /&gt;Select both (click on one, then ctrl-click the other), then right-click on either of the selected two and a menu gives an option to bridge the adapters.&lt;br /&gt;&lt;br /&gt;Voila!  It was that easy!&lt;br /&gt;&lt;br /&gt;However, apparently if you have previously enabled Internet Connection Sharing, you'll need to disable it first - apparently it is incompatible with bridged network adapters.&lt;br /&gt;&lt;br /&gt;So now I can have my voicebox and phone handset right near my laptop, up the other end of the house, far away from the router and without running cables through the house.&lt;br /&gt;&lt;br /&gt;Nice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8006155811872465673?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8006155811872465673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8006155811872465673' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8006155811872465673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8006155811872465673'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/02/engin-voicebox-sipura-spa-3102-via-lan.html' title='Engin voicebox (Sipura SPA 3102) sharing WiFi via LAN cable to Windows 7 laptop'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7694191271448931948</id><published>2010-02-18T14:47:00.000-08:00</published><updated>2010-02-18T14:49:26.180-08:00</updated><title type='text'>What's the (Google) Buzz?</title><content type='html'>What's the buzz with the Buzz?  Buzz off, Buzz, I'm too busy!&lt;br /&gt;&lt;br /&gt;OK, I grant it's cool how it pulls in data from so many sources.  But still, what, am I supposed to click in to the Buzz several times a day, and scroll through a long list of buzzes, looking for ones that have been updated?&lt;br /&gt;&lt;br /&gt;No thanks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7694191271448931948?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7694191271448931948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7694191271448931948' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7694191271448931948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7694191271448931948'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/02/whats-google-buzz.html' title='What&apos;s the (Google) Buzz?'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-215181338216002999</id><published>2010-02-07T17:04:00.000-08:00</published><updated>2010-02-07T17:07:39.542-08:00</updated><title type='text'>Secure data removal when disposing of a PC</title><content type='html'>So my laptop (er, &lt;em&gt;craptop&lt;/em&gt;) Toshiba Tecra A6 is at end-of-life, and I'm getting rid of it.&lt;br /&gt;&lt;br /&gt;Of course, the hard disk is laden with commercial-in-confidence data, so what do I do?&lt;br /&gt;&lt;br /&gt;Short answer : &lt;a href='http://eraser.heidi.ie/'&gt;Eraser&lt;/a&gt;!  Open-source, and it provides well over a dozen secure data removal options, including deleting specific files, 'wiping' disk free space, etc.&lt;br /&gt;&lt;br /&gt;How did I use?  I deleted all my files off the laptop, created a new Administrator user account and deleted my old user account, and then I used Eraser to ensure all that juicy data I just deleted can't be retrieved.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Nice&lt;/em&gt;.  I'm a fan.  Get it &lt;a href='http://eraser.heidi.ie/download.php'&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-215181338216002999?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/215181338216002999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=215181338216002999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/215181338216002999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/215181338216002999'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/02/secure-data-removal-when-disposing-of.html' title='Secure data removal when disposing of a PC'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7223582699382791814</id><published>2010-02-02T20:04:00.001-08:00</published><updated>2010-02-03T14:19:30.594-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF assembly merging'/><category scheme='http://www.blogger.com/atom/ns#' term='BAML'/><title type='text'>Merging WPF assemblies</title><content type='html'>Life can be unnecessarily complex, especially if you work with technology!&lt;br /&gt;&lt;br /&gt;WPF is great.  One of the ten best things Microsoft has ever done.  (Er - not that they haven't also done loads of terrible things, but that's another story.)&lt;br /&gt;&lt;br /&gt;Unfortunately, WPF windows and user controls are compiled into BAML, &lt;em&gt;every time you rebuild your application&lt;/em&gt;, and the compile-to-BAML process is not very efficient.&lt;br /&gt;&lt;br /&gt;I have, hmmm, probably 50 to 100 WPF windows and user controls in a particular project, and on a 3.2ghz CPU, app build time is around 12 seconds.  And that's with heaps of RAM, the superb Intel X25-M SSD, and other speed features.&lt;br /&gt;&lt;br /&gt;Compile the project without WPF windows and user controls, and it takes more like a second.&lt;br /&gt;&lt;br /&gt;In other words, compilation to BAML is just plain slow.&lt;br /&gt;&lt;br /&gt;Yet every time you change &lt;em&gt;anything&lt;/em&gt; in the project's source code - regardless of whether or not you actually modified any XAML files or associated code-behind files - the BAML files are regenerated.&lt;br /&gt;&lt;br /&gt;With C#, those BAML files are (it seems) regenerated just when you rebuild the project - which wastes some time.&lt;br /&gt;&lt;br /&gt;But with VB.NET, those BAML files are constantly being regenerated as the VB.NET IDE performs ongoing recompilations of the entire project for Intellisense purposes.&lt;br /&gt;&lt;br /&gt;This means that, working on a large VB.NET project with lots of XAML windows and user controls, you can face an unresponsive IDE several times a minute as it constantly compiles and recompiles and re-re-compiles, taking more than 10 seconds every time.&lt;br /&gt;&lt;br /&gt;Slow, slow, slow, slow, slow, slow.&lt;br /&gt;&lt;br /&gt;And for those of us who are into rapid testing and release cycles, slow builds are productivity killers.&lt;br /&gt;&lt;br /&gt;So I refactored the solution, putting the windows and user controls in a WPF DLL, leaving most of the application logic in the main project (the WPF EXE that already existed).&lt;br /&gt;&lt;br /&gt;There were a few tricks to getting that to work, but now build time is slashed.  Unless I actually modify a window or user control in that DLL, the DLL is not rebuilt, and so I save roughly 10 seconds each time.  And if you're making a series of minor tweaks and re-running, as is typical during testing cycles, that can easily translate into a 10% to 30% reduction in time spent by the developer.  THAT'S good!&lt;br /&gt;&lt;br /&gt;Of course, whatever XAML window or user control I happen to be working on at the time, I leave in the main WPF EXE, and only transfer it into the WPF DLL once I've tested it, and the usual flood of change requests for the new screen have died down.&lt;br /&gt;&lt;br /&gt;That way, I'm rarely modifying the WPF DLL, and so I'm rarely copping the full 12-ish second build time - sufficiently rarely that the slowness of the full build is largely irrelevant.&lt;br /&gt;&lt;br /&gt;All good and well ...&lt;br /&gt;&lt;br /&gt;... and I highly recommend it if you need the speed boost ...&lt;br /&gt;&lt;br /&gt;... BUT, things fall apart if you try to use a tool that merges assemblies.&lt;br /&gt;&lt;br /&gt;I spent hours today digging around, and this is what I found out :&lt;br /&gt;&lt;br /&gt;All of the XAML windows and user controls that have "Build Action" set to "Page" (which is the default), are compiled into a single assembly manifest resource named {AssemblyNameMinusFilenameExtension}.g.resources (e.g. MyApp.g.resources).&lt;br /&gt;&lt;br /&gt;Within that one assembly manifest resource is a bunch of BAML items, one for each window or user control.&lt;br /&gt;&lt;br /&gt;Now, if you change the name of the assembly manifest resource, WPF can no longer locate the BAML files.&lt;br /&gt;&lt;br /&gt;So let's for example say you have two assemblies : MyWpfExe and MyWpfDll.&lt;br /&gt;&lt;br /&gt;MyWpfExe.exe contains an assembly manifest resource named MyWpfExe.g.resources.&lt;br /&gt;&lt;br /&gt;MyWpfDll.dll contains an assembly manifest resource named MyWpfDll.g.resources.&lt;br /&gt;&lt;br /&gt;Problem is, if you merge the assemblies together, these two assembly manifest resources do not get merged, and because WPF will ONLY look for assembly manifest resources that match the assembly name, one of the assembly manifest resources (and all associated windows and user controls) will be ignored.&lt;br /&gt;&lt;br /&gt;e.g. MyMergedWpfExe.exe contains two assembly manifest resources :&lt;br /&gt;MyWpfExe.g.resources&lt;br /&gt;MyWpfDll.g.resources&lt;br /&gt;&lt;br /&gt;... but WPF will only look for one, matching the assembly name.  i.e. the MyWpfDll.g.resources will be completely ignored.&lt;br /&gt;&lt;br /&gt;Obvious solution?  Well, somehow merge the two assembly manifest resources into one.  But no easy cigar.  I expect it can be done.  I'll leave that as an exercise to the reader, if they care.  (I found no existing tools that do the job, so it would probably require someone to write a tool especially for this purpose.)&lt;br /&gt;&lt;br /&gt;I ended up finding a way that didn't require me to write a special tool.  It's cumbersome, it's "clunky", but it does work, and it meets my immediate needs, and I can always improve it later.&lt;br /&gt;&lt;br /&gt;So here goes (and warning : it is very technical!) :&lt;br /&gt;&lt;br /&gt;There are two parts to my trick.&lt;br /&gt;&lt;br /&gt;Part 1) Trick WPF into loading TWO DIFFERENT assembly manifest resources, from the SAME assembly, BOTH of which will be fully consulted when loading windows and user controls.  The heart of this trick is to rename one of the assembly manifest resources to include the "en-US" culture.  Unfortunately, this trick can only work if there are ONLY two assemblies with BAML stuff being merged, and it gets tricky if you are using localisation for other purposes (although you can still do it).  (More details below.)&lt;br /&gt;&lt;br /&gt;Part 2) The compiled BAML contains a link to the original assembly name, and of course, post-merging, the original assembly ain't anywhere to be found.  So, ridiculous as it might seem, you actually need to temporarily produce a version of the DLL that has the same assembly name as the EXE.  (More details below.)&lt;br /&gt;&lt;br /&gt;So, step by step, it goes something like this :&lt;br /&gt;&lt;br /&gt;Step 1) Alter MyWpfDll.dll's project settings so that its Assembly Name matches the exe's Assembly Name (MyWpfExe).&lt;br /&gt;&lt;br /&gt;Step 2) Build just the DLL (MyWpfExe.dll, due to the rename in step #1).&lt;br /&gt;&lt;br /&gt;Step 2) Open MyWpfExe.dll in Lutz Roeder's Reflector.&lt;br /&gt;&lt;br /&gt;Step 3) Drill down through the tree view until you find the resource named MyWpfExe.g.resources.  Right-click it and save it somewhere - e.g. C:\MyWpfExe.g.resources.&lt;br /&gt;&lt;br /&gt;Step 4) Revert the name change from step #1.  (i.e. reconfigure the MyWpfDll project to use MyWpfDll as its assembly name again instead of MyWpfExe.)&lt;br /&gt;&lt;br /&gt;Step 5) Rename MyWpfExe.g.resources to MyWpfExe.g.en-US.resources.&lt;br /&gt;&lt;br /&gt;Step 6) "Add existing file" to the MyWpfExe project, and choose MyWpfExe.g.en-US.resources.&lt;br /&gt;&lt;br /&gt;Step 7) Ensure that MyWpfExe.g.en-US.resources has Build Action set to "Embedded Resource" (which is the default at least on my computer, so that SHOULD already be fine).&lt;br /&gt;&lt;br /&gt;Step 8) Build the "solution" (MyWpfExe.exe and MyWpfDll.dll).&lt;br /&gt;&lt;br /&gt;Step 9) Merge assemblies.&lt;br /&gt;&lt;br /&gt;Voila!  That was very painful and cumbersome, but you now have two WPF assemblies merged together, in a manner that all of the BAML from both assemblies is still accessible.&lt;br /&gt;&lt;br /&gt;Alternatives :&lt;br /&gt;&lt;br /&gt;* Of course, one option since you have full source code for both projects, is to make a project file that combines all source files into one mega project.  Only use that project file when doing your release build.  Not ideal, but an option, especially if you can find or make a tool that will automatically combine two VS.NET projects into a single project.  (And hey - if you can find or make such a tool, it'll probably be less un-ideal than what I've presently settled for!  It's just, when I finally found something that met my immediate purposes, I decided to not waste any further time refining it for the moment.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7223582699382791814?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7223582699382791814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7223582699382791814' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7223582699382791814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7223582699382791814'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/02/merging-wpf-assemblies.html' title='Merging WPF assemblies'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6507633647981550499</id><published>2010-01-26T12:16:00.000-08:00</published><updated>2010-01-26T12:23:42.369-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LINQ to SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='PLINQO'/><category scheme='http://www.blogger.com/atom/ns#' term='CodeSmith'/><title type='text'>PLINQO : Data caching for the masses</title><content type='html'>The single biggest way to improve the speed of a database app is to cache data in memory, cutting-down on round-trips to remote servers.&lt;br /&gt;&lt;br /&gt;But caching usually requires tedious hand-coding.&lt;br /&gt;&lt;br /&gt;Apparently not-so any more.&lt;br /&gt;&lt;br /&gt;I haven't checked it out yet, but CodeSmith claims their new &lt;a href='http://plinqo.com/'&gt;PLINQO&lt;/a&gt; technology has built-in data caching mechanisms.  That sounds like a very easy way to get substantial speed improvements in one's app!&lt;br /&gt;&lt;br /&gt;It works in concert with LINQ to SQL.&lt;br /&gt;&lt;br /&gt;In short, it's an entity framework that purportedly makes data caching easy.  Exactly how easy?  I haven't played with it yet, so I can't comment.&lt;br /&gt;&lt;br /&gt;Switching frameworks is obviously a big effort, and I'm reasonably satisfied with the frameworks I'm already using, but this data-caching feature of PLINQO is enough to intrigue me - I think I might check it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6507633647981550499?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6507633647981550499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6507633647981550499' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6507633647981550499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6507633647981550499'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/01/plinqo-data-caching-for-masses.html' title='PLINQO : Data caching for the masses'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6685364429310932363</id><published>2010-01-21T23:33:00.000-08:00</published><updated>2010-01-21T23:47:24.016-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PC-Mac interoperation'/><category scheme='http://www.blogger.com/atom/ns#' term='Remote desktop'/><title type='text'>LogMeIn : Remote Mac screen sharing to Windows</title><content type='html'>A client has a Mac that I frequently need to log into remotely.&lt;br /&gt;&lt;br /&gt;It's a brand-new Mac Mini, running Snow Leopard.&lt;br /&gt;&lt;br /&gt;Getting the built-in VNC server to work with a Windows client was a very major pain.&lt;br /&gt;&lt;br /&gt;Most VNC viewers simply refused to connect at all.&lt;br /&gt;&lt;br /&gt;I did eventually find one Windows-based VNC viewer that would connect to the "Screen Sharing" on the Mac.&lt;br /&gt;&lt;br /&gt;But lo-and-behold, the Screen Sharing service would frequently freeze up and stop accepting new connections, and I would need to call the client and get someone to physically disable and re-enable the Screen Sharing service to resolve the problem.&lt;br /&gt;&lt;br /&gt;Further, the VNC connection would usually drop out after just a few minutes of inactivity, meaning I was constantly closing the VNC viewer and restarting it.&lt;br /&gt;&lt;br /&gt;All in all, it was like doing a forced march on a broken leg.&lt;br /&gt;&lt;br /&gt;Ouch.&lt;br /&gt;&lt;br /&gt;So I went a huntin' for other options.&lt;br /&gt;&lt;br /&gt;Must share a Mac's screen to a Windows client.&lt;br /&gt;&lt;br /&gt;Preferrably free, although I would willing pay up to a few tens of dollars.&lt;br /&gt;&lt;br /&gt;The only options I found wanted around $100 per year.  That's not scalable.  What if I picked up another client with a Mac needing similar remote support?  That'd be another $100 per year per Mac being supported.  Worth it for some, but not worth it in my particular case.&lt;br /&gt;&lt;br /&gt;Then I found LogMeIn.&lt;br /&gt;&lt;br /&gt;I tried it.&lt;br /&gt;&lt;br /&gt;The Free edition supports screen sharing exactly like I want.&lt;br /&gt;&lt;br /&gt;The Pro (non-free) edition has extra cool features like a "whiteboard" mode where the viewer can 'draw' on the screen, and both the person on the Mac, and the viewer on his remote PC, can see the drawing.&lt;br /&gt;&lt;br /&gt;The Free version, it turns out, comes with time-limited access to the Pro features.&lt;br /&gt;&lt;br /&gt;Smart move on LogMeIn's part.&lt;br /&gt;&lt;br /&gt;I was experimenting with all these cool features, and then the Mac died the death.&lt;br /&gt;&lt;br /&gt;My client told me that not only was I unable to connect, but they found the Mac in some unusable state and had to reboot it.&lt;br /&gt;&lt;br /&gt;Hmmm.&lt;br /&gt;&lt;br /&gt;Et tu, LogMeIn?&lt;br /&gt;&lt;br /&gt;After such a surge of hope when LogMeIn initially worked, I was feeling very disappointed.&lt;br /&gt;&lt;br /&gt;A web search turned up an odd clue : someone recommended running LogMeIn in 32-bit mode.&lt;br /&gt;&lt;br /&gt;I'm not a Mac man, and I don't know how to enable "32-bit" mode for an app.&lt;br /&gt;&lt;br /&gt;But I did manage to find a "Rosetta" mode for LogMeIn.&lt;br /&gt;&lt;br /&gt;After enabling "Rosetta" mode for LogMeIn (right-click the Start LogMeIn app, and the option is in there somewhere), and studiously avoiding the fancy whiteboard and other tools (just in case they were to blame), LogMeIn now works WONDERFULLY for me.  WONDERFULLY.&lt;br /&gt;&lt;br /&gt;I can actually have a reliable, unbroken remote desktop session from a Windows box to a Mac box, any time of day or night!&lt;br /&gt;&lt;br /&gt;It's like humanity finally arrived in the 21st century!&lt;br /&gt;&lt;br /&gt;So, kudos to LogMeIn.&lt;br /&gt;&lt;br /&gt;And if you give it a try and the Mac dies the death, then the solution is one or both of : Use Rosetta mode, and/or don't use those delicious tempting "Pro" tools.&lt;br /&gt;&lt;br /&gt;I could experiment more and figure out exactly which of those two variables made the difference, but time is so short I could hardly justify writing this note, let alone doing another half hour or hour of experiments, so sorry - hopefully this article will at least help some other wandering soul out there on the road to PC-Mac blissdom.  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6685364429310932363?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6685364429310932363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6685364429310932363' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6685364429310932363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6685364429310932363'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2010/01/logmein-remote-mac-screen-sharing-to.html' title='LogMeIn : Remote Mac screen sharing to Windows'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-3259527145591320303</id><published>2009-08-11T01:22:00.000-07:00</published><updated>2009-08-11T01:28:50.267-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><title type='text'>Nesting implicit styles in WPF</title><content type='html'>All I wanted to do was define a style at Page level to control the font size of Label controls, and then define other styles for parts of the page where Label controls need to be further customised.&lt;br /&gt;&lt;br /&gt;e.g. set font size to 8pt at the top-level, and for some parts of the page, set each label to a specific width.&lt;br /&gt;&lt;br /&gt;I Google-d around and thought the Style BasedOn attribute should do it for me.&lt;br /&gt;&lt;br /&gt;Alas, it appeared not to.&lt;br /&gt;&lt;br /&gt;But then I noticed a major bug in the VS.NET 2008 XAML designer : it was not properly applying style changes!&lt;br /&gt;&lt;br /&gt;If I changed the text in a Label control, the XAML designer would reflect that, but if I changed relevant styles, the XAML designer would often miss it.&lt;br /&gt;&lt;br /&gt;And that's where I realised : BasedOn IS the key, it's just that the VS.NET XAML designer is so pathetic that you have to close and re-open any XAML document you are editing in order to see the effect of nested style changes.&lt;br /&gt;&lt;br /&gt;And of course, to make matters worse, VS.NET is famous for its idiotically slow load times for XAML files in large projects that contain lots of XAML files.  So, hello lots more time being wasted now that we're forced to close and re-open XAML files just to get the designer to refresh properly...&lt;br /&gt;&lt;br /&gt;&lt;a href='http://blogs.claritycon.com/blogs/sean_devlin/archive/2009/07/27/cascading-implicit-styles-in-wpf.aspx'&gt;Clarity Consulting wrote a nice little piece showing how to use BasedOn with nested implicit styles&lt;/a&gt;.  The missing piece of the puzzle is simply the need to close and re-open the XAML designer each time you make a change.  Ugggh.  But at least it eventually gets to the desired effect...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-3259527145591320303?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/3259527145591320303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=3259527145591320303' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3259527145591320303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3259527145591320303'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/08/nesting-implicit-styles-in-wpf.html' title='Nesting implicit styles in WPF'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6358086861122583321</id><published>2009-06-27T02:23:00.000-07:00</published><updated>2009-06-27T02:34:34.544-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><title type='text'>Flash AS3 Dictionary - bliss!</title><content type='html'>&lt;p&gt;I came in on ActionScript at version 3, and with a strong javascript and .NET background.&lt;/p&gt;&lt;p&gt;Compared to javascript (which I quite like), I think ActionScript is even better.  &lt;small&gt;(They both have major issues, but I still quite like them, even if I hate the Flash software development tools which are "crappy as"...)&lt;/small&gt;&lt;/p&gt;&lt;p&gt;Sometimes you need to iterate a set of ActionScript object instances, and keep a record of some piece of data for each object instance.&lt;/p&gt;&lt;p&gt;In javascript it's easy - just add a new dynamic data field to each object instance.&lt;/p&gt;&lt;p&gt;But ActionScript adds the concept of "sealed" classes, which prevent the dynamic addition of new data fields.&lt;/p&gt;&lt;p&gt;So we're stuffed?&lt;/p&gt;&lt;p&gt;Well, there is a solution.  Only one, but it works very well.&lt;/p&gt;&lt;p&gt;It's the new ActionScript 3 Dictionary.&lt;/p&gt;&lt;p&gt;It is an associative array keyed not by a &lt;em&gt;string&lt;/em&gt; but by an &lt;em&gt;object instance&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;I use Dictionary objects all the time in other languages, so I was hoping ActionScript might have one, and I finally went looking for it, and found it yesterday.&lt;/p&gt;&lt;p&gt;Here are two articles I felt did a great job of introducing this powerful Dictionary object :&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href='http://www.actionscript.org/resources/articles/804/1/Building-A-Better-Array----The-Dictionary-Class/Page1.html'&gt;Building A Better Array - The Dictionary Class&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href='http://www.experimo.net/as3/vector-and-dictionary-in-as3/'&gt;Vector And Dictionary In ActionScript 3&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Viva la Dictionary!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6358086861122583321?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6358086861122583321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6358086861122583321' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6358086861122583321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6358086861122583321'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/06/flash-as3-dictionary-bliss.html' title='Flash AS3 Dictionary - bliss!'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6357979030179300704</id><published>2009-06-27T01:03:00.000-07:00</published><updated>2009-06-27T01:18:33.706-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft SilverLight'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><title type='text'>Microsoft Silverlight stumbles at the gate</title><content type='html'>I have in the past predicted that &lt;a href='http://selfdocumentingcode.blogspot.com/2009/04/flash-vs-silverlight-silverlight-will.html'&gt;Adobe Flash will lose out to Microsoft Silverlight&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But Microsoft keeps slipping up in one key area : &lt;em&gt;ubiquity&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Silverlight was supposedly a technology that would run everywhere - including on mobile devices.&lt;br /&gt;&lt;br /&gt;But Microsoft can't even get Silverlight running on their own Windows Mobile platform, let alone any other mobile devices.&lt;br /&gt;&lt;br /&gt;On the other hand, Flash has Flash Lite, which is already on millions of handheld devices worldwide.&lt;br /&gt;&lt;br /&gt;Yes, the Microsoft development tools actually work reliably, and yes, the Flash development tools are riddled with bugs, poorly documented, and priced uncompetitively.&lt;br /&gt;&lt;br /&gt;But with the meteoric rise of handheld devices, and the lack of Silverlight support for &lt;em&gt;any&lt;/em&gt; handheld devices (despite announcements over the past two years or so that "it's coming"), Microsoft is giving Adobe a massive breather.&lt;br /&gt;&lt;br /&gt;A breather that may cost Microsoft years in their attempt to dominate this particular market.&lt;br /&gt;&lt;br /&gt;If Adobe would make their tools and documentation at least as good as Microsoft's, then they could justify their price structure, and leave few incentives for anyone to use Silverlight.&lt;br /&gt;&lt;br /&gt;But on the other hand, if Adobe continues to prove incompetent in QC for software development tools and documentation, and Microsoft finally gets their act together with the long-promised and I'm-growing-tired-of-waiting-for "Silverlight for mobile", then my original prediction stands, and Silverlight will move out of the realm of predominantly line-of-business apps, more and more into the mainstream, until the days of Adobe's dominance are a distant memory like the Commodore 64.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6357979030179300704?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6357979030179300704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6357979030179300704' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6357979030179300704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6357979030179300704'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/06/microsoft-silverlight-stumbles-at-gate.html' title='Microsoft Silverlight stumbles at the gate'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7130352465764489420</id><published>2009-06-18T01:52:00.000-07:00</published><updated>2009-06-18T02:01:30.653-07:00</updated><title type='text'>JetStart - the end of Start Menu clutter</title><content type='html'>&lt;a href='http://www.codesector.com/jetstart.php'&gt;JetStart&lt;/a&gt; is awesome!&lt;br /&gt;&lt;br /&gt;It's rare that I'm yelling in excitement just reading about a product, or tripping over myself in my eagerness to tell the world about an amazing piece of software when I've only used it for two minutes, but such is the privileged case with &lt;a href='http://www.codesector.com/jetstart.php'&gt;JetStart&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As a programmer, I have dozens of tools &amp;amp; utilities installed over the years, and navigating my Start Menu is a nightmare.  Painus Maximum, as my wife likes to say.&lt;br /&gt;&lt;br /&gt;So often I find myself saying "I wish I could just type a few letters and see every Start Menu entry that matches".  It would be so much quicker to start IZArc or PDF Creator or any of my other occassionally-used tools if I didn't have to pore over an entire screen covered by my sprawling Start Menu.&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.codesector.com/jetstart.php'&gt;JetStart&lt;/a&gt; is my dream come true.  Its integration into the Windows experience is neat and inobtrusive.&lt;br /&gt;&lt;br /&gt;And it's fast.&lt;br /&gt;&lt;br /&gt;Press the Start key, then start typing.  Instant response!&lt;br /&gt;&lt;br /&gt;Now THIS is good software.  Yeah baby!&lt;br /&gt;&lt;br /&gt;Top kudos to the guys at codesector.com who made it.&lt;br /&gt;&lt;br /&gt;And no, its free, and I'm not getting any kickbacks for raving about it.  I reckon you'll rave too if you're a power user like me with an overbloated Start menu.  Give it a shot - what've you got to lose?  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7130352465764489420?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7130352465764489420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7130352465764489420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7130352465764489420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7130352465764489420'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/06/jetstart-theend-of-start-menu-clutter.html' title='JetStart - the end of Start Menu clutter'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7014191117333117125</id><published>2009-06-09T21:49:00.000-07:00</published><updated>2009-06-09T22:05:11.315-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Creation Suite CS4 Subscription Edition'/><title type='text'>Adobe Subscription Manager hiccups and workarounds</title><content type='html'>Adobe has released Adobe Creative Suite CS4 Design Edition on a Subscription basis to the Australian market only.  It's an experiment, presumably, to determine whether it's worth doing on a worldwide basis.&lt;br /&gt;&lt;br /&gt;It has a few unique glitches I had to fight with myself, so for the benefit of those who come after...&lt;br /&gt;&lt;br /&gt;-&lt;br /&gt;&lt;br /&gt;1) There is ABSOLUTELY NO STANDARD WAY to install the Subscription Edition if you have an expired trial version installed at the same time.&lt;br /&gt;&lt;br /&gt;For example, I had a trial version of Flash.&lt;br /&gt;&lt;br /&gt;The Subscription Edition installer said "oh - you already have Flash installed, so I don't need to install it again".  But the problem is, the Flash that is installed with the Subscription Edition is a slightly different version of Flash that knows how to accept subscription-based license keys and otherwise interoperate with the Adobe Subscription Manager.  The Flash trial, in contrast, will never recognise the Adobe Subscription Manager, even if your subscription is fully paid.&lt;br /&gt;&lt;br /&gt;i.e. you're forced to uninstall everything, then re-install using the Subscription Edition DVDs.&lt;br /&gt;&lt;br /&gt;A pain, but at least it works...&lt;br /&gt;&lt;br /&gt;-&lt;br /&gt;&lt;br /&gt;2) If your subscription expires, and you want to renew it, Adobe documentation says you need to use the Adobe Subscription Manager which, supposedly, is installed on your computer.&lt;br /&gt;&lt;br /&gt;The problem is, there is no link to the Adobe Subscription Manager.  Anywhere.&lt;br /&gt;&lt;br /&gt;Even doing an exhaustive search of "C:\Program Files\Adobe" (including subfolders) failed to find it, using the wildcarded search term "*sub*.exe", and when that failed, the wildcarded search term "*man*.exe".&lt;br /&gt;&lt;br /&gt;So I called Adobe tech support.&lt;br /&gt;&lt;br /&gt;I note that they have a special phone queue just for Subscription Edition customers.&lt;br /&gt;&lt;br /&gt;Hmmm - smacks of there being a lot of other people experiencing problems...&lt;br /&gt;&lt;br /&gt;... but to their credit, I was speaking to a human within about 30 seconds!  I was very impressed.&lt;br /&gt;&lt;br /&gt;They wanted to know my customer number, which took me a while to dig out, but when finally they had linked me to my order, they were ready to answer any questions I might have.&lt;br /&gt;&lt;br /&gt;I asked how to find the Subscription Manager.  The woman on the other end found the answer very quickly - they must have a good search tool for their internal help docs, or else it must be a very common question (or both) - and it lives in C:\Program Files\Common Files\Adobe\Adobe Subscription Manager CS4 and is called AdobeSubscriptionManager.exe.  Hurrah!&lt;br /&gt;&lt;br /&gt;So I double-clicked.&lt;br /&gt;&lt;br /&gt;And nothing happened.&lt;br /&gt;&lt;br /&gt;Something fishy going on here...&lt;br /&gt;&lt;br /&gt;I opened Task Manager and saw a program called ADOBES~1.EXE.  Ah!  I remembered seeing that earlier in the day.  Suddenly it dawned on me - the Adobe Subscription Manager is probably &lt;em&gt;supposed&lt;/em&gt; to be launched automatically, but at least in my case, it failed to ever show a UI, and got stuck running in the background.&lt;br /&gt;&lt;br /&gt;But because there was one stuck instance of Adobe Subscription Manager running in the background, it prevented any new instances from starting.&lt;br /&gt;&lt;br /&gt;Easy fix - I killed ADOBES~1.EXE using Task Manager, and double-clicked AdobeSubscriptionManager.exe again.&lt;br /&gt;&lt;br /&gt;Waiting...&lt;br /&gt;&lt;br /&gt;And after several seconds, huzzah!  There it was.&lt;br /&gt;&lt;br /&gt;I thanked the Adobe technician and proceeded to reactivate my subscription.&lt;br /&gt;&lt;br /&gt;-&lt;br /&gt;&lt;br /&gt;So there you have it, ladies &amp;amp; gentlemen - some little known issues with Adobe Subscription Manager, and corresponding workarounds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7014191117333117125?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7014191117333117125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7014191117333117125' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7014191117333117125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7014191117333117125'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/06/adobe-subscription-manager-hiccups-and.html' title='Adobe Subscription Manager hiccups and workarounds'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-2878138604329813528</id><published>2009-05-20T23:37:00.000-07:00</published><updated>2009-05-20T23:43:05.705-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe BridgeTalk'/><title type='text'>Using Adobe BridgeTalk synchronously</title><content type='html'>So let's face it : writing synchronous code is a lot easier than writing asynchronous code.  I can write asynchronous code easily enough, but it looks so much more cluttered, and/or takes so many more lines of code.  I'm a big believer in simplicity.&lt;br /&gt;&lt;br /&gt;So, if you want to whip up a simple script, and it doesn't need to win design awards, then I suggest you check out &lt;a href='http://www.ps-scripts.com/bb/viewtopic.php?p=3351&amp;sid=1fb1467f5ee17e2c9b17ee54b69bd03d'&gt;xbytor's cool little trick for using BridgeTalk &lt;strong&gt;synchronously&lt;/strong&gt;&lt;/a&gt;.  &lt;small&gt;(Search on that page for "Send a synchronous message".)&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Nice one, xbytor.&lt;br /&gt;&lt;br /&gt;And in case that forum goes down, here's a copy of the most pertinent bit.  (See the original thread for more questions, answers and examples.)&lt;br /&gt;&lt;br /&gt;First, some utility code :&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;// Send a synchronous message. The result is returned.&lt;br /&gt;// If a result doesn't come back in 'timeout' seconds, undefined is returned.&lt;br /&gt;BridgeTalk.prototype.sendSynch = function(timeout) {&lt;br /&gt;  var self = this;&lt;br /&gt;  self.onResult = function(res) {&lt;br /&gt;    this.result = res.body;&lt;br /&gt;    this.complete = true;&lt;br /&gt;  }&lt;br /&gt;  self.complete = false;&lt;br /&gt;&lt;br /&gt;  self.send();&lt;br /&gt;&lt;br /&gt;  if (timeout) {&lt;br /&gt;    for (var i = 0; i &lt; timeout; i++) {&lt;br /&gt;      BridgeTalk.pump();       // process any outstanding messages&lt;br /&gt;      if (!self.complete) {&lt;br /&gt;        $.sleep(1000);&lt;br /&gt;      } else {&lt;br /&gt;        break;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var res = self.result;&lt;br /&gt;  self.result = self.complete = self.onResult = undefined;&lt;br /&gt;  return res;&lt;br /&gt;};&lt;br /&gt;// for typos, provide an alias&lt;br /&gt;BridgeTalk.prototype.sendSync = BridgeTalk.prototype.sendSynch;&lt;/blockquote&gt;&lt;br /&gt;And now an example of how to use it :&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;function test() {&lt;br /&gt;  var bridgeApp = "bridge-1.0";&lt;br /&gt;&lt;br /&gt;  if (!BridgeTalk.isRunning(bridgeApp)) {&lt;br /&gt;    BridgeTalk.launch(bridgeApp);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var bt = new BridgeTalk();&lt;br /&gt;  bt.target = bridgeApp;&lt;br /&gt;  bt.body = "new Date().toString()";&lt;br /&gt;  var res = bt.sendSynch(10);&lt;br /&gt;  alert(res);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;test(); &lt;/blockquote&gt;&lt;br /&gt;Once again, mega kudos to xbytor.  Some coding purists might gag at the internal polling loop, but remember, we're not talking about production scripts released to thousands of users worldwide - we're talking about helping every developer be more productive by writing their own scripts more easily.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-2878138604329813528?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/2878138604329813528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=2878138604329813528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/2878138604329813528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/2878138604329813528'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/using-adobe-bridgetalk-synchronously.html' title='Using Adobe BridgeTalk synchronously'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-5577167750497461809</id><published>2009-05-20T22:56:00.000-07:00</published><updated>2009-05-20T23:33:23.519-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Illustrator'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe BridgeTalk'/><title type='text'>Adobe BridgeTalk woes</title><content type='html'>As just another look at how mind-numbingly idiotic a large proportion of Adobe APIs are, consider this attempt to use BridgeTalk :&lt;br /&gt;&lt;br /&gt;var bt = new BridgeTalk();&lt;br /&gt;bt.send();&lt;br /&gt;alert('The message was sent successfully.');&lt;br /&gt;&lt;br /&gt;We haven't specified a recipient, and we haven't specified an actual message.&lt;br /&gt;&lt;br /&gt;But run the code, and guess what?  Apparently, the message was sent successfully.&lt;br /&gt;&lt;br /&gt;Especially for such a poorly-documented class as BridgeTalk is, developers rely on meaningful error messages (including input validation error messages) to figure out what's going wrong and how on God's beautiful green earth we're supposed to use the thing.&lt;br /&gt;&lt;br /&gt;My original script looked more like this :&lt;br /&gt;&lt;br /&gt;function BridgeTalkResultHandler(result)&lt;br /&gt;{&lt;br /&gt;  alert('Hurrah!  The callback came!' + result.body);&lt;br /&gt;}&lt;br /&gt;var bt = new BridgeTalk();&lt;br /&gt;bt.targetApp = 'illustrator';&lt;br /&gt;bt.body = 'alert("hello");';&lt;br /&gt;bt.onResult = BridgeTalkResultHandler;&lt;br /&gt;bt.send();&lt;br /&gt;alert('The message was sent successfully.');&lt;br /&gt;&lt;br /&gt;Translation : get Illustrator to show a message.  Just an elementary test.&lt;br /&gt;&lt;br /&gt;But plug this into the ExtendScript ToolKit and run it, and all you get is meaningless nonsense.&lt;br /&gt;&lt;br /&gt;'The message was sent successfully' is given every time you run it, but Illustrator doesn't budge.&lt;br /&gt;&lt;br /&gt;Well, thought I, perhaps Illustrator refuses to interact with the user (e.g. with the alert method) under some circumstances.  So I changed the script to app.activeDocument.close(), and I left a document open in Illustrator, so I could see if something happened.  Still nothing.&lt;br /&gt;&lt;br /&gt;I removed the onResult handler to see if somehow that was causing the problem.  Nothing changed.&lt;br /&gt;&lt;br /&gt;And I stripped out more and more things, until I got to the code at the start of this article.&lt;br /&gt;&lt;br /&gt;The behaviour is identical, for every version of the script.&lt;br /&gt;&lt;br /&gt;In other words, BridgeTalk is doing absolutely nothing - not even any validation.&lt;br /&gt;&lt;br /&gt;I even tried crazy things like :&lt;br /&gt;&lt;br /&gt;bt.targetApp = 'illustraaaaaaaaaaaator';&lt;br /&gt;&lt;br /&gt;... but there wasn't any complaint about the non-existent target.&lt;br /&gt;&lt;br /&gt;Examples of BridgeTalk are not as plentiful as one might wish for, but my original code looks very much like the few examples I found.&lt;br /&gt;&lt;br /&gt;All I can say is : this is typical of Adobe APIs.  Poorly documented, counter-intuitive, and requiring wasteful trial-and-error to master.&lt;br /&gt;&lt;br /&gt;If it was open-source, or some cheapo product, I'd excuse it.  But when they want to charge thousands for their suite of products, you expect a LOT better than this.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Got it working - bt.target is the correct property name, not bt.targetApp.  I'm not sure whether I read a bad example, or whether I misread an example, but in either case, my thesis stands - Adobe APIs are a dog to work with except only when everything is working perfectly.  A helpful input validation error message, such as 'target property is required', would have saved me valuable time!  C'mon Adobe, you know you can do better than this...  What's worst is that Microsoft is now actually pretty good at making meaningful error messages (something they were hopeless at ten years ago) - so it's possible to have a moderately-self-documenting API, and that means Adobe has dropped the ball.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-5577167750497461809?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/5577167750497461809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=5577167750497461809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5577167750497461809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5577167750497461809'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/adobe-bridgetalk-woes.html' title='Adobe BridgeTalk woes'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8459493587426786420</id><published>2009-05-19T20:27:00.000-07:00</published><updated>2009-05-19T20:59:27.336-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Illustrator'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe BridgeTalk'/><title type='text'>Automate Adobe Flash using VB.NET or C#</title><content type='html'>Adobe is very thin as usual on technical details, so I've had to poke around and try different things.&lt;br /&gt;&lt;br /&gt;Here's what I've found :&lt;br /&gt;&lt;br /&gt;* .NET can communicate directly with Illustrator, but not directly with Flash, nor with BridgeTalk.&lt;br /&gt;&lt;br /&gt;* .NET can send javascript to Illustrator, including javascript which utilises &lt;a href='http://selfdocumentingcode.blogspot.com/2009/05/cross-scripting-adobe-illustrator-and.html'&gt;BridgeTalk to communicate between Illustrator and Flash&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;* So it is possible to automate both Illustrator and Flash using VB.NET/C#/other-.NET-languages, but it requires .NET &amp;lt;-&amp;gt; Illustrator &amp;lt;-&amp;gt; BridgeTalk &amp;lt;-&amp;gt; Flash.&lt;br /&gt;&lt;br /&gt;* In VB.NET, you connect to Illustrator as follows :&lt;br /&gt;&lt;br /&gt;Dim app As Object = CreateObject("Illustrator.Application")&lt;br /&gt;&lt;br /&gt;* To get Illustrator to run arbitrary javascript :&lt;br /&gt;&lt;br /&gt;app.DoJavaScript(myJavaScript);&lt;br /&gt;&lt;br /&gt;e.g. to get Illustrator to greet us :&lt;br /&gt;&lt;br /&gt;app.DoJavaScript("alert('Hello!');");&lt;br /&gt;&lt;br /&gt;* To get Illustrator to return a useful value from a script we have sent it, don't use the "return" keyword - just include the return value as the final expression in the script block.&lt;br /&gt;&lt;br /&gt;e.g. :&lt;br /&gt;&lt;br /&gt;Dim ReturnValueFromIllustrator As Object = app.DoJavaScript("1 + 2;")&lt;br /&gt;MsgBox(ReturnValueFromIllustrator) ' Shows "3"&lt;br /&gt;&lt;br /&gt;* The .NET &amp;lt;-&amp;gt; Illustrator leg is synchronous, even though the Illustrator &amp;lt;-&amp;gt; BridgeTalk &amp;lt;-&amp;gt; Flash legs are ASYNCHRONOUS.  (Yeah - just to make life more interesting.)&lt;br /&gt;&lt;br /&gt;Hmmm - in short, I wouldn't say it's "easy", but it is possible.&lt;br /&gt;&lt;br /&gt;Maybe Adobe will enter the 21st century sometime and really make all their apps easily cross-scriptable, and their scripting engines a lot more robust.  Until then...&lt;br /&gt;&lt;br /&gt;... your brother in the pain of scripting Adobe products.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;P.S. If you're using C#, or if you're using VB.NET and want a better Intellisense experience (and better runtime performance, and better compile-time checking) than just using VB.NET's CreateObject method, add a reference to the "Adobe Illustrator CS4 Type Library".  Once you've done that, you can connect to Adobe Illustrator as simply as "Dim app As New Illustrator.Application" (or in C#, "Illustrator.Application app = new Illustrator.Application();").&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8459493587426786420?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8459493587426786420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8459493587426786420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8459493587426786420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8459493587426786420'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/automate-adobe-flash-using-vbnet-or-c.html' title='Automate Adobe Flash using VB.NET or C#'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7633122509731224931</id><published>2009-05-19T18:28:00.001-07:00</published><updated>2009-05-19T18:46:25.038-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='instanceof'/><category scheme='http://www.blogger.com/atom/ns#' term='ExtendScript'/><title type='text'>ExtendScript: instanceof Number</title><content type='html'>var xyz = 123.45;&lt;br /&gt;alert(xyz instanceof Number);&lt;br /&gt;&lt;br /&gt;Always false.  Not very intuitive at first.&lt;br /&gt;&lt;br /&gt;Searching for ExtendScript instanceof Number didn't help, but searching for Javascript instanceof Number did.&lt;br /&gt;&lt;br /&gt;Unfortunately, the short of it is that we have to resort to the slowness of string comparisons.  C'mon - I thought this was the 21st century!&lt;br /&gt;&lt;br /&gt;var xyz = 123.45;&lt;br /&gt;alert(typeof xyz == 'number');&lt;br /&gt;&lt;br /&gt;But there are situations where instanceof Number DOES work :&lt;br /&gt;&lt;br /&gt;var xyz = new Number(123.45);&lt;br /&gt;alert(xyz instanceof Number); // true&lt;br /&gt;&lt;br /&gt;... and in such instances, the typeof trick DOESN'T work :&lt;br /&gt;&lt;br /&gt;var xyz = new Number(123.45);&lt;br /&gt;alert(xyz instanceof Number); // true&lt;br /&gt;&lt;strong&gt;alert(typeof xyz == 'number'); // false&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There is a reason for it, and when you understand the reason, it makes sense enough, but it does prove that javascript and all its derivatives are a little idiosyncratic and obscure at times.&lt;br /&gt;&lt;br /&gt;For more info :&lt;br /&gt;&lt;br /&gt;&lt;a href='http://stackoverflow.com/questions/203739/why-does-instanceof-return-false-for-some-literals'&gt;StackOverflow - why does instanceof return false for some literals?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://juhukinners.com/tag/instanceof/'&gt;More technical info (hands-on) about javascript and instanceof&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thanks to the two articles I just listed!  They helped solve for me what was seeming a great (and annoying) mystery.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7633122509731224931?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7633122509731224931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7633122509731224931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7633122509731224931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7633122509731224931'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/extendscript-instanceof-number.html' title='ExtendScript: instanceof Number'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-5913509302724479252</id><published>2009-05-17T19:21:00.000-07:00</published><updated>2009-05-17T22:20:07.017-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Engin'/><category scheme='http://www.blogger.com/atom/ns#' term='VoIP'/><title type='text'>Running two Engin voiceboxes on the same network</title><content type='html'>Again, a post that'll only help a very few of you, but for the sake of those few...&lt;br /&gt;&lt;br /&gt;Engin is a fabulous VoIP (internet telephony) company.  We have two accounts with them - one for our business, and one for our home.&lt;br /&gt;&lt;br /&gt;Everything was working perfectly at our old address, with TPG as our ISP.&lt;br /&gt;&lt;br /&gt;We've relocated, and TPG doesn't cover our outlying suburb, so we're now with Telstra.&lt;br /&gt;&lt;br /&gt;Problem : With Telstra's ADSL2+ modem, only one of our VoIP lines works properly.&lt;br /&gt;&lt;br /&gt;Specifically, both make outbound calls just fine, but inbound calls only work consistently for one of the two lines.&lt;br /&gt;&lt;br /&gt;If I reset the Engin voiceboxes (which internally are SipuraSPAs), and wait a few seconds for them to re-register with Engin, then inbound calls work fine for both lines, for about five minutes, and after five minutes, its just the one line that inbound calls work for.&lt;br /&gt;&lt;br /&gt;I contacted Engin tech support last week, and they changed one of my Engin voiceboxes to use the "bring-your-own" Engin settings.  I thought that fixed the problem, but it turned out that the test call had been made within five minutes of a "soft reset" of the Engin device, and that's the only reason the test inbound call worked at that time.  i.e. problem not solved.&lt;br /&gt;&lt;br /&gt;Today I got it working, at last, and permanently.&lt;br /&gt;&lt;br /&gt;It's not intuitive, but I set up two port forwarding ranges on my ADSL2+ modem, one for UDP ports 16384 through 18383, and the other for UDP ports 18384 through 20384.  I pointed one port forwarding range to the one Engin voicebox, and the other range to the other voicebox.&lt;br /&gt;&lt;br /&gt;It's about half an hour later, and inbound calls for both lines are still working perfectly.  Nice...&lt;br /&gt;&lt;br /&gt;In my previous attempts to resolve this issue, Google-ing for "two Engin voiceboxes" and such like turned up a grand total of zero people discussing problems with running two Engin voiceboxes side-by-side.  So hopefully, for the next person who needs a little help, this post might provide a few ideas...&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;UPDATE : A few hours later, and I discovered it's NOT working, but I figured out why, and here's the low-down :&lt;br /&gt;&lt;br /&gt;It turns out that the port forwarding DIDN'T HELP ONE BIT.&lt;br /&gt;&lt;br /&gt;But I've pinpointed exactly what the problem is :&lt;br /&gt;&lt;br /&gt;The Engin voiceboxes re-register with Engin every nearly-30-minutes.  (It's every roughly 29 and a half minutes.)&lt;br /&gt;&lt;br /&gt;But the Telstra ADSL2+ router closes UDP "connections" after about 300 seconds (five minutes) of inactivity.&lt;br /&gt;&lt;br /&gt;So every half hour, there is a five minute window of opportunity during which inbound calls will work, and then nearly 25 minutes where they won't.&lt;br /&gt;&lt;br /&gt;My confirmation test earlier today must have been in that five minute window of opportunity.&lt;br /&gt;&lt;br /&gt;The fix?&lt;br /&gt;&lt;br /&gt;Well, I trawled through the options in the admin panel for this Telstra ADSL2+ modem, and don't seem to have any power to change the default timeout.&lt;br /&gt;&lt;br /&gt;So I contacted Engin tech support again, and asked them to remotely log in to my machine and change the default timeout on both my Engin voiceboxes down to 280 seconds.  That gives them roughly 20 seconds (far more than enough) to execute their re-registration process before the ADSL2+ router deems their UDP "connection" disposable.  The re-registration process resets the modem's five minute timer, and this process, continually repeating itself, twelve times an hour, ensures that inbound Engin calls will work at any time.&lt;br /&gt;&lt;br /&gt;And I've removed those ADSL2+ port forwards, as they are now completely useless...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-5913509302724479252?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/5913509302724479252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=5913509302724479252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5913509302724479252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5913509302724479252'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/running-two-engin-voiceboxes-on-same.html' title='Running two Engin voiceboxes on the same network'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-5093490942030413661</id><published>2009-05-14T20:55:00.000-07:00</published><updated>2009-05-14T21:07:57.438-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lsass.exe'/><title type='text'>lsass.exe high CPU usage and disk I/O</title><content type='html'>One of my old computers has had a problem for YEARS.&lt;br /&gt;&lt;br /&gt;Windows XP, service pack 2.&lt;br /&gt;&lt;br /&gt;Within minutes of reboot, lsass.exe goes to near 100% CPU utilisation, and sits there for sometimes around half an hour.&lt;br /&gt;&lt;br /&gt;Rendering the computer pretty much unusable.&lt;br /&gt;&lt;br /&gt;ALL attempts to resolve the problem had failed.&lt;br /&gt;&lt;br /&gt;And after wasting lots and lots of time, I resigned myself to simply hibernating not rebooting where possible, and losing half an hour of time every time I wanted to reboot the computer.&lt;br /&gt;&lt;br /&gt;Killing lsass.exe fails, because the Task Manager informs you that it is a system process.&lt;br /&gt;&lt;br /&gt;Trying to reduce its priority, so it hogs less CPU, fails for the same reason.&lt;br /&gt;&lt;br /&gt;It is exactly the same file (same file size, and same file bytes - I used fc.exe to compare) as the lsass.exe on my other Windows XP computers - none of which exhibit this problem.&lt;br /&gt;&lt;br /&gt;I haven't found a solution, but things have improved now.&lt;br /&gt;&lt;br /&gt;1) Earlier today, based on comments I saw on one website, I went into the properties for each hard disk, and unchecked the "Allow Indexing Service to index this disk for fast file searching" option.  When I clicked "Apply", it asked whether I want to apply this change to all subfolders as well, and I said yes.  It took ages, but it did finally finish applying the change.&lt;br /&gt;&lt;br /&gt;2) Note that I had already long prior disabled the Indexing Service itself.&lt;br /&gt;&lt;br /&gt;3) Also earlier today, based on suggestions on another website, I completely disabled the Terminal Services service.  (I also disabled Fast User Switching, prior to disabling said Terminal Services service.)&lt;br /&gt;&lt;br /&gt;lsass.exe still hogs CPU.  It's I/O read and write count goes up to over a hundred thousand.  But then it stops.  At approximately the same I/O read/write count each time.  And once it stops, my computer runs fine.&lt;br /&gt;&lt;br /&gt;And fortunately, I don't know what's changed, but it only seems to take about five minutes now.  Which is really stupid.  But much more bearable than half an hour.&lt;br /&gt;&lt;br /&gt;It doesn't seem to be a worm or trojan or anything such like.  Antivirus scans turn up nothing.&lt;br /&gt;&lt;br /&gt;handle.exe reports exactly the same files open by lsass.exe each time I run it.  That's a lot of I/O to generate for the same set of files!!!  Unless it's doing some sneaky direct-to-disk I/O and bypassing the usual file-handle system...&lt;br /&gt;&lt;br /&gt;And besides, what's with all those writes?  Well over a hundred thousand disk writes within the first five minutes of bootup?&lt;br /&gt;&lt;br /&gt;Google-ing for lsass.exe issues reveals lots of people experiencing problems, but it turns up remarkably few solutions.&lt;br /&gt;&lt;br /&gt;I haven't found a complete solution, but perhaps somehow between unchecking that "Allow Indexing Service ..." option, and disabling the Terminal Services service, it has taken a bite out of the ridiculous amount of time that lsass.exe now wastes each time I boot...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-5093490942030413661?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/5093490942030413661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=5093490942030413661' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5093490942030413661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5093490942030413661'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/lsassexe-high-cpu-usage-and-disk-io.html' title='lsass.exe high CPU usage and disk I/O'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-5654172147597860685</id><published>2009-05-14T01:58:00.001-07:00</published><updated>2009-05-14T02:41:56.610-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Illustrator'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe BridgeTalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Bridge'/><category scheme='http://www.blogger.com/atom/ns#' term='ExtendScript'/><category scheme='http://www.blogger.com/atom/ns#' term='JSFL'/><title type='text'>Cross-scripting Adobe Illustrator and Adobe Flash</title><content type='html'>21st century, expensive products, same company makes them all, and sells them all in the same package.&lt;br /&gt;&lt;br /&gt;You'd think they'd play happily together.&lt;br /&gt;&lt;br /&gt;And Adobe documentation here and there hints that they do.&lt;br /&gt;&lt;br /&gt;But finding out &lt;strong&gt;how&lt;/strong&gt; is &lt;em&gt;mighty difficult&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;You fire up the ExtendScript Toolkit, and the documentation makes it sound like you can do almost &lt;em&gt;anything&lt;/em&gt; from there.&lt;br /&gt;&lt;br /&gt;Play around with Adobe Illustrator scripting in the ExtendScript Toolkit - sweet!&lt;br /&gt;&lt;br /&gt;But now try to script Adobe Flash...&lt;br /&gt;&lt;br /&gt;... oops, um, well, there doesn't really seem to be a way to do it.&lt;br /&gt;&lt;br /&gt;Does Adobe document that you can't?  Well, not that I've managed to find.&lt;br /&gt;&lt;br /&gt;In fact, one other commentator stopped short of giving a definitive answer that Flash &lt;em&gt;isn't&lt;/em&gt; supported by the ExtendScript Toolkit, and instead just said that it seems it isn't.&lt;br /&gt;&lt;br /&gt;C'mon Adobe, give us clear, informative, unambiguous documentation!&lt;br /&gt;&lt;br /&gt;In fact, if you put "#target flash" in a script in the ExtendScript Toolkit, and try to run it, it actually launches Flash, and then tells you that it failed to connect to the Flash scripting engine.  What the???&lt;br /&gt;&lt;br /&gt;An Adobe brochure about Flash CS3 claims that it is now compatible with ExtendScript, but frankly, I don't see how, and we're now up to CS4!!!  ("&lt;a href='http://www.adobe.com/aboutadobe/pressroom/pressmaterials/pdfs/cs3_flash_whatsnew.pdf'&gt;Flash CS3 also adds ExtendScript and BridgeTalk support for cross-application scripting.&lt;/a&gt;")&lt;br /&gt;&lt;br /&gt;So after many hours of wasted time, I've figured out how to make Illustrator and Flash sing to each other.&lt;br /&gt;&lt;br /&gt;I'm not impressed by the obtuse steps required.&lt;br /&gt;&lt;br /&gt;And I'm not impressed by the extremely non-definitive documentation on Adobe's part.&lt;br /&gt;&lt;br /&gt;Here's how you do it :&lt;br /&gt;&lt;br /&gt;1) Your Adobe Illustrator scripts will be written using the ExtendScript language, whereas your Adobe Flash scripts &lt;strong&gt;must be written using a language called JSFL&lt;/strong&gt;.  Both languages are javascript-based, and have many similarities, but they also have many differences.  (e.g. native filesystem access in ExtendScript is done via the File class, whereas in JSFL it's done via the FLfile class.  Hello, any reason for that, anybody?)&lt;br /&gt;&lt;br /&gt;2) &lt;strong&gt;Adobe Bridge is not Adobe BridgeTalk&lt;/strong&gt;.  The names are very similar, but the use is very different, and unfortunately, the difference is not clearly articulated in Adobe docs.&lt;br /&gt;&lt;br /&gt;Adobe &lt;em&gt;Bridge&lt;/em&gt; is a moderately useless file cataloging and file browsing tool.&lt;br /&gt;&lt;br /&gt;In contrast, Adobe &lt;em&gt;BridgeTalk&lt;/em&gt; is a simple but powerful inter-process communication tool.&lt;br /&gt;&lt;br /&gt;So, we're going to use Adobe BridgeTalk to communicate between Illustrator and Flash.&lt;br /&gt;&lt;br /&gt;3) It is very hard to find Adobe BridgeTalk documentation.  (e.g. Google-ing for "adobe bridgetalk reference" is close to useless.)&lt;br /&gt;&lt;br /&gt;I suspect this is in part because BridgeTalk is SO simple that there's hardly anything to document, and thus, Adobe is content to let developers learn by example.&lt;br /&gt;&lt;br /&gt;And learn by example is how I had to do it.&lt;br /&gt;&lt;br /&gt;4) One of the best sources of examples of Adobe Bridge&lt;strong&gt;Talk&lt;/strong&gt; scripting is actually in the &lt;a href='http://www.adobe.com/devnet/bridge/'&gt;Adobe &lt;strong&gt;Bridge&lt;/strong&gt; SDK&lt;/a&gt;.  Yes, that sounds confusing, but it's true.&lt;br /&gt;&lt;br /&gt;Download said Adobe Bridge SDK.  It's about 4MB of compressed files.  Unzip, and inside are a few interesting PDFs, and a bunch of jsx files showing cool tricks using BridgeTalk (amongst other things).&lt;br /&gt;&lt;br /&gt;(I suggest you read the short section "Communicating with Other Applications" in the "Bridge CS4 JavaScript Guide.pdf" that comes in the docs folder in the Adobe Bridge SDK.)&lt;br /&gt;&lt;br /&gt;5) In brief, BridgeTalk sends javascript as a string, from one application to another (e.g. Illustrator to Flash), and sends the value of the last-executed-statement in said script back to the calling application.  It's a bit obtuse, but it's very powerful.&lt;br /&gt;&lt;br /&gt;6) Note that BridgeTalk is ASYNCHRONOUS.  And there is no synchronous mode.  So you have to be patient with writing the extra code to handle breaking a single synchronous procedure into smaller asynchronous steps.&lt;br /&gt;&lt;br /&gt;7) There is an extremely-poorly-documented means of launching ANY application via BridgeTalk.  e.g. you can run a Windows batch file, or trigger your source code versioning system, or invoke a custom tool you wrote in a non-Adobe language.  You can pretty much run anything you like.&lt;br /&gt;&lt;br /&gt;It's based around a function called "system".&lt;br /&gt;&lt;br /&gt;As with most Adobe stuff, this "system" function is extremely poorly documented.&lt;br /&gt;&lt;br /&gt;The only way I've found to use it is to call app.system('command-line.exe bla bla'); &lt;strong&gt;from within Bridge&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;So - get this - if you want to fire up a useful external program (e.g. source code control) from within a script that is automating Illustrator or Flash, you need to use BridgeTalk to send a script to Bridge, and the script you send to Bridge needs to include the app.system(&amp;lt;command-line&amp;gt;) invocation.  Talk about convoluted!&lt;br /&gt;&lt;br /&gt;But at least it works.&lt;br /&gt;&lt;br /&gt;Oh - and app.system(...) is SYNCHRONOUS, unlike BridgeTalk which is ASYNCHRONOUS.  Just to make sure your neurons are really getting a workout...&lt;br /&gt;&lt;br /&gt;8) If you've understood everything to this point, and want a cool trick to make it much easier to generate lengthy scripts that get shared between different Adobe products, you can use the toSource() function, as described by Justin of Ajar Productions in an article entitled "&lt;a href='http://ajarproductions.com/blog/2008/12/14/easy-and-readable-extendscript-to-jsfl-workflow/'&gt;Easy (and Readable) ExtendScript to JSFL Workflow&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;Remember : JSFL = scripting the Flash* development ("authoring") environment, whilst ExtendScript is used e.g. for Illustrator.  Justin's article covers writing an ExtendScript for Adobe Illustrator, that also uses BridgeTalk to get Flash to do some things, yet all within a single script file, and without much messy code.  Very nice work, Justin!&lt;br /&gt;&lt;br /&gt;(* Technically, JSFL is used for a few other products, not just Flash, but for my present purposes, it is accurate enough to say JSFL = scripting the Flash development environment.)&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Conclusion?&lt;br /&gt;&lt;br /&gt;Adobe makes things horribly painful to learn.&lt;br /&gt;&lt;br /&gt;Oh - and to use.  e.g. obtuse error messages.&lt;br /&gt;&lt;br /&gt;But despite the pain along the way, you can actually accomplish a huge amount.  If you have spare hair and a high pain threshold, you might find (as I am finding) that ExtendScript, JSFL and BridgeTalk are extremely rewarding tools to be able to use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-5654172147597860685?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/5654172147597860685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=5654172147597860685' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5654172147597860685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/5654172147597860685'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/cross-scripting-adobe-illustrator-and.html' title='Cross-scripting Adobe Illustrator and Adobe Flash'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-70695906568154103</id><published>2009-05-06T22:45:00.000-07:00</published><updated>2009-05-06T23:22:03.138-07:00</updated><title type='text'>BSOD, rdbss.sys, network dropouts, unwise_.exe, and the Win32/Heur virus/trojan</title><content type='html'>This will only help a very small number of you, but for the sake of these few...&lt;br /&gt;&lt;br /&gt;I have lost HOURS and HOURS this week with the internet connection on my email computer dropping out.&lt;br /&gt;&lt;br /&gt;"Repair Connection" worked a few times, but in the last few days even that stopped helping.&lt;br /&gt;&lt;br /&gt;Switching between LAN and wireless also helped initially, but in the past few days, not at all.&lt;br /&gt;&lt;br /&gt;It got to the point where I would lose ALL network access within a few minutes of boot.&lt;br /&gt;&lt;br /&gt;Just long enough to check email once.&lt;br /&gt;&lt;br /&gt;And it got to the point where I could only "fix" it by rebooting.&lt;br /&gt;&lt;br /&gt;So get this : my (slow) email machine, that takes roughly five minutes to do a shutdown/reboot cycle, had to be turned off and turned back on practically every time I wanted to check email or send an email!!!!!!!  Very frustrating!&lt;br /&gt;&lt;br /&gt;&lt;smaller&gt;(Nor was it just a case of "set &amp;amp; forget".  The laptop requires password entry at two points during the boot cycle, so rebooting it is a major distraction.)&lt;/smaller&gt;&lt;br /&gt;&lt;br /&gt;I tried using Internet Explorer's diagnose-connection-problems tool.  It informed me that "Windows has detected a problem with the winsock provider catalog on this computer", and offered to repair the problem.  But that didn't help.&lt;br /&gt;&lt;br /&gt;At around the same time, I began to find that the laptop would bring up the infamous "Blue Screen Of Death" (BSOD) during shutdown.  Every time.  Yet another source of pain in the email-checking routine.&lt;br /&gt;&lt;br /&gt;And of course, I'm used to checking email at least every hour, as it is a primary means of communication with customers...&lt;br /&gt;&lt;br /&gt;The BSOD was a red herring.  It said that rdbss.sys had been unloaded "without canceling pending operations" - whatever that means.  I searched and searched, and of course, found nothing that helped.&lt;br /&gt;&lt;br /&gt;I tried resetting the Winsock stack - as suggested by some articles - but the problem persisted.&lt;br /&gt;&lt;br /&gt;What if...  what if this is a symptom of a common virus?&lt;br /&gt;&lt;br /&gt;I haven't had a virus on any of my computers in something like six or seven years.&lt;br /&gt;&lt;br /&gt;I don't actually have a virus scanner installed - they usually slow a computer down horribly.&lt;br /&gt;&lt;br /&gt;As a very technically-oriented programmer, I am very familiar with the limitations of technology, and instinctively manage to steer clear of most sources of viruses.&lt;br /&gt;&lt;br /&gt;But whatever was going on with my email computer was very strange, and it was wasting hours and hours, so I decided to give it a virus scan.&lt;br /&gt;&lt;br /&gt;AVG became my tool of choice.&lt;br /&gt;&lt;br /&gt;I downloaded it onto another computer and transferred the installer across via USB stick.&lt;br /&gt;&lt;br /&gt;Fortunately, it allowed me to install without needing to access the internet - e.g. for updated virus signatures.&lt;br /&gt;&lt;br /&gt;Pretty quickly, the virus scan turned up a "Win32/Heur" virus in a file called "C:\Windows\fonts\unwise_.exe".  Aha!  Likely the culprit!&lt;br /&gt;&lt;br /&gt;And sure enough it was.  More on the virus in a moment, but I used Task Manager to kill the running instance of unwise_.exe, and within minutes, my network access was working properly again!&lt;br /&gt;&lt;br /&gt;It might even be that unwise_.exe and its Win32/Heur were not &lt;strong&gt;directly&lt;/strong&gt; killing the network, but perhaps were engaging in network activity that my network router found objectionable.  Or maybe the problem was indeed entirely within that infected laptop.&lt;br /&gt;&lt;br /&gt;Either way, virus gone, problem solved.&lt;br /&gt;&lt;br /&gt;And the BSODs have disappeared too!&lt;br /&gt;&lt;br /&gt;So if you're having strange network dropouts minutes after boot... it might just be a virus.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;A couple of thoughts about this particular virus :&lt;br /&gt;&lt;br /&gt;It uses the file name "unwise_.exe" - note the underscore.  I find this intriguing.  "unwise.exe" (no underscore) is (IIRC) the name of a popular program uninstaller that works with a very large number of programs.  (Is it part of the "InstallShield" suite?  I'm hazy on the details now...)&lt;br /&gt;&lt;br /&gt;So presumably, the virus writers chose the name "unwise_.exe" (note the underscore) because of its similarity to "unwise.exe" (no underscore) - i.e. to try to make it look more innocuous.&lt;br /&gt;&lt;br /&gt;But to the trained eye, it was every bit suspicious.&lt;br /&gt;&lt;br /&gt;First up, whilst "unwise.exe" (no underscore) is a common name, "unwise_.exe" (note the underscore) is NOT a common name, and uncommon file names that are so suspiciously similar to common file names don't just happen by accident!&lt;br /&gt;&lt;br /&gt;Secondly, the file had both the SYSTEM and HIDDEN file attributes set.  Oh yeah - that means you won't actually be able to find it yourself, unless you do something like go to the Command Prompt and type something like "dir C:\Windows\fonts\*.exe /ah".&lt;br /&gt;&lt;br /&gt;Thirdly, no executables ever live in the C:\Windows\fonts folder.  That alone is almost sufficient proof that the file is malicious.  But what a clever choice - the C:\Windows\fonts folder cannot actually be browsed in Windows Explorer like other folders can.  If you launch Windows Explorer and navigate to C:\Windows\fonts, you'll see a special "fonts list" view, which fails to show the offending "unwise_.exe", even though it is in that folder.&lt;br /&gt;&lt;br /&gt;So whoever wrote this "unwise_.exe" thing knew what they were doing, and went to great lengths to hide their malicious program's presence on affected systems.&lt;br /&gt;&lt;br /&gt;Note further that this virus installs itself to start at system boot (or user logon - one or the other, and I'm not quite sure which) and to run under the SYSTEM account.  That's another clue that it's a bad boy - the real "unwise.exe", being an uninstaller, and thus always launched by the USER not the SYSTEM, would not be found in the Task Manager running under the SYSTEM account.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;Oh - and before you flame me - someone else had been using my email computer quite heavily around the time of the infection (1-May-2009 was the date of infection, based on the file datetime stamp on the C:\Windows\fonts\unwise_.exe file), and so whilst that probably means I need to install an anti-virus program permanently if I'm going to let them keeping using my computer, it does potentially vindicate my "I don't need an anti-virus program for myself" attitude of many years.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;Thanks for reading!  I hope this helps some of you...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-70695906568154103?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/70695906568154103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=70695906568154103' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/70695906568154103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/70695906568154103'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/05/bsod-rdbsssys-network-dropouts.html' title='BSOD, rdbss.sys, network dropouts, unwise_.exe, and the Win32/Heur virus/trojan'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7373051301930716725</id><published>2009-04-15T22:29:00.000-07:00</published><updated>2009-04-15T22:38:33.402-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><title type='text'>Flash, translate transform, and x/y co-ordinates</title><content type='html'>"Self Documenting Code" is my mantra - code that is intuitive.&lt;br /&gt;&lt;br /&gt;Flash is not.&lt;br /&gt;&lt;br /&gt;I lost yet another hour or two trying to get a simple translate transform working.  The doco fails to mention that :&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;If you set x or y for a DisplayObject, it effectively overwrites any translate transform in the current transformation matrix for the DisplayObject.&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I hate to be harsh, but you could at least mention this in the documentation!  XAML transformations apply in &lt;em&gt;addition&lt;/em&gt; to any x/y co-ordinates set on an object.  Not so in Flash.&lt;br /&gt;&lt;br /&gt;And so if you apply a transformation, and then set a DisplayObject's x/y properties, you might be puzzled wondering why the translation component of the transformation is not taking effect.&lt;br /&gt;&lt;br /&gt;That's why.&lt;br /&gt;&lt;br /&gt;It makes sense enough when you understand it, but it proves once again that Adobe is often worse than useless at writing documentation and at designing intuitive APIs.  Why did I have to spend an hour or two figuring this out for myself?  It should have been documented, or been more apparent in the API itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7373051301930716725?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7373051301930716725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7373051301930716725' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7373051301930716725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7373051301930716725'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/flash-translate-transform-and-xy-co.html' title='Flash, translate transform, and x/y co-ordinates'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-7609168504602084126</id><published>2009-04-09T01:11:00.000-07:00</published><updated>2009-04-09T01:18:13.454-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><title type='text'>Flash automatically merges shapes at compile time</title><content type='html'>Here be dragons.&lt;br /&gt;&lt;br /&gt;Flash automatically combines shapes at compile time.&lt;br /&gt;&lt;br /&gt;So if you were expecting to place two or more shapes on the stage and be able to access them via the stage's getChildAt method, you're in for an interesting time.&lt;br /&gt;&lt;br /&gt;It's not as simple as "Flash combines all shapes into a single shape".  It seems to work based on z-index.&lt;br /&gt;&lt;br /&gt;Suppose you add two shapes to the stage, then add a textbox, then add a third shape.&lt;br /&gt;&lt;br /&gt;You'll discover at runtime that the first two shapes have been merged into one, but the third has not.&lt;br /&gt;&lt;br /&gt;If you play with the z-index ("send to back", "send to front") in the Flash IDE, you'll discover that the ONLY thing that controls whether or not two particular shapes get merged at compile time is whether or not they are neighbours in the z-index.&lt;br /&gt;&lt;br /&gt;(Technically, they need to be part of the same unbroken sequence of shapes in the z-index, so for example if you add three shapes to the stage in succession, they will be combined into a single shape at compilation time, because they will appear one after the other in the z-index.)&lt;br /&gt;&lt;br /&gt;Unfortunately, I failed to find any documentation which mentions this, or any other Flash developers having their plans thwarted by this 'feature'.  So I hereby post my "here be dragons" flag.&lt;br /&gt;&lt;br /&gt;The solution?  If you NEED the shapes to be drawn in Flash (as opposed to drawn in ActionScript at runtime) and you NEED them to be separate shapes at runtime, then cut them out of your document and paste them into a temporary document, then paste one shape back, then create an off-stage dynamic text field (to form a z-index divider), then paste in the next shape, and so on, and so forth.&lt;br /&gt;&lt;br /&gt;Of course, it should be very rare that you need to do this kind of thing, but I came across such an instance today, and lost several hours due to this seemingly undocumented 'feature'.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-7609168504602084126?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/7609168504602084126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=7609168504602084126' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7609168504602084126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/7609168504602084126'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/flash-automatically-merges-shapes-at.html' title='Flash automatically merges shapes at compile time'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-1899483813717318645</id><published>2009-04-07T18:20:00.000-07:00</published><updated>2009-04-07T18:34:41.582-07:00</updated><title type='text'>Accessing your Ubuntu partition from Windows</title><content type='html'>&lt;a href='http://www.chrysocome.net/virtualvolumes'&gt;Virtual Volumes&lt;/a&gt; is beta software, but for read-only access to an Ubuntu partition, its everything I need.&lt;br /&gt;&lt;br /&gt;I have a relatively recent installation of Ubuntu, and it is brilliant.  Its native support of NTFS means I can access all my Windows files from Ubuntu.  But going the other way is trickier.  Virtual Volumes fills this gap (for my simple requirements).&lt;br /&gt;&lt;br /&gt;Virtual Volumes is a desktop app, not a kernel driver.  For my purposes, that was a benefit, because it meant I didn't need to reboot after installation, and there is nothing consuming extra system resources when I'm not accessing my Linux partition.&lt;br /&gt;&lt;br /&gt;The same guy who created Virtual Volumes also created a very popular tool called &lt;a href='http://www.chrysocome.net/explore2fs'&gt;explore2fs&lt;/a&gt;, but for no apparent reason, it failed to work with my recent Ubuntu installation.&lt;br /&gt;&lt;br /&gt;I also tried DiskInternals' &lt;a href='http://www.diskinternals.com/linux-reader/'&gt;Linux-reader&lt;/a&gt; which again, is popular and probably works for many Linux distributions, but failed to work with my recent Ubuntu installation.&lt;br /&gt;&lt;br /&gt;In short, Virtual Volumes is well worth a try, either as your first choice, or as a backup option if other options fail.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;(Thanks to &lt;a href='http://www.ubuntugeek.com/tools-to-access-linux-partitions-from-windows.html'&gt;UbuntuGeek.com&lt;/a&gt; for pointing me to the DiskInternals Linux-Reader tool.)&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;P.S. If you want a kernel-mode driver, &lt;a href='http://www.fs-driver.org/'&gt;fs-driver.org&lt;/a&gt; looks promising, but I can't vouch for it.&lt;br /&gt;&lt;br /&gt;P.P.S. Huge kudos to chrysocome.net!  Virtual Volumes is my friend.  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-1899483813717318645?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/1899483813717318645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=1899483813717318645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1899483813717318645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1899483813717318645'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/accessing-your-ubuntu-partition-from.html' title='Accessing your Ubuntu partition from Windows'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6544386728526782541</id><published>2009-04-07T02:12:00.001-07:00</published><updated>2009-04-07T02:34:04.026-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='aspnet_compiler'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET framework'/><title type='text'>aspnet_compiler and its mysterious silent failures</title><content type='html'>Around the year 2000, Microsoft started actually doing some things extremely well.&lt;br /&gt;&lt;br /&gt;Internet Explorer 4 was the most abysmal web browser ever to disgrace the human race, but Internet Explorer 5 was remarkably solid.&lt;br /&gt;&lt;br /&gt;Windows ME was their buggiest and single worst desktop operating system ever, but Windows 2000 was impressive.&lt;br /&gt;&lt;br /&gt;Visual Basic 6, ASP, VBA, COM and all that stuff was a bit same-old, same-old - a clunky development experience.  But the .NET framework truly ushered in a new era of programming productivity.&lt;br /&gt;&lt;br /&gt;The .NET framework itself is awesome.  Microsoft has never produced anything better, in my opinion, than the .NET framework.&lt;br /&gt;&lt;br /&gt;But within the .NET framework lives an incredibly buggy tool called aspnet_compiler.&lt;br /&gt;&lt;br /&gt;Unfortunately, some of us are forced to rely upon it.&lt;br /&gt;&lt;br /&gt;It frequently fails with no error message.&lt;br /&gt;&lt;br /&gt;Nada on the console.&lt;br /&gt;&lt;br /&gt;Nada in the event log.&lt;br /&gt;&lt;br /&gt;Just absolute silence.&lt;br /&gt;&lt;br /&gt;It pretends it has happily successfully finished, but in actual fact, something has gone wrong and it absolutely refuses to tell you about it.&lt;br /&gt;&lt;br /&gt;And that wastes hours.  And hours.  And did I mention, hours.&lt;br /&gt;&lt;br /&gt;Today I lost about an hour and a half.  Aspnet_compiler would succeed if I excluded any one of my dozen or so subfolders in my web root folder.  But if I tried to include all my subfolders, it would grind away as if it was working successfully, and then it would suddenly fail without any error message.&lt;br /&gt;&lt;br /&gt;I got it to the point that I could compile successfully if I excluded any one of several files in one particular folder, but if I tried to include them all, it would fail with no error message.&lt;br /&gt;&lt;br /&gt;But if I removed a different subfolder from the root folder, I could include all those files that previously I could include all-but-one of.&lt;br /&gt;&lt;br /&gt;It was aspnet_compiler demonstrating its classic fickleness.  I think Microsoft invented it for no other purpose than to waste developers' time.  OK, maybe that's getting a little too harsh...&lt;br /&gt;&lt;br /&gt;Anyhow, lo-and-behold, when I copied the entire problematic precompilation-input folder to another location and tried again, it failed, but this time with a compilation error message that at least I can do something about.&lt;br /&gt;&lt;br /&gt;What was the problem?&lt;br /&gt;&lt;br /&gt;It seems that aspnet_compiler is unable to cope with long file paths.  It seems that once the absolute file path to any file in the precompilation input exceeds some threshhold, aspnet_compiler becomes very fragile, and sometimes succeeds, but with slightly different input, sometimes fails.&lt;br /&gt;&lt;br /&gt;By copying my source code to a temporary folder near the root of my drive, I shortened the maximum file path, and thus avoided aspnet_compiler's file-path-length issues.&lt;br /&gt;&lt;br /&gt;But that's not the only stupid thing aspnet_compiler is known to do.&lt;br /&gt;&lt;br /&gt;For example, sure, at least I'm getting a compilation error now.  But the compilation error I'm getting actually has nothing to do with any of the files which, if I exclude, it all compiles successfully.  i.e. the thing its tripping over now is not a real issue.  But at least it gives me something to focus more specifically on.&lt;br /&gt;&lt;br /&gt;Such are the vagueries of life with aspnet_compiler.&lt;br /&gt;&lt;br /&gt;But wait, there's more!&lt;br /&gt;&lt;br /&gt;Suppose you have two ASPX files in the same namespace and with the same base class name, and suppose it works fine during testing in IIS before precompilation.  All good and well, you'd think.  And then you try to precompile.  And aspnet_compiler dies saying nothing more than that it "failed with error code 1" (or is it 0? it's a while since I last had this problem, though I've had it too many times before).  The cause?  aspnet_compiler requires that all class names throughout the entire web app be unique within their respective namespaces.  Fair enough.  It's a reasonably intuitive rule now that you mention it.  But I had to figure it out for myself.  'Coz aspnet_compiler doesn't tell you what's wrong in this instance - it just dies with that very obscure error message.&lt;br /&gt;&lt;br /&gt;And so I regret that I ever bought Microsoft's hype that aspnet_compiler is now the best and recommended pathway to shipping websites.  The tool is unstable, unreliable, and frequently complains about non-existent problems.&lt;br /&gt;&lt;br /&gt;But aside from aspnet_compiler, I love the .NET framework.  It's the best thing Microsoft has ever done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6544386728526782541?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6544386728526782541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6544386728526782541' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6544386728526782541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6544386728526782541'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/aspnetcompiler-and-its-mysterious.html' title='aspnet_compiler and its mysterious silent failures'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-4622554969069065719</id><published>2009-04-06T16:49:00.001-07:00</published><updated>2009-04-06T17:01:49.104-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='anti-spam'/><title type='text'>Mail server setup, mailing lists, and Microsoft's "Smart Network Data Services"</title><content type='html'>I received a weird email today, and it first it looked like spam.  It claimed to be from staff@hotmail.com, and I don't interact with Hotmail.com.&lt;br /&gt;&lt;br /&gt;But on closer examination of the message, I realised there was something here worth investigating further.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Dear Jonathan Field,&lt;br /&gt;&lt;br /&gt;Smart Network Data Services has determined that the trusted email address for your network 203.89.209.146 through 203.89.209.150 has either changed or the email address previously trusted is no longer valid.  Consequently, your access to data for this network has been disabled, pending re-authorization.&lt;br /&gt;&lt;br /&gt;Please visit the Smart Network Data Services site to remove the network and re-add the network with a valid trusted email address.&lt;br /&gt;&lt;br /&gt;You are receiving this because you have signed up to be part of a preview release of Smart Network Data Services, or a Smart Network Data Services user has requested that this email be sent to this address. Smart Network Data Services is a revolutionary Windows Live Mail initiative, designed to allow everyone who owns IP space to contribute to the fight against spam and protect e-mail as a valued communications, productivity and commerce tool. If you have questions about our privacy policy, please read our privacy statement available at http://privacy.live.com.&lt;/blockquote&gt;&lt;br /&gt;I don't have a clue what "Smart Network Data Services" is, and I'm pretty sure I never signed up for a preview of it, but I Google it and it's actually quite interesting.&lt;br /&gt;&lt;br /&gt;&lt;a href='https://postmaster.live.com/snds/'&gt;Smart Network Data Services&lt;/a&gt; home page.&lt;br /&gt;&lt;br /&gt;Yeah - their website is hard to navigate, and poorly written, but there's some very useful data inside.&lt;br /&gt;&lt;br /&gt;If you run a mail server and/or have clients with mailing lists, Smart Network Data Services promises to be of some assistance in the process of identifying how Hotmail treats messages from your mail servers.&lt;br /&gt;&lt;br /&gt;I only just came across it now, and I found it extremely hard to navigate, so don't ask me for help using it, but I did manage to sign up and access an "IP address status" page - which thankfully told me I'm not a spammer.  :o)&lt;br /&gt;&lt;br /&gt;Its sad but true that managing a legitimate mailing list or mail server in the 21st century requires highly developed technical skills, and constant monitoring of the ever-changing anti-spam landscape.  Within that context, Microsoft's Smart Network Data Services is a new tool to help keep the emails flowing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-4622554969069065719?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/4622554969069065719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=4622554969069065719' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4622554969069065719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4622554969069065719'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/mail-server-setup-mailing-lists-and.html' title='Mail server setup, mailing lists, and Microsoft&apos;s &quot;Smart Network Data Services&quot;'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8630311018228454360</id><published>2009-04-06T03:32:00.001-07:00</published><updated>2009-04-06T03:34:47.002-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft SilverLight'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><title type='text'>Flash vs SilverLight : SilverLight will win (my prediction)</title><content type='html'>I've been living in Adobe Flash / ActionScript land for the last few weeks, and there has been a very unexpected side-effect.&lt;br /&gt;&lt;br /&gt;Today, when I was working in Microsoft Visual Studio again, it was a joy to use!&lt;br /&gt;&lt;br /&gt;I always used to think Microsoft Visual Studio was HIDEOUSLY slow and inefficient - and it is - but after inflicting Adobe Flash on myself for a week and a half, Visual Studio seems absolutely awesome.&lt;br /&gt;&lt;br /&gt;As yet another example of the sheer stupidity which pervades Adobe Flash and its implementation of ActionScript :&lt;br /&gt;&lt;br /&gt;1) Grab a big Adobe Flash project - you know, one that takes ten seconds to build.&lt;br /&gt;2) Open it in Flash CS4.&lt;br /&gt;3) Press Ctrl+Enter to run it in test mode.&lt;br /&gt;4) Close the runner.&lt;br /&gt;5) Press Ctrl+Enter to run it again, as if you just wanted to check out one more thing.&lt;br /&gt;&lt;br /&gt;Guess what?&lt;br /&gt;&lt;br /&gt;Adobe Flash is so stupid, that it doesn't notice that nothing has changed since the last build, and so it rebuilds the project, wasting more time.&lt;br /&gt;&lt;br /&gt;And it doesn't seem to have any incremental build either.  If you have a large project, and change one tiny thing ANYWHERE in the project, you face the entire laborious build process once again.&lt;br /&gt;&lt;br /&gt;On a fast (3ghz QuadCore) computer, I am finding Flash makes debugging a major chore by making tedious to iteratively change and test.&lt;br /&gt;&lt;br /&gt;Visual Studio in contrast?  Do a debug run, and it will build and run.  Run again without changing anything?  It knows it doesn't need to rebuild, so it starts instantly.  Change anything?  It supports incremental build to a certain extent.&lt;br /&gt;&lt;br /&gt;It makes Adobe Flash look like it comes from the 90s, or earlier.  Except, that it's actually Adobe Flash CS4 - the very latest and greatest in 2009.  Ouch - that sucks.&lt;br /&gt;&lt;br /&gt;Oh - and I thought Visual Studio was bad, because the incremental build is actually quite limited.  Turns out, Flash seems to have no incremental build at all.&lt;br /&gt;&lt;br /&gt;And don't talk about load times - I thought Visual Studio load times were bad.  But after Flash, it feels zippy.&lt;br /&gt;&lt;br /&gt;And today, Flash crashed on me literally, hmmm, about ten times.  I mean, crashed, dead, have to restart the app, and sorry about any unsaved work.  That kind of crash.&lt;br /&gt;&lt;br /&gt;Visual Studio is INCREDIBLY inefficient, but at least it hardly ever crashes.  And Flash's inefficiencies make Visual Studio look like a racecar.&lt;br /&gt;&lt;br /&gt;Add to this the documentation errors and erroneous compiler errors that define Flash 10 with ActionScript 3, and you have the perfect recipe for the most imperfect program I ever imagined could wear the Adobe name.&lt;br /&gt;&lt;br /&gt;If it were a house, the "for sale" sign out front would say "full of potential".&lt;br /&gt;&lt;br /&gt;Translation : it needs a LOT of work.&lt;br /&gt;&lt;br /&gt;My bet?&lt;br /&gt;&lt;br /&gt;Adobe will drop the ball (or continue to drop the ball).&lt;br /&gt;&lt;br /&gt;SilverLight will win.&lt;br /&gt;&lt;br /&gt;And it will take roughly 8 to 10 years to happen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8630311018228454360?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8630311018228454360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8630311018228454360' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8630311018228454360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8630311018228454360'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/flash-vs-silverlight-silverlight-will.html' title='Flash vs SilverLight : SilverLight will win (my prediction)'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8755936512986126790</id><published>2009-04-05T16:37:00.001-07:00</published><updated>2009-04-06T15:14:45.585-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bazaar'/><title type='text'>Graphical add/commit in Bazaar without the slowness of TortoiseBZR</title><content type='html'>How can you quickly &amp;amp; easily pick which files you want to add to Bazaar?&lt;br /&gt;&lt;br /&gt;I've had too many painful experiences (not Bazaar's fault) of going "bzr add", and then discovering that amidst the dozens of files I DID want to add, there were a whole bunch that I DIDN'T.&lt;br /&gt;&lt;br /&gt;Removing them is a bit of a pain - I tend to use very long self-descriptive folder names and file names, so if a big "bzr add" operation added dozens of files, and I needed to manually remove perhaps a dozen or more, it was very time inefficient.&lt;br /&gt;&lt;br /&gt;Fortunately, Bazaar has the answer!  I just didn't discover it until yesterday.&lt;br /&gt;&lt;br /&gt;bzr qadd&lt;br /&gt;&lt;br /&gt;That little "q" at the beginning of the "add" command brings up a GUI window, allowing you to very quickly &amp;amp; easily select exactly which files you want added.&lt;br /&gt;&lt;br /&gt;Bazaar, I love you!  :o)&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;P.S. You can also use "bzr qcommit", which is a FABULOUS way to do a partial commit.  And "bzr qdiff" if you want a diff that is easier to read than "bzr diff".&lt;br /&gt;&lt;br /&gt;&lt;div style='margin-left:20px;margin-right:20px;border:solid 1px white;padding-left:15px;padding-right:15px;'&gt;&lt;p&gt;UPDATE : The preceding works fine if you used the Windows installer for Bazaar.  If you are using Linux, you need to install a Bazaar plugin called QBzr - see bialix's comments on this article.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8755936512986126790?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8755936512986126790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8755936512986126790' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8755936512986126790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8755936512986126790'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/graphical-addcommit-in-bazaar-without.html' title='Graphical add/commit in Bazaar without the slowness of TortoiseBZR'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-4203370087543273951</id><published>2009-04-05T16:02:00.000-07:00</published><updated>2009-04-05T16:23:15.168-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='MOUSE_OVER'/><category scheme='http://www.blogger.com/atom/ns#' term='MOUSE_OUT'/><category scheme='http://www.blogger.com/atom/ns#' term='SimpleButton'/><title type='text'>Flash SimpleButton, and MOUSE_OVER and MOUSE_OUT not firing</title><content type='html'>Adobe Flash documentation is often worse than useless.  Useless would be "tells us nothing we didn't already know".  WORSE than useless is "tells us information that is NOT correct, causing us to waste time".&lt;br /&gt;&lt;br /&gt;Their flash.display.SimpleButton is the culprit once again.&lt;br /&gt;&lt;br /&gt;I was dynamically generating SimpleButton instances in ActionScript 3, and adding MOUSE_OVER and MOUSE_OUT event handlers.&lt;br /&gt;&lt;br /&gt;But the event handlers were never firing.&lt;br /&gt;&lt;br /&gt;I reviewed &lt;a href='http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/SimpleButton.html'&gt;the documentation&lt;/a&gt; - the SimpleButton definitely supports the MOUSE_OVER and MOUSE_OUT events.&lt;br /&gt;&lt;br /&gt;I tried adding the event handlers to the flash.text.TextField instances which formed the button states, but that didn't work either - the events simply never ever fired.&lt;br /&gt;&lt;br /&gt;I finally figured out what's going wrong.  It's that SimpleButton constructor once again.&lt;br /&gt;&lt;br /&gt;Here's what the doco says (&lt;strong&gt;false info - worse than useless&lt;/strong&gt;) about the SimpleButton constructor :&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Any or all of the display objects that represent the various button states can be set as parameters in the constructor.&lt;/blockquote&gt;&lt;br /&gt;ANY OR ALL ... CAN BE.  In other words, it is OPTIONAL to set the various states using the constructor.&lt;br /&gt;&lt;br /&gt;&lt;a href='http://selfdocumentingcode.blogspot.com/2009/04/flash-bugs-dynamic-simplebutton-gotcha.html'&gt;In a previous blog post&lt;/a&gt;, I noted that, despite the CLAIM that the constructor arguments are optional, the first argument is actually MANDATORY.&lt;br /&gt;&lt;br /&gt;If you don't specify the first argument, the button never transitions between states, even if you set the states later using the upState, overState etc properties.&lt;br /&gt;&lt;br /&gt;But if you DO specify the first argument, the up-and-over animation works correctly.&lt;br /&gt;&lt;br /&gt;That was from that previous blog post.&lt;br /&gt;&lt;br /&gt;Well, the new lesson for today's blog post is that in fact ALL FOUR arguments to the constructor are MANDATORY if you wish to get MOUSE_OVER and MOUSE_OUT events from the SimpleButton.&lt;br /&gt;&lt;br /&gt;It doesn't make sense, and it makes mockery of their (poor as too often the case) documentation, and in fact makes mockery of Adobe's ability to design an intuitive API, but it is the case.&lt;br /&gt;&lt;br /&gt;The one saving grace is that we can specify the SAME DisplayObject for all four constructor arguments.  e.g.&lt;br /&gt;&lt;br /&gt;var sb:SimpleButton = new SimpleButton(MySprite, MySprite, MySprite, MySprite);&lt;br /&gt;&lt;br /&gt;(And of course, the other way you can do it is subclass SimpleButton and set the upState, overState etc properties in your own constructor.  Basically, by the end of the constructor, those values must be set.)&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;As a final note, I was just about to paste the simple test code I whipped up, to make it extremely easy for you to reproduce my test results, but as I did so, Adobe Flash suddenly died on me and completely disappeared from the taskbar without even its usual "Adobe Flash just died" popup message.&lt;br /&gt;&lt;br /&gt;All I can say is that I am disgusted with Adobe Flash - not only is the documentation often worse than useless, but the program itself is fragile, and crashes on me usually more than once per work day.&lt;br /&gt;&lt;br /&gt;And this is Flash CS4 - their latest and greatest...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-4203370087543273951?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/4203370087543273951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=4203370087543273951' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4203370087543273951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4203370087543273951'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/flash-simplebutton-and-mouseover-and.html' title='Flash SimpleButton, and MOUSE_OVER and MOUSE_OUT not firing'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-9064146309790131797</id><published>2009-04-03T21:01:00.000-07:00</published><updated>2011-04-14T17:17:36.526-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bazaar'/><title type='text'>Merging unrelated branches in Bazaar</title><content type='html'>&lt;em&gt;The skinny : 'cd &amp;lt;working-tree-to-merge-into&amp;gt;', then 'bzr merge &amp;lt;branch-to-merge-with&amp;gt; -r0..-1', and then 'bzr commit "Merged with {bla}"'.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I continue to love Bazaar.&lt;br /&gt;&lt;br /&gt;I've wondered for a while : "How can I merge two completely unrelated branches?"&lt;br /&gt;&lt;br /&gt;Scenario : I'm working on a large website with an extensive ASP.NET section, and an extensive Flash section.  The ASP.NET section is very mature.  The Flash section has just begun.  I want to be able to version control the Flash stuff in the same repository as the ASP.NET stuff, but in unrelated branches, and eventually merge the branches once the Flash stuff matures somewhat.&lt;br /&gt;&lt;br /&gt;Can do!  But it took a bit of figuring out.&lt;br /&gt;&lt;br /&gt;Along the way, I kept bumping my head against this error message from Bazaar :&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;bzr: ERROR: Branches have no common ancestor, and no merge base revision was specified.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Suppose my folders were :&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&lt;br /&gt;&lt;br /&gt;and&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\FlashStuff&lt;br /&gt;&lt;br /&gt;I was trying to do :&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff&lt;br /&gt;&lt;br /&gt;That wasn't working, so I tried using the --revision= option to specify a base revision (as hinted by the error message) :&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff --revision=1&lt;br /&gt;&lt;br /&gt;Still no go.&lt;br /&gt;&lt;br /&gt;So I looked at the --change= option.&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff --change=1..27&lt;br /&gt;&lt;br /&gt;(27 being the latest revision number in the FlashStuff branch.)&lt;br /&gt;&lt;br /&gt;Still no go - it tells me that the --change= option cannot handle revision ranges - it can only handle one specific revision number.&lt;br /&gt;&lt;br /&gt;OK, so what if I try to integrate just the very latest change?&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff --change=27&lt;br /&gt;&lt;br /&gt;That didn't work either.  Instead, it created lots of conflicts.&lt;br /&gt;&lt;br /&gt;Ah - finally I think I see the light!&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff --change=1&lt;br /&gt;&lt;br /&gt;Yes!  Progress!  It worked!  i.e. I have to start with the very first change in the unrelated branch.&lt;br /&gt;&lt;br /&gt;Now will it let me merge the remaining changes?&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff&lt;br /&gt;&lt;br /&gt;Nope - it complains that I have uncommitted changes.&lt;br /&gt;&lt;br /&gt;Easily fixed :&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr commit -m "Merged with FlashStuff revision 1"&lt;br /&gt;&lt;br /&gt;Good.&lt;br /&gt;&lt;br /&gt;And now let's try the merge again :&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff&lt;br /&gt;&lt;br /&gt;Bonanza!  It worked!&lt;br /&gt;&lt;br /&gt;And I have now successfully merged two COMPLETELY UNRELATED branches that lived under the same repository.&lt;br /&gt;&lt;br /&gt;In summary, the quick way to do it :&lt;br /&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff --change=1&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr commit -m "Merged with FlashStuff revision 1"&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr commit -m "Merged fully with FlashStuff"&lt;br /&gt;&lt;br /&gt;And I'm a happy camper.  :o)&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;UPDATE : Thanks to bialix (in the comments) for pointing out a simpler way to accomplish the same thing :&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr merge ..\FlashStuff -r0..-1&lt;br /&gt;C:\BzrRepo\AspDotNetStuff&amp;gt; bzr commit -m "Merged with FlashStuff"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Slightly different syntax, accomplishes the same thing, but more concise.  Did I mention I love Bazaar?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-9064146309790131797?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/9064146309790131797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=9064146309790131797' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9064146309790131797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9064146309790131797'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/merging-unrelated-branches-in-bazaar.html' title='Merging unrelated branches in Bazaar'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-1894658711192208421</id><published>2009-04-02T17:53:00.000-07:00</published><updated>2009-04-02T18:25:59.482-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActionScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='flash.display.TextField'/><title type='text'>Flash bugs: dynamic TextField and letterSpacing issue</title><content type='html'>I'm creating TextField instances in ActionScript, modeled after one TextField instance in the Flash UI designer.&lt;br /&gt;&lt;br /&gt;There are two stupid problems.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Problem 1:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The first is that Flash is very forgetful.&lt;br /&gt;&lt;br /&gt;Suppose I go :&lt;br /&gt;&lt;br /&gt;tb.text = 'Some new text';&lt;br /&gt;&lt;br /&gt;Just like that, key TextField settings are lost!  Idiotic.  Things like letterSpacing get reset to zero.&lt;br /&gt;&lt;br /&gt;The solution (&lt;a href='http://bobspace.wordpress.com/2006/09/28/flash-yourmomgettextformat-is-the-key-to-letterspacing/'&gt;noted by others&lt;/a&gt;) is to :&lt;br /&gt;&lt;br /&gt;var tf:flash.text.TextFormat = tb.getTextFormat();&lt;br /&gt;tb.text = 'Some new text';&lt;br /&gt;tb.setTextFormat(tf);&lt;br /&gt;&lt;br /&gt;If that makes sense to anyone, I suppose there probably are airborne sows.&lt;br /&gt;&lt;br /&gt;But it kinda does the trick.  &lt;em&gt;Kinda&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Enter: problem the second&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;If I'm doing all this with an embedded font, the aforesaid hack DOES NOT WORK.&lt;br /&gt;&lt;br /&gt;At least, not without a bit more effort.&lt;br /&gt;&lt;br /&gt;I had the original textbox, built in to the Flash stage.  Let's call it tbOriginal.&lt;br /&gt;&lt;br /&gt;Then I have my dynamic textboxes, modelled off the original.&lt;br /&gt;&lt;br /&gt;tbCreatedAtRuntime.text = 'Some text here';&lt;br /&gt;tbCreatedAtRuntime.setTextFormat(tbOriginal.getTextFormat());&lt;br /&gt;&lt;br /&gt;Nice - does the trick, except that the letterSpacing is shot.&lt;br /&gt;&lt;br /&gt;So I play with the letter spacing.  I try all sorts of values.&lt;br /&gt;&lt;br /&gt;tbCreatedAtRuntime.text = 'Some text here';&lt;br /&gt;var tf:flash.text.TextFormat = tbOriginal.getTextFormat();&lt;br /&gt;tf.letterSpacing = 0.55; /* I tried lots of different values here. */&lt;br /&gt;tbCreatedAtRuntime.setTextFormat(tf);&lt;br /&gt;&lt;br /&gt;The problem was that, regardless of what letterSpacing value I set, it would often make no difference whatsoever to the overall length of the string.&lt;br /&gt;&lt;br /&gt;But it was weirder than that.  Once I got down to about 0.54, the string length jumped down very significantly.  It was like the letterSpacing had a very course rounding applied, such that there was only one "real" letterSpacing option per 0.5 increment of the letterSpacing value.&lt;br /&gt;&lt;br /&gt;But I knew this couldn't be the total story, because the tbOriginal was using a letterSpacing of 0.75, and on screen it was longer than tbCreatedAtRuntime with letterSpacing around 0.5, and shorter than tbCreatedAtRuntime with letterSpacing around 1, and as stated earlier, tbCreatedAtRuntime would treat letterSpacing of 0.75 the same as letterSpacing of 1.0.&lt;br /&gt;&lt;br /&gt;What gives?&lt;br /&gt;&lt;br /&gt;Fortunately, whilst not intuitive (after all, this is Flash isn't it?), the documentation did this time give me the clue I needed.&lt;br /&gt;&lt;br /&gt;It turns out that Flash only supports integer values&lt;sup&gt;(1)&lt;/sup&gt; for letterSpacing for "device fonts".  My brain whirred away for a microsecond and I realised what the problem was.&lt;br /&gt;&lt;br /&gt;I was using a special font, but I hadn't explicitly told my dynamically-created TextField to use font embedding.  I just presumed that, since it got its TextFormat from tbOriginal, it would get the same font embedding as tbOriginal.  Not so.&lt;br /&gt;&lt;br /&gt;So now I explicitly tell tbCreatedAtRuntime to use the same font embedding as tbOriginal :&lt;br /&gt;&lt;br /&gt;tbCreatedAtRuntime.embedFonts = tbOriginal.embedFonts;&lt;br /&gt;&lt;br /&gt;... and now at last, letterSpacing works as expected.  Whew!&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;But can you permit me to lament once more just how STUPID this design (or lack of design) is?&lt;br /&gt;&lt;br /&gt;Adobe might be good at graphics, but they are very bad at development tools and APIs.&lt;br /&gt;&lt;br /&gt;What SHOULD happen is that if ANY text field ANYWHERE in the Flash file has embedded a font, and ANY other text field anywhere else in the same movie (or even created dynamically) attempts to use the same font, the embedded font should be automatically applied to that other text field.&lt;br /&gt;&lt;br /&gt;Now, failing that, at the very least, copying the TextFormat from one text field to another should ensure that if the first had an embedded font, the second uses the same embedded font.&lt;br /&gt;&lt;br /&gt;Adobe, lift your game!  Microsoft's APIs make yours look pathetic.  You can do better than this!&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;sup&gt;(1)&lt;/sup&gt; The integer-letter-spacing-for-device-fonts limitation is mentioned in the &lt;a href='http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00002814.html'&gt;Flash 8 documentation&lt;/a&gt;.  I'm using Flash 10, and I am surmising that Flash 10 supports 0.5 increments, in contrast to the Flash 8 doco which claims only 1.0 increments are supported in Flash 8.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-1894658711192208421?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/1894658711192208421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=1894658711192208421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1894658711192208421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1894658711192208421'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/flash-bugs-dynamic-textfield-and.html' title='Flash bugs: dynamic TextField and letterSpacing issue'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-888045838280341169</id><published>2009-04-02T17:27:00.000-07:00</published><updated>2009-04-02T17:51:58.012-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ActionScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='SimpleButton'/><title type='text'>Flash bugs: dynamic SimpleButton gotcha</title><content type='html'>I'm creating a SimpleButton in ActionScript and it ain't showing up.&lt;br /&gt;&lt;br /&gt;var b:flash.display.SimpleButton = new flash.display.SimpleButton();&lt;br /&gt;b.upState = bla;&lt;br /&gt;b.overState = bla;&lt;br /&gt;b.downState = bla;&lt;br /&gt;b.hitTestState = bla;&lt;br /&gt;b.useHandCursor = true;&lt;br /&gt;this.addChild(b);&lt;br /&gt;&lt;br /&gt;The problem is, the button, she no appear.  Nada.&lt;br /&gt;&lt;br /&gt;I thought maybe my problem is that I'm using the same sprite for the different states, but changing that didn't make any difference.&lt;br /&gt;&lt;br /&gt;Turns out, Flash is proving its inferiority once again.&lt;br /&gt;&lt;br /&gt;The SimpleButton constructor, it so happens, accepts four OPTIONAL arguments, being the four SimpleButton states.&lt;br /&gt;&lt;br /&gt;Given that they are OPTIONAL, you would think you could omit them ALL and just set the four state properties after construction.&lt;br /&gt;&lt;br /&gt;You'd think so.  And so did I.&lt;br /&gt;&lt;br /&gt;But it turns out that, even though the documentation and the in-editor code helps all say the states are optional, THE UP STATE IS ACTUALLY MANDATORY.&lt;br /&gt;&lt;br /&gt;Ridiculous.&lt;br /&gt;&lt;br /&gt;In short, this works, because it supplies the mandatory-though-pretending-to-be-optional UpState argument to the SimpleButton constructor :&lt;br /&gt;&lt;br /&gt;var b:flash.display.SimpleButton = new flash.display.SimpleButton(bla);&lt;br /&gt;/*b.upState = bla; - no longer needed*/&lt;br /&gt;b.overState = bla;&lt;br /&gt;b.downState = bla;&lt;br /&gt;b.hitTestState = bla;&lt;br /&gt;b.useHandCursor = true;&lt;br /&gt;this.addChild(b);&lt;br /&gt;&lt;br /&gt;And of course, you might prefer to just save lines and go :&lt;br /&gt;&lt;br /&gt;var b:flash.display.SimpleButton = new flash.display.SimpleButton(bla, bla, bla, bla);&lt;br /&gt;b.useHandCursor = true;&lt;br /&gt;this.addChild(b);&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;On a related note, I was trying to figure out WHY Flash is so STUPID in this regard.  (Stupidity and unintuitive behaviour are more common than I would have expected in ActionScript.  I really honestly thought Microsoft's XAML was passable and that Adobe would be as good or better.  Sadly, Adobe is actually far behind M$ in the 'we make things that actually make sense' game, even if M$ itself isn't perfect.)&lt;br /&gt;&lt;br /&gt;My first guess was that the constructor determines the SimpleButton's dimensions from the upState, and thus, when no upState is passed to the constructor, the SimpleButton has no idea how big it needs to be.&lt;br /&gt;&lt;br /&gt;If that were the case, I could simply set the SimpleButton's width and height, and it would work.&lt;br /&gt;&lt;br /&gt;But no go.&lt;br /&gt;&lt;br /&gt;Here's the code :&lt;br /&gt;&lt;br /&gt;var b:flash.display.SimpleButton = new flash.display.SimpleButton();&lt;br /&gt;b.width = 100;&lt;br /&gt;b.height = 100;&lt;br /&gt;b.upState = bla;&lt;br /&gt;b.overState = bla;&lt;br /&gt;b.downState = bla;&lt;br /&gt;b.hitTestState = bla;&lt;br /&gt;b.useHandCursor = true;&lt;br /&gt;this.addChild(b);&lt;br /&gt;&lt;br /&gt;And it is as dead and useless as the very first code listing in this article.&lt;br /&gt;&lt;br /&gt;In short, it seems that the SimpleButton is COMPLETELY UNABLE TO HANDLE UPSTATE BEING OMITTED FROM THE CONSTRUCTOR INVOCATION.&lt;br /&gt;&lt;br /&gt;Which makes me ask why Adobe's documentation is so poor that there is no comment about it.  And why their compiler doesn't complain when that argument is missing from the constructor invocation.  And in fact why, overall, they make such an unintuitive design.&lt;br /&gt;&lt;br /&gt;Here's what I would have done, since I believe in making APIs as flexible as possible :&lt;br /&gt;&lt;br /&gt;1) All constructor arguments are optional.&lt;br /&gt;&lt;br /&gt;2) Button width and height are calculated just-in-time, or at least, calculation is deferred until upState gets set for the first time on a given SimpleButton instance.&lt;br /&gt;&lt;br /&gt;Voila!  Talk about intuitive!  In contrast, I really don't know how Adobe muck up like this, and at multiple places throughout their API.  Shame, Adobe.  Shame.  Please lift your game.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-888045838280341169?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/888045838280341169/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=888045838280341169' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/888045838280341169'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/888045838280341169'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/04/flash-bugs-dynamic-simplebutton-gotcha.html' title='Flash bugs: dynamic SimpleButton gotcha'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8245703508101866515</id><published>2009-03-29T16:41:00.001-07:00</published><updated>2009-03-29T18:16:21.938-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft SilverLight'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Flash'/><title type='text'>Flash ain't so flash</title><content type='html'>I thought Microsoft SilverLight was just a rip-off of Adobe Flash, and so I wanted Flash to remain dominant.&lt;br /&gt;&lt;br /&gt;I finally started learning Flash, and have decided it sucks compared to SilverLight.&lt;br /&gt;&lt;br /&gt;Flash is great for creating pre-defined animations, but for programming complex dynamic animations, it has issues.&lt;br /&gt;&lt;br /&gt;Worse yet, it's code editor is EXTREMELY hard to use.&lt;br /&gt;&lt;br /&gt;And the ActionScript compiler even produces incorrect error messages.&lt;br /&gt;&lt;br /&gt;All up, whilst a week ago I had high hopes of adding my own bit of momentum to the Flash technology, I am now inclined to believe that SilverLight will annihilate it, due if nothing else to vastly better development tools for complex programmatically-controlled animations.&lt;br /&gt;&lt;br /&gt;So, for example, I wanted to accomplish the simple task of creating a button in Flash that, when clicked, would respond visually so I knew I was correctly handling the mouse click event.&lt;br /&gt;&lt;br /&gt;I decided to make my button turn semi-transparent when clicked - just an elementary visual confirmation that my event handler fired.&lt;br /&gt;&lt;br /&gt;I drew my button (an arrow) with the crappy drawing tools in Flash.  (I see now why the average Flash artist would start in Illustrator, and only go to Flash once all their artwork was finished.)&lt;br /&gt;&lt;br /&gt;I converted it to a symbol, and in the library, chose the "Button" type (instead of MovieClip or Graphic).&lt;br /&gt;&lt;br /&gt;All should be well, or so I thought.  I then proceeded to use the stock-standard ActionScript 3.0 Flash CS4 button event handling code :&lt;br /&gt;&lt;br /&gt;function myHandler()&lt;br /&gt;{&lt;br /&gt;    myButton.alpha = 0.1;&lt;br /&gt;}&lt;br /&gt;myButton.addEventHandler(MouseEvent.CLICK, myHandler);&lt;br /&gt;&lt;br /&gt;Right off the bat, the editor is TERRIBLE.  Microsoft has this thing called "Intellisense", that I just took for granted.  But seeing that one of their chief rivals, namely Adobe, can't create something even half as good, makes me realise that Microsoft is actually quite good at creating code editors.&lt;br /&gt;&lt;br /&gt;Oh - for sure - Flash has an "Intellisense" equivalent, but only if you declare a strongly-typed variable.  But why should I have to do that?  Flash already knows that "myButton" is a reference to that button on-screen, so why should I have to declare yet another variable just to get strong typing?&lt;br /&gt;&lt;br /&gt;Anyhow, I dutifully do so :&lt;br /&gt;&lt;br /&gt;var myStronglyTypedButtonReference:? = myButton;&lt;br /&gt;function myHandler()&lt;br /&gt;{&lt;br /&gt;    myStronglyTypedButtonReference.alpha = 0.1;&lt;br /&gt;}&lt;br /&gt;myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);&lt;br /&gt;&lt;br /&gt;Snag.  What type to use?&lt;br /&gt;&lt;br /&gt;Again, the code editor is crappy to the max.&lt;br /&gt;&lt;br /&gt;Fortunately, there is a very-slow-to-use (no search functionality) class list on the left-hand-side of the editor.  It is categorised, which means that whilst my intuition tells me I probably need to find a class called "Button", I need to search through package after package after package.  Oh - at the very end there is an "Index" option, which I use.  On my powerful computer, it still takes too many seconds to prepare the index, but I am finally rewarded.  In the index I find a Button class, and it is in the fl.controls package.&lt;br /&gt;&lt;br /&gt;var myStronglyTypedButtonReference:fl.controls.Button = myButton;&lt;br /&gt;function myHandler()&lt;br /&gt;{&lt;br /&gt;    myStronglyTypedButtonReference.alpha = 0.1;&lt;br /&gt;}&lt;br /&gt;myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);&lt;br /&gt;&lt;br /&gt;You'd think that would work.  But no.&lt;br /&gt;&lt;br /&gt;Flash now complains that "Type was not found or was not a compile-time constant: Button".  Fat lot of good that is!&lt;br /&gt;&lt;br /&gt;I search and search.  The answer almost everyone gives is "just add a button to your stage then delete it straight away, and this will add the necessary library code to your project".&lt;br /&gt;&lt;br /&gt;Ummm - but don't I already have a button on my stage?  I mean, this arrow I drew is very definitely a button.&lt;br /&gt;&lt;br /&gt;I add another copy of the arrow button from the Library to the ActionScript layer, just in case that will help, but the problem persists.&lt;br /&gt;&lt;br /&gt;Prompted by one web page, I look at my class path, but that has nothing to do with the problem.&lt;br /&gt;&lt;br /&gt;Finally, I find a web page that gives me the clue I need.  Check out WarpZone's contribution &lt;a href='http://www.kirupa.com/forum/archive/index.php/t-273758.html'&gt;here&lt;/a&gt;.  Turns out you need to open the "Components" window, and drag a "Button" control from that "Components" window onto your stage.&lt;br /&gt;&lt;br /&gt;So I do it.&lt;br /&gt;&lt;br /&gt;And now Flash complains that it can't convert a SimpleButton to a Button!!!&lt;br /&gt;&lt;br /&gt;Can I just say that this is really really really stupid.  In SilverLight, it is quick &amp; easy to determine the data type of any control on the "stage".  But in Flash, it seems you have to just guess, then look for compiler error messages or runtime error messages that would indicate if you guessed wrong!&lt;br /&gt;&lt;br /&gt;So I need to use "SimpleButton", not "Button".&lt;br /&gt;&lt;br /&gt;var myStronglyTypedButtonReference:fl.controls.&lt;strong&gt;SimpleButton&lt;/strong&gt; = myButton;&lt;br /&gt;function myHandler()&lt;br /&gt;{&lt;br /&gt;    myStronglyTypedButtonReference.alpha = 0.1;&lt;br /&gt;}&lt;br /&gt;myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);&lt;br /&gt;&lt;br /&gt;Problem : SimpleButton is not in the fl.controls package.  Groan.  Back to the Index.  Oh - guess what - it's so dumb it hasn't cached the results of the last time I opened the index.  So it spends way too much time once more opening the index.&lt;br /&gt;&lt;br /&gt;But at least I can find SimpleButton without too much more pain.  It lives in flash.display.&lt;br /&gt;&lt;br /&gt;var myStronglyTypedButtonReference:&lt;strong&gt;flash.display.SimpleButton&lt;/strong&gt; = myButton;&lt;br /&gt;function myHandler()&lt;br /&gt;{&lt;br /&gt;    myStronglyTypedButtonReference.alpha = 0.1;&lt;br /&gt;}&lt;br /&gt;myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);&lt;br /&gt;&lt;br /&gt;Extremely unintuitive so far!  But surely I have arrived, no?&lt;br /&gt;&lt;br /&gt;But no.&lt;br /&gt;&lt;br /&gt;When I run, Flash tells me :&lt;br /&gt;&lt;br /&gt;ArgumentError: Error #1063: Argument count mismatch on Untitled_fla::MainTimeline/myHandler(). Expected 0, got 1.&lt;br /&gt;&lt;br /&gt;Wait a moment - &lt;strong&gt;expected ZERO, got ONE&lt;/strong&gt;?&lt;br /&gt;&lt;br /&gt;Adobe, do you know how to write compiler error messages?&lt;br /&gt;&lt;br /&gt;My function takes ZERO arguments.  If ZERO are expected, then things should work fine!&lt;br /&gt;&lt;br /&gt;But, suspecting sloppiness on Adobe's part, I figure that they probably &lt;em&gt;intended&lt;/em&gt; to say "expected ONE, got ZERO".  So more searching on the web, and I find a code example that uses a single argument of type Object for event handlers.  I try it, and at last it works :&lt;br /&gt;&lt;br /&gt;var myStronglyTypedButtonReference:flash.display.SimpleButton = myButton;&lt;br /&gt;function myHandler(&lt;strong&gt;eventObj:Object&lt;/strong&gt;)&lt;br /&gt;{&lt;br /&gt;    myStronglyTypedButtonReference.alpha = 0.1;&lt;br /&gt;}&lt;br /&gt;myStronglyTypedButtonReference.addEventHandler(MouseEvent.CLICK, myHandler);&lt;br /&gt;&lt;br /&gt;Once again, were it SilverLight, it would have been much quicker &amp; easier for me to identify which argument(s) are required for the event handler, and what data type each argument needs to be.&lt;br /&gt;&lt;br /&gt;Oh - and SilverLight does at least tend to give ACCURATE error messages.&lt;br /&gt;&lt;br /&gt;And this is just a small sliver of my Flash woes.  It is horribly unintuitive.&lt;br /&gt;&lt;br /&gt;Flash, I wanted to support you, to cheer you on in the race against Microsloth, but I am deeply shocked, saddened, and surprised to find that from a programmability perspective, Microsoft has already won the race.  You suck.&lt;br /&gt;&lt;br /&gt;I hope it doesn't stay this way.&lt;br /&gt;&lt;br /&gt;UPDATE : Despite its many faults and failings, Flash can do really powerful things when you finally figure out how to do things.  (It's the "finally figure out" process that Adobe has made waaay too hard.)  So for example, here are two pages with EXCELLENT introductory information that has helped me immensely in my quest for complex dynamically-generated Flash animations :&lt;br /&gt;&lt;br /&gt;&lt;a href='http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00000143.html'&gt;Core Display Classes in Adobe Flash&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&amp;file=00000176.html'&gt;How to use the Adobe Flash Drawing API at runtime&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8245703508101866515?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8245703508101866515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8245703508101866515' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8245703508101866515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8245703508101866515'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/03/flash-aint-so-flash.html' title='Flash ain&apos;t so flash'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-8169730235124369279</id><published>2009-03-16T16:10:00.000-07:00</published><updated>2009-03-16T16:24:45.484-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='version control systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Bazaar'/><title type='text'>Bazaar - managing local feature branches with lightweight checkouts</title><content type='html'>Bazaar is the BEST source code versioning system in the world, or at least, the best non-commercial one (I can't comment on commercial ones except Visual SourceSafe, which epitomises dog-ness).&lt;br /&gt;&lt;br /&gt;Well, that's my opinion, after using SVN and Visual SourceSafe, and reading fairly extensively about other systems.&lt;br /&gt;&lt;br /&gt;But it can be hard to get started, just because it is SO powerful and has SO many options and can be used in SO many different ways.&lt;br /&gt;&lt;br /&gt;If you're a single developer who just uses it to track their own work, and never makes feature branches, life is very simple.&lt;br /&gt;&lt;br /&gt;bzr init&lt;br /&gt;bzr add&lt;br /&gt;bzr commit -m "My project is now in Bazaar!  Woot, woot!"&lt;br /&gt;... edit your project ...&lt;br /&gt;bzr add&lt;br /&gt;bzr commit -m "I just made edits to my project, and Bazaar has been updated accordingly."&lt;br /&gt;&lt;br /&gt;It's really sweet.  Suppose you ship a new version, and you want to be able to access the exact source code that was used in that version :&lt;br /&gt;&lt;br /&gt;bzr tag "Released version 1.2.3"&lt;br /&gt;&lt;br /&gt;And to review previous tags?  Simple :&lt;br /&gt;&lt;br /&gt;bzr tags&lt;br /&gt;&lt;br /&gt;If you mucked up?&lt;br /&gt;&lt;br /&gt;bzr revert&lt;br /&gt;&lt;br /&gt;(Throws away your changes since the last commit.)&lt;br /&gt;&lt;br /&gt;That's all very sweet and simple.  (Sure beats SVN and Visual SourceSafe!!!!!!!!!!!!!!!)&lt;br /&gt;&lt;br /&gt;But I wanted to use feature branches.&lt;br /&gt;&lt;br /&gt;There are various ways to do it, but here's a simplified version of how I'm doing it, with great success :&lt;br /&gt;&lt;br /&gt;Create a root development folder.  For sake of demonstration, let's call it "src".&lt;br /&gt;&lt;br /&gt;src&gt; bzr init-repo --no-trees&lt;br /&gt;src&gt; md trunk&lt;br /&gt;src&gt; cd trunk&lt;br /&gt;src\trunk&gt; bzr init&lt;br /&gt;&lt;br /&gt;At this point, you have a trunk, with nothing in it.  Not much use, but press on...&lt;br /&gt;&lt;br /&gt;src\trunk&gt; cd..&lt;br /&gt;src&gt; md wt&lt;br /&gt;&lt;br /&gt;Here, "wt" is an acronym I've chosen somewhat arbitrarily.  It stands for "working tree".  It's the only place I'm going to have a copy of the (often extensive) set of files in the project.&lt;br /&gt;&lt;br /&gt;Get it?&lt;br /&gt;&lt;br /&gt;Bazaar lets you have as many branches as you want, without clogging your hard disk!  THAT is AWESOME!&lt;br /&gt;&lt;br /&gt;Now any time you embark on a change, you can afford to do it in a branch.  That keeps your work well organised, and means you don't end up stuck with half-finished changes in your trunk.  Very nice!&lt;br /&gt;&lt;br /&gt;Did I mention that Bazaar is the best source code versioning system in the world?  :o)&lt;br /&gt;&lt;br /&gt;Ah - but we're not done yet.  It's still useless at this point.  Press on...&lt;br /&gt;&lt;br /&gt;src&gt; cd wt&lt;br /&gt;src\wt&gt; bzr checkout ..\trunk --lightweight&lt;br /&gt;&lt;br /&gt;Woot, woot!  At this point, copy any existing files for the project into src\wt, then proceed.&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr add&lt;br /&gt;src\wt&gt; bzr commit -m "Initial commit, directly into trunk.  After this point, we will work on branches, not on the trunk."&lt;br /&gt;&lt;br /&gt;Extra wootness!  Now we have a trunk, and a working tree, and we are ready to start branching.&lt;br /&gt;&lt;br /&gt;src\wt&gt; cd..&lt;br /&gt;src&gt; bzr branch trunk "Branch001 - completely revolutionise colour scheme"&lt;br /&gt;src&gt; bzr branch trunk "Branch002 - add new powerful print-preview system"&lt;br /&gt;src&gt; bzr branch trunk "Small changes"&lt;br /&gt;&lt;br /&gt;Yep - you guessed it.  If you think there's a reasonable chance you'll get stuck halfway through a set of changes, and not have them finished before you have to work on some other aspect of the source code, then that's a good candidate for a branch.  But if it's a REALLY small change (e.g. update the copyright notice in a single file), no need to create a new branch just for that.  You could conceivably make that change directly in the trunk (although I advise against it, for reasons that are beyond the scope of this article).  My solution?  I have a permanent branch called "Small changes", and that's where I make small changes!  :o)&lt;br /&gt;&lt;br /&gt;So now, let's start work!&lt;br /&gt;&lt;br /&gt;src&gt; cd wt&lt;br /&gt;src\wt&gt; bzr switch "..\Branch001 - completely revolutionise colour scheme"&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;&lt;br /&gt;At this point, the working tree matches the contents of Branch001.&lt;br /&gt;&lt;br /&gt;Start work on that colour scheme.&lt;br /&gt;&lt;br /&gt;Oh no!  The boss has walked in and said the new print-preview system has to take priority.&lt;br /&gt;&lt;br /&gt;Gotta change to a different branch.&lt;br /&gt;&lt;br /&gt;Easy done :&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr commit -m "These are my changes so far."&lt;br /&gt;src\wt&gt; bzr switch "..\Branch002 - add new powerful print-preview system"&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;&lt;br /&gt;Voila!  Now the working tree matches Branch002.  Code away merrily...&lt;br /&gt;&lt;br /&gt;In comes the accounts lady.  "The last digit on the bank account number should be seven, not three."&lt;br /&gt;&lt;br /&gt;This change should be done immediately.  No point waiting two weeks for the new uber-funky print-preview system, nor five months for the new colour scheme to finally be done.&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr commit -m "Well, working on Branch002 was fun and all, but necessity demands my (temporary) departure."&lt;br /&gt;src\wt&gt; bzr switch "..\Small changes"&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;&lt;br /&gt;Now fix that account number.  And then proceed...&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr commit -m "Maggie informed me that the account number was incorrect.  Fixed now."&lt;br /&gt;&lt;br /&gt;Now, chances are, we want that change to go into the trunk right now.  Let's do that.&lt;br /&gt;&lt;br /&gt;A clue : BAZAAR IS NOT INTUITIVE WHEN IT COMES TO COMBINING FEATURE BRANCHES INTO THE TRUNK.&lt;br /&gt;&lt;br /&gt;Oh - don't flame me.  The problem is that most documentation talks about the 'bzr push" and "bzr pull" options.&lt;br /&gt;&lt;br /&gt;But these will destroy everything.  You'll lose the farm, the house, the boat...&lt;br /&gt;&lt;br /&gt;There is a very simple rule to keep in mind when working on feature branches on your own computer :&lt;br /&gt;&lt;br /&gt;bzr merge!!!!!!!&lt;br /&gt;&lt;br /&gt;Yes - Bazaar's merging features are second-to-none.  They are truly impressive.&lt;br /&gt;&lt;br /&gt;So despite the myriad examples out there telling you to "bzr push" your changes to the central server - ignore it!  Those instructions apply in certain common situations, but do not apply for our current purposes.&lt;br /&gt;&lt;br /&gt;So here's how we get the latest changes from a branch into the trunk :&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr merge ..\trunk&lt;br /&gt;&lt;br /&gt;That's the first step.  Remember - whilst we've been busily working away on a branch, there might have been other branches committed to trunk.  So the trunk we once knew is not necessarily the current trunk.  We need to ensure that what we're about to commit to the trunk is compatible with the current version of the trunk.&lt;br /&gt;&lt;br /&gt;And the way we do that is to first merge the latest changes from the TRUNK back into the current branch.&lt;br /&gt;&lt;br /&gt;Having done that, we run our unit tests.  If everything compiles and runs fine, we're happy chaps.  If not, fix it!  :o)&lt;br /&gt;&lt;br /&gt;When we're happy with the merge :&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr commit -m "Merged with trunk"&lt;br /&gt;&lt;br /&gt;Cool.  So now we know that our changes in this branch are compatible with the trunk.  That means it's safe to merge this branch into the trunk.&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr switch ..\trunk&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;src\wt&gt; bzr merge "..\Small changes"&lt;br /&gt;&lt;br /&gt;There shouldn't be any conflicts or other problems at this point, because we already merged the trunk into our branch, and any problems should have been encountered then not now.&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr commit -m "Merged with branch 'Small changes'"&lt;br /&gt;&lt;br /&gt;Woot, woot!&lt;br /&gt;&lt;br /&gt;Oh - there's the boss again.  I'd forgotten about the print preview.  Better get back onto it :&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr switch "..\Branch002 - add new powerful print-preview system"&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;&lt;br /&gt;Code away.&lt;br /&gt;&lt;br /&gt;Oh no!  I just discovered that the print preview cannot possibly work unless the account number is correct - but the account number was fixed in a different branch!&lt;br /&gt;&lt;br /&gt;Not a problem.&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr merge "..\Small changes"&lt;br /&gt;src\wt&gt; bzr commit -m "Merged with branch 'Small changes'"&lt;br /&gt;&lt;br /&gt;Ah - wonderful.  Now the changes in the "Small changes" branch are also in Branch002.&lt;br /&gt;&lt;br /&gt;What's better yet is that Bazaar is so smart that you can merge those two branches together as many times as you want, and Bazaar will keep a record of what has been previously merged and what hasn't been, so that you'll never have trouble with the one change being included multiple times!&lt;br /&gt;&lt;br /&gt;THAT is POWERFUL.&lt;br /&gt;&lt;br /&gt;In fact, suppose we made Branch003 for some purpose or other :&lt;br /&gt;&lt;br /&gt;src\wt&gt; cd..&lt;br /&gt;src&gt; bzr branch trunk Branch003&lt;br /&gt;src&gt; cd wt&lt;br /&gt;src\wt&gt; bzr switch ..\Branch003&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;&lt;br /&gt;Suppose it adds some cool new features to our library of helper functions.&lt;br /&gt;&lt;br /&gt;Suppose we finish with the branch :&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr merge ..\trunk&lt;br /&gt;... compile and run unit tests ...&lt;br /&gt;src\wt&gt; bzr commit -m "Merged with trunk"&lt;br /&gt;src\wt&gt; bzr switch ..\trunk&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;src\wt&gt; bzr merge ..\Branch003&lt;br /&gt;src\wt&gt; bzr commit -m "Merged with Branch003"&lt;br /&gt;&lt;br /&gt;At this point, Branch003, trunk, and "Small changes" ALL contain the account number change, and Branch003 and trunk both contain the new helper functions.&lt;br /&gt;&lt;br /&gt;We don't need Branch003 any more, so we're going to switch away from it and delete it.  (We could switch to any branch, but hey, for the time being, I'll switch to the trunk, 'coz I don't know where I'm going next.)&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr switch ..\trunk&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;src\wt&gt; rd ..\Branch003 /s&lt;br /&gt;... and type "y" and Enter to confirm that you want to mercilessly annihilate Branch003.&lt;br /&gt;&lt;br /&gt;Now, in some other source code versioning systems, you have to manually track which changes have been merged where.  (Not mentioning any names...  &amp;lt;cough - SVN&amp;gt; )&lt;br /&gt;&lt;br /&gt;But with Bazaar, things just work, and they work perfectly!&lt;br /&gt;&lt;br /&gt;We return to the print preview branch :&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr switch "..\Branch002 - add new powerful print-preview system"&lt;br /&gt;src\wt&gt; bzr revert&lt;br /&gt;&lt;br /&gt;Oh - turns out we need those new helper functions.&lt;br /&gt;&lt;br /&gt;If Branch003 still existed, we could get those new helper functions by merging it in to Branch002.&lt;br /&gt;&lt;br /&gt;Or we can merge the trunk into Branch002.&lt;br /&gt;&lt;br /&gt;But Bazaar is so cool, that it doesn't matter which one we do, or even if do both, or even if we do both multiple times!  It just works!&lt;br /&gt;&lt;br /&gt;src\wt&gt; bzr merge ..\trunk&lt;br /&gt;src\wt&gt; bzr commit -m "Merged with trunk, to get those wonderful new helper functions."&lt;br /&gt;&lt;br /&gt;So, merge is your friend.&lt;br /&gt;&lt;br /&gt;See, because I grew up with Visual SourceSafe and SVN, "merge" had a negative connotation.  I assumed that the change history, including the detailed comments I leave with every commit, would be marred by merging.&lt;br /&gt;&lt;br /&gt;But with Bazaar, the history is preserved!&lt;br /&gt;&lt;br /&gt;It's easy to prove :&lt;br /&gt;&lt;br /&gt;src\wt&gt; cd ..\trunk&lt;br /&gt;src\trunk&gt; bzr log&lt;br /&gt;&lt;br /&gt;And now you get a nice big listing of all the changes that have happened.  It doesn't matter how many times you merged, all changes and all commit messages are preserved.&lt;br /&gt;&lt;br /&gt;THAT'S what I call a good source code versioning system (aka "revision control system").&lt;br /&gt;&lt;br /&gt;So many branches and can't remember which one the working tree is currently bound to?&lt;br /&gt;&lt;br /&gt;src\trunk&gt; cd ..\wt&lt;br /&gt;src\wt&gt; bzr info&lt;br /&gt;&lt;br /&gt;Ah!  It tells us which branch we're bound to.  Very nice.&lt;br /&gt;&lt;br /&gt;Now, my setup is actually considerably more elaborate than this.  I have multiple development machines that I switch between - one laptop for the road, and a much more powerful desktop that I prefer using when I can.&lt;br /&gt;&lt;br /&gt;I wanted a "central trunk" from which I could run automated unit tests, and which could be my controlled release point.  Plus, I have other developers help out here and there.  So I really wanted a system that works this simply and this well, but works across multiple computers.&lt;br /&gt;&lt;br /&gt;And I needed each computer to have its own "local trunk" so that the respective developers could branch away happily even when they were not connected to the internet and the central trunk.&lt;br /&gt;&lt;br /&gt;So, in effect (although I accomplished it slightly differently), I have a folder called "central-trunk", on my controlled-release computer.&lt;br /&gt;&lt;br /&gt;I have found that the Bazaar logs look nicest when you only have one level of indirection with merges.  Since I like nice, readable logs, this is what I do :&lt;br /&gt;&lt;br /&gt;I merge finished branches into the CENTRAL trunk, and I never delete a branch until I have merged it with that CENTRAL trunk (unless I'm abandoning the branch).&lt;br /&gt;&lt;br /&gt;The LOCAL trunk exists ONLY TO ENSURE I CAN CREATE NEW LOCAL BRANCHES EASILY.&lt;br /&gt;&lt;br /&gt;And to keep the local trunk in-sync with the central trunk, I run the following when connected :&lt;br /&gt;&lt;br /&gt;src\trunk&gt; bzr pull Z:\central-trunk&lt;br /&gt;&lt;br /&gt;I NEVER merge or commit into my LOCAL trunk.  If I'm working on two branches that need features from each other, I merge them into each other.&lt;br /&gt;&lt;br /&gt;So basically there are three levels - the central trunk, the local trunk, and each feature branch.&lt;br /&gt;&lt;br /&gt;The changes are "bzr pull"ed from the central trunk into the local trunk.&lt;br /&gt;&lt;br /&gt;"bzr branch" from the local trunk creates local feature branches.&lt;br /&gt;&lt;br /&gt;"bzr merge", NOT "bzr push", takes my local feature branch into the central trunk.&lt;br /&gt;&lt;br /&gt;And "bzr merge" also handles inter-branch updates along the way.&lt;br /&gt;&lt;br /&gt;-&lt;br /&gt;&lt;br /&gt;Bazaar changed my programming life.  It is a source code versioning system that works, and works brilliantly well, and isn't cumbersome.  It is a pleasure to use.  I enjoy the feeling of committing a change, and I enjoy merging a feature branch into the trunk.  It feels like hammering another peg into the cliff face, as I climb the metaphorical cliff of whichever crazy software development endeavour I've embarked on.  (And I usually embark on difficult ones!  :o)  )&lt;br /&gt;&lt;br /&gt;It changed my life, even long before I started using feature branches.  For a long time, I just used (and loved) the ability to track each version of the trunk, and tag releases.&lt;br /&gt;&lt;br /&gt;Now with feature branches, things are even better again.&lt;br /&gt;&lt;br /&gt;If I'd been given this information when I first found Bazaar, I would have accomplished more.  Feature branches are a produtivity tool.&lt;br /&gt;&lt;br /&gt;But the documentation was more focussed on contributing to open-source projects where you always branch directly off the head revision from a read-only URL somewhere, and where only specially-privileged people can commit to trunk.  That's fine - that's a very powerful and very common use of Bazaar.&lt;br /&gt;&lt;br /&gt;But it can do so much more!  I hope in this article that I've helped some of you get up-to-speed with Bazaar in ways that will transform your programming life for the better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-8169730235124369279?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/8169730235124369279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=8169730235124369279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8169730235124369279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/8169730235124369279'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/03/bazaar-managing-local-feature-branches.html' title='Bazaar - managing local feature branches with lightweight checkouts'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-4434226479077785877</id><published>2009-03-01T02:38:00.000-08:00</published><updated>2009-03-01T04:42:12.043-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance'/><category scheme='http://www.blogger.com/atom/ns#' term='SSDs'/><category scheme='http://www.blogger.com/atom/ns#' term='Intel SSDs'/><title type='text'>Beating the performance bogeys in the Intel SSDs</title><content type='html'>Intel changed the world forever with its new X25M and X18M SSDs.&lt;br /&gt;&lt;br /&gt;But reports are circulating of major performance problems.&lt;br /&gt;&lt;br /&gt;Everyone's puzzled, and &lt;a href='http://arstechnica.com/hardware/news/2009/02/intel-cant-yet-replicate-published-ssd-performance-drop-1.ars'&gt;Intel denies any performance problems at all&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What's the low-down?&lt;br /&gt;&lt;br /&gt;It's simple, as far as I can tell.&lt;br /&gt;&lt;br /&gt;First, let's review the kinds of problems being reported :&lt;br /&gt;&lt;br /&gt;* &lt;a href='http://www.pcper.com/article.php?aid=669&amp;type=expert&amp;pid=1'&gt;Intel SSD is BLISTERINGLY fast when first installed, but after a few months, random write performance plummets.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;* &lt;a href='http://www.behardware.com/articles/731-6/ssd-product-review-intel-ocz-samsung-silicon-power-supertalent.html'&gt;Testing the Intel SSD by hammering it with tiny random writes for even less than a few hours brings a brand-new SSD to its knees - write speeds lower than 10MB per second.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;* &lt;a href='http://www.pcper.com/article.php?aid=669&amp;type=expert&amp;pid=6'&gt;Imaging a hard disk partition onto a brand-new Intel SSD, results in that SSD's write speed dropping to just a fraction of the advertised speed.&lt;/a&gt;  &lt;small&gt;(Search the linked page for 'All we did here was write the OS files')&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;You're not going to like this, but if you partition the drive - e.g. in half - and only ever use one of the two partitions, you won't see these problems.&lt;br /&gt;&lt;br /&gt;Or at least, that's my bet, not actually owning one quite yet (although I've placed an order).&lt;br /&gt;&lt;br /&gt;Can you see why?&lt;br /&gt;&lt;br /&gt;The Intel SSD is so mind-bogglingly brilliant because it combines random writes into sequential writes.  Others have already blogged about that very well, so I won't detail it here.&lt;br /&gt;&lt;br /&gt;The problem is that the SSD doesn't know when virtual sectors are "available" again - it only knows which virtual sectors the operating system has ever written to.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;If the operating system has EVER written to a virtual sector, the SSD controller studiously preserves the content of that virtual sector ever after, EVEN IF THE OPERATING SYSTEM LATER THINKS IT HAS DELETED FILES AND THAT THEREFORE THE SECTOR IS UNUSED AND AVAILABLE FOR RE-USE.&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Thus, if you use the wrong imaging tool, and write an 80GB partition to your brand-new Intel SSD, &lt;strong&gt;BAM&lt;/strong&gt; - as far as the SSD is concerned, you have 0% free space.  Yup - your partition might have contained 60% free space, but if the imaging tool does a sector-by-sector copy of the source disk to the SSD, then the imaging tool will write to &lt;em&gt;every&lt;/em&gt; virtual sector in the SSD, and the poor SSD controller will be left diligently trying to preserve the contents of empty sectors.&lt;br /&gt;&lt;br /&gt;SO, the trick to ensuring that the Intel SSD controller has some "breathing space" in which to perform its magic, is to ensure you NEVER COMPLETELY FILL the SSD.&lt;br /&gt;&lt;br /&gt;Sad, but true.&lt;br /&gt;&lt;br /&gt;Yup - that means that if you fill your 80GB SSD with 80GB of data (whether test data for random write tests, or 80GB worth of your data files), then read speed will stay great &lt;small&gt;(it does slow down, but you're not likely to notice without a performance monitoring tool)&lt;/small&gt;, &lt;em&gt;but write speed will plummet&lt;/em&gt;.  The poor SSD controller won't be able to turn random writes into sequential writes, 'coz there's no free space!&lt;br /&gt;&lt;br /&gt;Actually, there &lt;em&gt;is&lt;/em&gt; free space - a tiny bit.  See, &lt;em&gt;apparently&lt;/em&gt;, the Intel SSD comes with a few GBs spare storage space beyond the advertised capacity.&lt;br /&gt;&lt;br /&gt;Without this spare storage space "up its sleeve", the Intel SSD could, in worst-case performance scenarios, have random write speeds as abysmally low as say the OCZ Core V2 (which I am suffering with).&lt;br /&gt;&lt;br /&gt;So by having more storage space available than it lets the computer directly use, the SSD controller always has a little bit of room to move - and that's why even when things go horribly pear shaped, the Intel SSD can still maintain a random write speed of well over 1 megabyte per second (reports vary up to even still around 20 megabytes per second) - which is WAY more than the competitors do from the very outset!!!  &lt;small&gt;(For comparison, my OCZ Core V2 120GB has a random write speed for 4kb blocks somewhere under, well, I'm not entirely sure, but I think less than 100 kilobytes per second - i.e. less than 0.1 megabytes per second.)&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;So let's take the case of the hardcore random-write test.  We write a special program that randomly chooses any sector across the entire 80GB of the SSD, and writes just to that sector, and then chooses another randomly, and writes to that, and does so as fast as the SSD can handle it, for hours on end.&lt;br /&gt;&lt;br /&gt;For the first 80GB-worth of random writes, it zooms along at the mind-boggling speed of 70MB per second or more.&lt;br /&gt;&lt;br /&gt;But it quickly hits a wall.  The SSD controller was attaining these astounding speeds by combining the random writes into sequential writes, but shortly after 80GB worth of writes, it runs out of unused sequential storage locations.  (Remember that it has a bit of breathing room, but that gets used up quickly too...)&lt;br /&gt;&lt;br /&gt;In this condition, the effort required to combine even just two random writes into one sequential write is multiplied.  On the virgin drive, it could cram 2MB of random writes into each 2MB write block (or whatever write block size it actually uses - I pick 2MB for demonstration purposes, but the principle remains true whatever the actual write block size).  But on the drive in this random-write-crammed-full condition, if there was no "breathing space" (additional storage space beyond what the host computer is aware of), then each 4 kilobyte (0.004 megabyte) random write would require an entire 2 megabyte write block to be written.  That's a slowdown factor of 2 / 0.004 = 500!!!!!!!  No wonder people report speed problems!&lt;br /&gt;&lt;br /&gt;Of course, Intel was smart to include the "breathing space" - it ensures that the worst-case random write speed never actually gets as bad as that.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;SO&lt;/strong&gt; - what's a man to do?&lt;br /&gt;&lt;br /&gt;The reality is, this problem is not as bothersome as you might think - if you know what triggers it and how to avoid it.&lt;br /&gt;&lt;br /&gt;The simplest thing to do - and what I plan to do as soon as mine arrives - is to give it even a bit more breathing space than comes built-in.&lt;br /&gt;&lt;br /&gt;e.g. partition it into 70GB + 10GB, and never touch the 10GB.  That gives the controller an extra 10GB of "breathing space".  In a more extreme case, if you - for example - chopped the drive in half, and kept 40GB in an untouched partition, where the SSD controller can have a huge amount of "breathing space", then you should find that the worst-case random write performance never drops below roughly half of the best-case random-write performance.&lt;br /&gt;&lt;br /&gt;So why is it that Intel claims they can't reproduce the reported problems?  I bet they're not testing with a chokkers drive.  Pack that drive full - every last sector - and you'll get random write speed issues double-quick time.  But leave more "breathing space" than the default built-in, and things will improve.&lt;br /&gt;&lt;br /&gt;Does it seem sad to lose a big chunk of an already-very-expensive-per-gigabyte SSD?&lt;br /&gt;&lt;br /&gt;It sure does.  But on the flipside, do you need all 80GB of super-speed goodness?&lt;br /&gt;&lt;br /&gt;In my case, I reckon I can survive with say just 40GB or 60GB of primary partition, tools, and source code, and keep my photo libraries and downloads and other huge files on a traditional spinning platter.&lt;br /&gt;&lt;br /&gt;But do I even care that much?  Suppose random write speed dropped to 10MB/s?  Given that it has practically zero seek time, and given that developing for the Microsoft .NET Framework results in HUGE numbers of small relatively random writes, 10MB/s sustained on an SSD will probably still out-pace my current hard disk by a good margin.&lt;br /&gt;&lt;br /&gt;I think I'll set aside 20GB as unused additional "breathing room" initially, and then chip into that later if I can make more precise calculations about worst-case random write performance with different amounts of breathing room...&lt;br /&gt;&lt;br /&gt;So talk to me - did it work for you?&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;UPDATE: If your Intel SSD has hit the doledrums (i.e. has lost its random write performance), check out the &lt;a href='http://www.pcper.com/article.php?aid=669&amp;type=expert&amp;pid=6'&gt;HDD Erase&lt;/a&gt; tool and accompanying notes.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-4434226479077785877?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/4434226479077785877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=4434226479077785877' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4434226479077785877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4434226479077785877'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/03/beating-performance-bogeys-in-intel.html' title='Beating the performance bogeys in the Intel SSDs'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-3109067017497182732</id><published>2009-01-19T19:36:00.000-08:00</published><updated>2009-01-19T19:43:02.552-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='conversion'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Illustrator'/><category scheme='http://www.blogger.com/atom/ns#' term='SVG'/><category scheme='http://www.blogger.com/atom/ns#' term='XamlTune'/><title type='text'>XamlTune just got a little better</title><content type='html'>XamlTune is a fab utility for converting SVG to XAML.  It's one of the best things going for conversion from Adobe Illustrator to XAML.&lt;br /&gt;&lt;br /&gt;Unfortunately, like all SVG-to-XAML converters, it's flawed in various ways.&lt;br /&gt;&lt;br /&gt;I've just released my second patch for XamlTune, which fixes a few more of the flaws and makes Adobe Illustrator to XAML conversion that much easier again.&lt;br /&gt;&lt;br /&gt;(You can &lt;a href="http://www.codeplex.com/XamlTune/SourceControl/PatchList.aspx"&gt;download my XamlTune patches here&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Key fixes:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;SVG shapes (circles, ellipses, etc) that have a transformation matrix, now convert correctly.  Woot!  (The trick was to convert them into XAML Paths instead of XAML shapes.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;SVG circles are now converted into XAML Ellipses, instead of being converted into XAML Paths.  (But if the circle has a transformation matrix, we stick with XAML Paths, as per the previous point.)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;XamlTune has cost me a few days of debugging work (i.e. debugging XamlTune), but it has saved me much more time than that with an already extensive SVG-to-XAML conversion framework.  I am glad to be able to contribute my bug-fixes back to the project and help it help others more.&lt;br /&gt;&lt;br /&gt;Enjoy!  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-3109067017497182732?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/3109067017497182732/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=3109067017497182732' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3109067017497182732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3109067017497182732'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/01/xamltune-just-got-little-better.html' title='XamlTune just got a little better'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-778750362348449239</id><published>2009-01-14T22:53:00.000-08:00</published><updated>2009-01-14T22:59:15.900-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PayPal'/><title type='text'>PayPal - well, their tech support kinda worked for me</title><content type='html'>I &lt;a href="http://selfdocumentingcode.blogspot.com/2008/12/paypal-systems-gone-awry.html"&gt;sent a very unhappy email to PayPal&lt;/a&gt; about some stupid stuff their automated systems was doing to my account.  It took a phone call to find out what address to send the email to.  But despite the many difficulties I've had with them, to be fair, I must commend them that :&lt;br /&gt;&lt;br /&gt;1) We were actually able to ring them by phone and speak with a human;&lt;br /&gt;&lt;br /&gt;2) When we sent our complaint email to the email address we were given by phone, we actually got a reply from a human - and within only a day or two;&lt;br /&gt;&lt;br /&gt;3) The human answering our email had clearly comprehended our complaint, and checked our account to ensure it was all fine;&lt;br /&gt;&lt;br /&gt;Yes - PayPal automated processes have some issues - some of them pretty serious - but to be fair, I have to say that I am impressed that they listened and responded and my account is working again.&lt;br /&gt;&lt;br /&gt;Kudos PayPal for at least doing this much...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-778750362348449239?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/778750362348449239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=778750362348449239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/778750362348449239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/778750362348449239'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/01/paypal-well-their-tech-support-kinda.html' title='PayPal - well, their tech support kinda worked for me'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-1746639575708095881</id><published>2009-01-12T23:19:00.000-08:00</published><updated>2009-01-12T23:28:38.271-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe Illustrator'/><category scheme='http://www.blogger.com/atom/ns#' term='SVG'/><category scheme='http://www.blogger.com/atom/ns#' term='XamlTune'/><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><title type='text'>Convert Adobe Illustrator files to XAML via SVG</title><content type='html'>There are lots of ways to convert Adobe Illustrator files to XAML, but for my needs, none of them were quite good enough.&lt;br /&gt;&lt;br /&gt;The Adobe Illustrator XAML-export-plugin was mucking up some of our line art.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.inkscape.org/"&gt;InkScape's&lt;/a&gt; built-in XAML support was mucking things up even worse.  (I LOVE InkScape, but its XAML support is still not as good as hopefully it will be one day...)&lt;br /&gt;&lt;br /&gt;XamlTune was mucking up a few things here and there as well.&lt;br /&gt;&lt;br /&gt;Anyhow, I discovered that, for our line art, the main problem with XamlTune was its handling of thick strokes on ellipses.  I fixed the XamlTune source code, submitted a patch, and now, voila, XamlTune is converting our line art perfectly!  (Or at least, my eye notices no deficiencies.)&lt;br /&gt;&lt;br /&gt;Here are the steps I'm taking:&lt;br /&gt;&lt;br /&gt;1) Open the Adobe Illustrator file in Adobe Illustrator.  (A free 30 day trial is available.)&lt;br /&gt;&lt;br /&gt;2) Save a copy as an SVG document.  (There are lots of SVG options, but at least for us, the default SVG options work fine.)&lt;br /&gt;&lt;br /&gt;3) Use &lt;a href="http://www.codeplex.com/XamlTune"&gt;XamlTune&lt;/a&gt; to convert from SVG to XAML.&lt;br /&gt;&lt;br /&gt;I doubt my patch will be integrated into the main XamlTune source in a hurry, so if you have enough technical nouse, &lt;a href="http://www.codeplex.com/XamlTune/SourceControl/PatchList.aspx"&gt;get my patch from the XamlTune CodePlex site&lt;/a&gt; and enjoy the benefits.  :o)&lt;br /&gt;&lt;br /&gt;Your mileage may vary - apparently SVG to XAML conversion is not good at handling gradients, but all our line art is just simple sets of lines, paths and shapes, so that hasn't been a problem for us...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-1746639575708095881?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/1746639575708095881/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=1746639575708095881' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1746639575708095881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1746639575708095881'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/01/convert-adobe-illustrator-files-to-xaml.html' title='Convert Adobe Illustrator files to XAML via SVG'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-744205110658230683</id><published>2009-01-12T23:12:00.000-08:00</published><updated>2009-01-12T23:19:00.641-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XamlTune'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET bugs'/><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><title type='text'>"Cannot locate resource" in VS.NET 2008 when debugging</title><content type='html'>I downloaded XamlTune - very helpful, but a little buggy.  So I turned to the VS.NET 2008 debugger.  But every time I tried to run the XamlTune source code, I would get a "Cannot locate resource 'Output.xaml'" error message at runtime during app startup.&lt;br /&gt;&lt;br /&gt;I searched and searched and found zillions of people getting the "Cannot locate resource" error message, but nothing solved the problem in this case.&lt;br /&gt;&lt;br /&gt;By trial and error, I finally discovered that the assembly name is the culprit in this case.&lt;br /&gt;&lt;br /&gt;The XamlTune "solution" contains a DLL called XamlTune and a separate executable by the same name.&lt;br /&gt;&lt;br /&gt;XamlTune.dll&lt;br /&gt;XamlTune.exe&lt;br /&gt;&lt;br /&gt;In Release mode, this runs fine, and presumably, in previous versions of VS.NET, it ran fine.  But in VS.NET 2008 sp1, running in Debug mode, the aforesaid error occurs.&lt;br /&gt;&lt;br /&gt;The solution is extremely simple: Change one or other project file so that the assembly names of the two projects differ.&lt;br /&gt;&lt;br /&gt;Clearly a bug in the VS.NET or .NET framework implementation, and it certainly wasted hours of my time today, but when you know how to solve it, everything works nicely again...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-744205110658230683?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/744205110658230683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=744205110658230683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/744205110658230683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/744205110658230683'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/01/cannot-locate-resource-in-vsnet-2008.html' title='&quot;Cannot locate resource&quot; in VS.NET 2008 when debugging'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-9157492575088454373</id><published>2009-01-12T21:40:00.001-08:00</published><updated>2009-01-12T23:10:18.997-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SVG'/><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><category scheme='http://www.blogger.com/atom/ns#' term='vector graphics stroke'/><title type='text'>XAML stroke - inconsistent, but livable if you know the tricks...</title><content type='html'>I'm using XamlTune to convert SVG to XAML.  Ellipses with thick strokes weren't converting correctly.  I dug deeper, and discovered that XAML is inconsistent in its treatment of stroke placement.&lt;br /&gt;&lt;br /&gt;For paths, the stroke is centred on the path line (as with SVG).  But with ellipses and rectangles (and hence circles and squares too), XAML draws the stroke INSIDE the perimeter line.  SVG is consistent - the stroke is always centred on the perimeter line.&lt;br /&gt;&lt;br /&gt;Anyhow, I had difficulty finding info on this anywhere, so I tested my theory with some practical examples.&lt;br /&gt;&lt;br /&gt;In XAML, create an Ellipse with e.g. a 100 pixel diameter.&lt;br /&gt;&lt;br /&gt;&amp;lt;Ellipse Width="100" Height="100" Fill="Yellow" /&amp;gt;&lt;br /&gt;&lt;br /&gt;Then set a very wide stroke:&lt;br /&gt;&lt;br /&gt;&amp;lt;Ellipse Width="100" Height="100" Fill="Yellow" StrokeThickness="50" Stroke="Blue" /&amp;gt;&lt;br /&gt;&lt;br /&gt;Voila!  Note that the size of the circle is the same whether there is a stroke or not.  Thus, XAML uses an internal stroke for ellipses.&lt;br /&gt;&lt;br /&gt;But do the same thing in Inkscape (i.e. in SVG) and the circle gets larger as the stroke gets wider.&lt;br /&gt;&lt;br /&gt;Since I found it hard to find anyone else commenting on the same "gotcha", I thought I'd make note of it here...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-9157492575088454373?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/9157492575088454373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=9157492575088454373' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9157492575088454373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9157492575088454373'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2009/01/xaml-stroke-inconsistent-but-livable-if.html' title='XAML stroke - inconsistent, but livable if you know the tricks...'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-1228585715335427817</id><published>2008-12-05T23:24:00.001-08:00</published><updated>2008-12-05T23:31:04.125-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008'/><title type='text'>SQL Server 2008 Express Edition</title><content type='html'>I've just installed SQL Server 2008 Express Edition.&lt;br /&gt;&lt;br /&gt;Thought #1 : It rocks.&lt;br /&gt;&lt;br /&gt;I found SQL Server 2005 (particularly the SQL Server 2005 Management Studio Express) to be VERY slow - you know, 10 second delay here, 10 second delay there.  And btw, I'm using a very powerful machine.&lt;br /&gt;&lt;br /&gt;None of that ridiculous stuff (so far) from SQL Server 2008 - bam!  Responsive.  Fast.  I like.&lt;br /&gt;&lt;br /&gt;Thought #2 : It's extremely unintuitive figuring out how to install SQL Server 2008 Management Studio Express.&lt;br /&gt;&lt;br /&gt;SQL Server 2008 Express Edition installed with my version of .NET Studio 2008 Express.  But no Management Studio.  I find Management Studio particularly useful, so I wanted to install it.&lt;br /&gt;&lt;br /&gt;Problem #1 : It's now called Management Studio &lt;span style="font-style:italic;"&gt;Basic&lt;/span&gt; instead of Management Studio &lt;span style="font-style:italic;"&gt;Express&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Problem #2 : With SQL Server 2005 Express Edition, you could download and install the Management Studio separately.  Turns out that option ain't available with SQL Server 2008 Express Edition.  You actually have to download a 200MB+ install package that includes both SQL Server 2008 Express Edition and the Management Studio.  That's not obvious, but once you know it, ok, you can move on...&lt;br /&gt;&lt;br /&gt;Problem #3 : When you launch this installer, it is extremely unintuitive finding how to install just the Management Studio, given that (if you're in the case I was in) you already have SQL Server 2008 Express Edition installed and just want the Management Studio to be installed.&lt;br /&gt;&lt;br /&gt;Many many MANY thanks to these guys who wrote an article which gave me just enough information that, with a bit of trial and error, I finally managed to triumph.  If you're in the same boat as me, go to &lt;a href="http://www.asql.biz/Articoli/SQLX08/Art1_2.aspx"&gt;Installing SQL Server Express 2008&lt;/a&gt; and it shows you the things you need to know.  Kudos!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-1228585715335427817?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/1228585715335427817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=1228585715335427817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1228585715335427817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/1228585715335427817'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2008/12/sql-server-2008-express-edition.html' title='SQL Server 2008 Express Edition'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-3187362408315880297</id><published>2008-12-03T19:53:00.000-08:00</published><updated>2009-01-14T23:00:14.516-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PayPal'/><title type='text'>PayPal - systems gone awry</title><content type='html'>&lt;span style="font-style: italic;"&gt;Strong language warning&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hello PayPal,&lt;br /&gt;&lt;br /&gt;I hope that the reports of abysmal/non-existent PayPal service are false, because this situation is entirely PayPal's fault, and I've heard lots of stories of PayPal screwing customers when the situation was not the customer's fault.&lt;br /&gt;&lt;br /&gt;My wife made a purchase online using her credit card.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;She does NOT and has NEVER had a PayPal account.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;She did NOT log in to PayPal to make the purchase - she simply typed in her credit card number.&lt;br /&gt;&lt;br /&gt;It so happens that she is an additional card holder for my credit card account.&lt;br /&gt;&lt;br /&gt;It so happens that I have two PayPal accounts, and my credit card is linked to one of those accounts.&lt;br /&gt;&lt;br /&gt;You, PayPal, decided behind the scenes to link my wife's online purchase to my PayPal account, &lt;span style="font-weight: bold;"&gt;but you have done so in a way that has broken everything&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I will go into full detail below, but &lt;span style="font-weight: bold;"&gt;the present ludicrous situation is that YOU PayPal are demanding that my wife log in to her non-existent PayPal account to restore her account access.  She cannot log in to her account, because she does not have one &lt;/span&gt;(and has never had one).&lt;span style="font-weight: bold;"&gt;  And in the meantime, my own PayPal account is disrupted, and logging in to my own PayPal account has not resolved the issue.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you have gotten this far, thank you for taking the time to consider that it might be possible to improve the PayPal systems.  (If not, then I sincerely hope you are supplanted by someone who actually acknowledges their mistakes and improves their game.)&lt;br /&gt;&lt;br /&gt;Here is what happened :&lt;br /&gt;&lt;br /&gt;* Early July, my wife made the purchase as previously described (from "Hallelujah Acres"), using a computer I do not use, that was not logged in to PayPal.  She entered the credit card number directly.&lt;br /&gt;&lt;br /&gt;* At around the same time, I used PayPal (on a different computer, and logging in to my PayPal account) to donate a small sum of money (around US$10) to someone else.&lt;br /&gt;&lt;br /&gt;* Weeks later (international delivery, so it took a while), we received the goods my wife purchased (some health food).&lt;br /&gt;&lt;br /&gt;* My wife, reviewing our credit card statement, saw a large PayPal transaction.  The credit card statement read "PAYPAL *BFOBUILDING &lt;span style="font-style: italic;"&gt;&amp;lt;number removed from this public copy of this email&amp;gt;&lt;/span&gt;".  The number matched my PayPal account number.  I knew that the only recent activity on my account was the US$10 donation.  &lt;span style="font-weight: bold;"&gt;I logged in to my PayPal account, and the small donation was the only transaction visible.&lt;/span&gt;  The bank statement said PayPal took the money, and related it to my PayPal account number, but PayPal denied knowledge of the transaction, claiming nothing had happened.  I knew nothing had happened on my PayPal account, because I had not used PayPal for a very long time, except for that small donation.  Accordingly, it was evident that fraud or computer error had occurred.  For the first and only time in my (lengthy) credit card history, I raised a chargeback with my bank.&lt;br /&gt;&lt;br /&gt;* On the 4th of September, my wife got a phone call out-of-the-blue from a woman in America.  This woman politely asked why we had issued a chargeback.  My wife was confused.  My brain made a few quick connections and I suspected I knew what had happened.  I took the phone from my wife and spoke with the woman.  Lo-and-behold, she was from Hallelujah Acres, and the PayPal transaction we had rejected was for the health food we purchased.  But how were we to know?  &lt;span style="font-weight: bold;"&gt;PayPal was indicted on the bank statement, yet my PayPal account claimed ignorance.&lt;/span&gt;  Anyhow, as soon as I realised that the transaction was valid - even though &lt;span style="font-weight: bold;"&gt;misreported by PayPal&lt;/span&gt; - I promised to contact my bank and undo the chargeback - which I promptly did.  (I contacted my bank, asked what to do, and sent in a detailed fax re-authorising the transaction as they advised me to do.)&lt;br /&gt;&lt;br /&gt;Whilst it was irresponsible of PayPal to put us and the vendor through this hassle (by representing to my bank that the payment came from my PayPal account, yet showing no evidence of it in my PayPal account), that is only half the story.  My wife subsequently received an email from PayPal declaring that she must re-activate her account due to the recent chargeback.  She never had an account.&lt;br /&gt;&lt;br /&gt;But it goes on.  I had reason to wish to use PayPal again just recently, but discovered that my own PayPal account is not working properly.  Realising it was probably related to this whole stupid debacle, and having heard only bad things about PayPal's moronic support policies (or "no support" policies), I didn't even bother contacting you.&lt;br /&gt;&lt;br /&gt;Now my wife receives a second email insisting that she must re-activate her non-existent account, and threatening account closure if she takes no action.&lt;br /&gt;&lt;br /&gt;Based on how poorly your automated systems have performed in the past, it seems likely you will accidentally (or is that deliberately?) close my own good account too, and without warning, and without cause.&lt;br /&gt;&lt;br /&gt;I have used PayPal in the past.  The only trouble I have ever caused PayPal is by acting in good faith on information PayPal itself provided - i.e. by you not showing in my account history the transaction in question, but you simultaneously reporting to my credit card provider that the transaction in question actually did come from that selfsame account, you were clearly telling me that the transaction was in error or a fraud, and I acted in good faith on that information you provided.  And now you insist on continuing to confuse and bamboozle my innocent wife by telling her to take action with her non-existent PayPal account, and you continue to frustrate myself and any vendors I might purchase from in the future by disabling my own account to some extent yet not providing me any way of re-enabling my own account.&lt;br /&gt;&lt;br /&gt;I have joined the long list of people who have found PayPal to be a farce, a joke.&lt;br /&gt;&lt;br /&gt;If you resolve this issue, without further ridiculous hassle or effort on the part of myself or my wife, I will be impressed.  And I will blog about it to counter the voices of those who say that PayPal never cares.&lt;br /&gt;&lt;br /&gt;But there are too many sad stories out there for me to believe that you will.&lt;br /&gt;&lt;br /&gt;Which way will it be?&lt;br /&gt;&lt;br /&gt;Here's hoping,&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jonathan Field&lt;br /&gt;&lt;br /&gt;UPDATE Thu 15-Jan-2009 : &lt;a href="http://selfdocumentingcode.blogspot.com/2009/01/paypal-well-their-tech-support-kinda.html"&gt;PayPal replied&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-3187362408315880297?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/3187362408315880297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=3187362408315880297' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3187362408315880297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/3187362408315880297'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2008/12/paypal-systems-gone-awry.html' title='PayPal - systems gone awry'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-9114126977147610266</id><published>2007-10-06T18:47:00.000-07:00</published><updated>2007-10-06T18:56:01.052-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePod'/><category scheme='http://www.blogger.com/atom/ns#' term='iPod'/><title type='text'>SharePod - get MP3s off your iPod</title><content type='html'>I guess most iPod users have had the frustration of having legitimate MP3s on their iPod, losing the originals on their computer, and having no easy way to get the MP3s back.&lt;br /&gt;&lt;br /&gt;In my case, I had an AWESOME conference on my iPod, and I had the right to give other people copies of the conference, but I misplaced my master CD with the original MP3s, and I didn't feel like spending three hours digging through my vast and relatively disorganised collections of "stuff" just to find it.&lt;br /&gt;&lt;br /&gt;I turned to Google, as I usually do when I need help.  To my dismay, there were lots of programs that claimed to do wonders for your iPod, but only a few of them, when actually tested, offered the specific feature I needed.  Worse, ALL of the ones I found were commercial programs and wouldn't extract the entire length of each track.  Now, given that I'm distributing this conference as a public service, and this is the &lt;span style="font-style: italic;"&gt;only&lt;/span&gt; thing I wanted to get off my iPod, paying US$40 seemed ridiculously steep.&lt;br /&gt;&lt;br /&gt;And then, somehow - hallelujah - I encountered &lt;a href="http://www.sturm.net.nz/website.php?Section=iPod+Programs&amp;amp;Page=SharePod"&gt;SharePod&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;It did what I needed, first time, no worries.&lt;br /&gt;&lt;br /&gt;And it's freeware.&lt;br /&gt;&lt;br /&gt;If I find myself using it a fair bit more in the future, I will very likely send the developer a donation.  Hey - I might even send them a small $5 or $10 donation just for the help it's already been.  (That's still cheap compared to the US$40 ask elsewhere.)&lt;br /&gt;&lt;br /&gt;So if you're counting your pennies and you have a bunch of MP3s buried in your iPod and need to get them back out, &lt;a href="http://www.sturm.net.nz/website.php?Section=iPod+Programs&amp;amp;Page=SharePod"&gt;SharePod&lt;/a&gt; comes with a five-star recommendation from yours truly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-9114126977147610266?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/9114126977147610266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=9114126977147610266' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9114126977147610266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/9114126977147610266'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2007/10/sharepod-get-mp3s-off-your-ipod.html' title='SharePod - get MP3s off your iPod'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-4621671140463100963</id><published>2007-09-16T07:53:00.000-07:00</published><updated>2007-09-17T04:13:48.588-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>CSS best practice : bold and italics</title><content type='html'>CSS is a marvel.  Separation of content and layout is almost a life-saver.&lt;br /&gt;&lt;br /&gt;But somehow, somewhere along the line, a big bunch of programmers have gone overboard into CSS stupidity.&lt;br /&gt;&lt;br /&gt;Consider blogger.com.  They shun the &amp;lt;em&amp;gt; and &amp;lt;strong&amp;gt; tags in favour of &amp;lt;span&amp;gt; tags with inline CSS.&lt;br /&gt;&lt;br /&gt;Yes, it's true that in the bad ol' days, programmers used the &amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; tags to mark headers, and yes it's true that &lt;i&gt;that&lt;/i&gt; should stop (and should have stopped some years ago).  If you're making a header, use a header tag, and use &lt;i&gt;CSS&lt;/i&gt; (not &amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; tags) to define the visual appearance of your header.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;But &amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; have a proper use as content-bearing tags.&lt;/i&gt;  The use of bold and italics is as intrinsic to the writing process as the use of all-caps was before bold and italics came on the scene.  The &amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; tags, correctly used, are &lt;i&gt;not&lt;/i&gt; formatting tags.  They are &lt;i&gt;content&lt;/i&gt; tags.&lt;br /&gt;&lt;br /&gt;Now here's where things get &lt;b&gt;really&lt;/b&gt; interesting.  Suppose you want to quote someone, and you want the quote to appear italicized, but suppose the quote already contains italics.  Doing things my (sane) way, no problem.  Doing things Blogger's way, and you are stuck down the creek without a paddle.&lt;br /&gt;&lt;br /&gt;e.g. suppose I'm building a sales site for XYZ company, and they have a few customer testimonials in the righthand sidebar.&lt;br /&gt;&lt;br /&gt;Here's fictitious testimonial #1 :&lt;br /&gt;&lt;br /&gt;"You guys are &lt;i&gt;awesome&lt;/i&gt;!  Your product has changed my life!"&lt;br /&gt;&lt;br /&gt;Now, let's do this the proper CSS way, and create a class named "Testimonial".&lt;br /&gt;&lt;br /&gt;&amp;lt;span class='Testimonial'&amp;gt;"You guys are &amp;lt;em&amp;gt;awesome&amp;lt;/em&amp;gt;!  Your product has changed my life!"&amp;lt;/span&amp;gt;&lt;br /&gt;&lt;br /&gt;Obviously, we define the Testimonial class in our CSS file as follows :&lt;br /&gt;&lt;br /&gt;&lt;code&gt;span.Testimonial&lt;br /&gt;{&lt;br /&gt;  font-style:italic;&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;All well and good, until someone notices that there is no difference now between the word "awesome" and the other words.  &lt;i&gt;Everything's&lt;/i&gt; italicized.  What to do?  Ah!  Simple solution!  CSS to the rescue!  Add another definition to the CSS file :&lt;br /&gt;&lt;br /&gt;&lt;code&gt;span.Testimonial i&lt;br /&gt;{&lt;br /&gt;  font-style:normal;&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Voila!&lt;/b&gt;&lt;/i&gt;  We have now preserved the "content" embodied in the &amp;lt;em&amp;gt; tag.  Remember, &amp;lt;em&amp;gt; doesn't so much mean "make this italic" as much as it means "emphasize this".  With the simple CSS given above, we have retained the emphasis of the enclosed &amp;lt;em&amp;gt; tag, by actually making it &lt;i&gt;non-&lt;/i&gt;italicized.&lt;br /&gt;&lt;br /&gt;In contrast, here's what Blogger does when you italicize some text :&lt;br /&gt;&lt;br /&gt;"You guys are &amp;lt;span style="font-style:italic;"&amp;gt;awesome&amp;lt;/span&amp;gt;!  Your product has changed my life!"&lt;br /&gt;&lt;br /&gt;Can you see the problem?  We can wrap it in our Testimonial span :&lt;br /&gt;&lt;br /&gt;&amp;lt;span class='Testimonial'&amp;gt;"You guys are &amp;lt;span style="font-style:italic;"&amp;gt;awesome&amp;lt;/span&amp;gt;!  Your product has changed my life!"&amp;lt;/span&amp;gt;&lt;br /&gt;&lt;br /&gt;... but we have completely lost a piece of content - being the emphasis on the word "awesome".&lt;br /&gt;&lt;br /&gt;Now you might think you're really clever and point out that you could always make a CSS definition like this :&lt;br /&gt;&lt;br /&gt;&lt;code&gt;span.Testimonial span&lt;br /&gt;{&lt;br /&gt;  font-style:normal;&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;... but if you'd given it a few moments more thought, you would have realized that this only works if you limit content to one type of emphasis &lt;b&gt;only&lt;/b&gt;.  Suppose a different testimonial used bold instead of italics, and still another used both bold &lt;b&gt;and&lt;/b&gt; italics.  Bummer.  You're done for.&lt;br /&gt;&lt;br /&gt;In short?  &lt;b&gt;&amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; are content-bearing tags&lt;/b&gt;.  Sure - they've been misused and abused as formatting tags (e.g. where header tags should have been used instead), but the misuse doesn't change the fact that there is and always will be a very vital content-bearing role that these tags must carry.  Many programmers think they're oh-so-clever and oh-so-standards-aware and oh-so-CSS-knowledgeable by replacing &amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; tags with &amp;lt;span&amp;gt;s that have inline styles, but in the process they are actually violating the very intention of CSS - they are replacing a content-bearing tag with what (in the way they use it) is actually a formatting element!  &lt;b&gt;Separation of content and formatting demands that ONLY &amp;lt;strong&amp;gt; and &amp;lt;em&amp;gt; tags be used to accomplish emboldening and italicization in the flow of content&lt;/b&gt;.  Replacing them with spans that have inline styles might make you feel clever, but it violates the coremost principles of CSS.  &lt;i&gt;And&lt;/i&gt; it makes your pages bigger.&lt;br /&gt;&lt;br /&gt;So there.  :o)&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Tune in next week for another episode of "&lt;/i&gt;CSS Bloopers&lt;i&gt;" - the exciting program where your coding practices are mercilessly ripped to shreds.  :o)&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-4621671140463100963?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/4621671140463100963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=4621671140463100963' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4621671140463100963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/4621671140463100963'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2007/09/css-best-practice-bold-and-italics.html' title='CSS best practice : bold and italics'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6417768165545673771</id><published>2007-09-16T07:19:00.000-07:00</published><updated>2007-09-16T07:34:59.205-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET hosting'/><title type='text'>When ASP.NET support isn't ASP.NET support</title><content type='html'>&lt;a href='http://www.1and1.com/'&gt;1and1.com&lt;/a&gt; offer cheap hosting deals and I was quick to sign up.  I needed ASP.NET hosting and they fit the bill.  Or so I thought.&lt;br /&gt;&lt;br /&gt;Some of my ASP.NET apps sit atop  Microsoft Access databases.  (Scream and holler all you like, but there are good reasons in the cases it is so.)  1and1 sales material says their Microsoft hosting accounts support ASP.NET, SQL Server, Access, etc, etc.  All fine and dandy, right?&lt;br /&gt;&lt;br /&gt;What they &lt;span style="font-style:italic;"&gt;didn't&lt;/span&gt; tell me in advance (or else I would have gone elsewhere) is that Access support is &lt;span style="font-style:italic;"&gt;only available for old-style ASP&lt;/span&gt;.  That's right : if you have an ASP.NET app, &lt;span style="font-style:italic;"&gt;it cannot use Access&lt;/span&gt;.  It has to use SQL Server.  That might not sound so bad, but if you signed up expecting otherwise (and reasonably so on the basis of their sales material), you'd be in for a shock.&lt;br /&gt;&lt;br /&gt;I bought a "professional" hosting package, which comes with 5 sites, etc, etc.  But it only allows &lt;span style="font-style:italic;"&gt;one&lt;/span&gt; SQL Server database, with a size cap of 100MB.  So switching certain apps over to SQL Server wasn't the answer either.&lt;br /&gt;&lt;br /&gt;And finally, I just discovered today that they don't support setting up your 5 sites as separate ASP.NET web applications!  Crikey!  They could at least have told me this at the start.  In other words, you can have &lt;span style="font-style:italic;"&gt;one&lt;/span&gt; web app with five domain names pointing at it, but you can't have five discrete web apps.  So much for their "professional" package.&lt;br /&gt;&lt;br /&gt;So if you have only a single site and a 100MB SQL Server database is more than enough, get one of the low-end 1and1.com packages.  Or if you need a zillion sites, maybe one of their uber-high-end packages will do the trick, but this so-called "Professional" package stinks.  It looks good on paper, but 1and1.com have severely limited it's usefulness, and without adequate pre-sale disclosure.&lt;br /&gt;&lt;br /&gt;So, when you're going for cheap ASP.NET hosting, whether 1and1.com or elsewhere, &lt;span style="font-style:italic;"&gt;and you have a handful of sites you want to host&lt;/span&gt; (e.g. in my case, a business site, a blog, and a freebie language-education website on the side), then beware you don't get suckered in to this same trap.&lt;br /&gt;&lt;br /&gt;I hope this saves someone else the frustration and wasted time I've had to go through.  That's all folks.  Tune in next week for another episode of "&lt;span style="font-style:italic;"&gt;And They Told Us Computers Would Make Life Easier...&lt;/span&gt;".  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6417768165545673771?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6417768165545673771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6417768165545673771' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6417768165545673771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6417768165545673771'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2007/09/when-aspnet-support-isnt-aspnet-support.html' title='When ASP.NET support isn&apos;t ASP.NET support'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9013148337555241633.post-6240669501025662612</id><published>2007-09-16T05:57:00.000-07:00</published><updated>2007-09-16T06:37:07.974-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='clipboard'/><title type='text'>Set Arbitrary Text To The Clipboard Using Javascript</title><content type='html'>You want to set a value to the clipboard, using javascript in a browser window.&lt;br /&gt;&lt;br /&gt;And it needs to work in Internet Explorer and in Mozilla/FireFox.&lt;br /&gt;&lt;br /&gt;You'd think it would be simple.  It is, after all, the 21st century.&lt;br /&gt;&lt;br /&gt;Think again.&lt;br /&gt;&lt;br /&gt;The nearest to simple is a &lt;a href='http://www.krikkit.net/howto_javascript_copy_clipboard.html'&gt;script by Krikkit&lt;/a&gt;.  The very very short of it is that after over three hours of wasted time, I have a much simplified version of the script.  Kudos to Krikkit for getting the script to the point he did - without it, I would have gotten nowhere.  But this version is definitely superior because a) the comments are in English not Dutch :o) and b) it is very roughly only half the lines ('coz I found an alternative and much simpler way to accomplish the same thing).&lt;br /&gt;&lt;br /&gt;So here's the code.  It works in Internet Explorer and Mozilla/FireFox.  Sorry - no Opera and I don't know about Safari.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;function CopyStringToClipboard(s)&lt;br /&gt;{&lt;br /&gt;  if (window.clipboardData)&lt;br /&gt;  {&lt;br /&gt;    /* Internet Explorer does things this way */&lt;br /&gt;    window.clipboardData.setData("Text", s);&lt;br /&gt;  }&lt;br /&gt;  else if (window.netscape)&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;      netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');&lt;br /&gt;    } catch (ex) {window.alert("Mozilla is not configured to allow this script to set the clipboard data.");return;}&lt;br /&gt;&lt;br /&gt;    var ClipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);&lt;br /&gt;    ClipboardHelper.copyString(s);&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;However, life ain't quite &lt;span style="font-style:italic;"&gt;that&lt;/span&gt; simple.  FireFox will refuse to allow clipboard access (even just the humble lowly setting of clipboard data) unless the user makes a config change.  Argh!  That's ok-ish for techies like me who are making an app for internal use (as is the case right now), but if you're doing it for wider distribution...&lt;br /&gt;&lt;br /&gt;Anyhows, the folks at Febooti have done a wonderful job of explaining exactly &lt;a href='http://www.febooti.com/support/website-help/website-javascript-copy-clipboard.html'&gt;which setting needs to be changed and how&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Credits :&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.krikkit.net/howto_javascript_copy_clipboard.html'&gt;Krikkit's version&lt;/a&gt; - comments are in Dutch and it's much more complicated than necessary, but bravo, it does the job, and that's the main thing that matters, so definitely kudos in that direction&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.gamedev.net/community/forums/topic.asp?topic_id=281951'&gt;The broken Dutch version but with the comments having been translated from Dutch into English&lt;/a&gt; - and that's where I got the English comments I've used in my version, except that it also wasted me a slab of time because for no apparent reason, this version added square brackets around some numbers in the javascript, which caused it to not work, and it took a while to figure out what on earth was happening...  Nonetheless, kudos for speaking both Dutch and English, or at very least, for taking initiative to pump the comments through an automated translator.  :o)&lt;br /&gt;&lt;br /&gt;... and thanks to the Mozilla Developer Centre where I finally found a much simpler way to accomplish the same thing.  (But I still credit the Dutch version for part of the solution 'coz without it, I would never have known about that obscure "UniversalXPConnect" setting.)&lt;br /&gt;&lt;br /&gt;That's all folks!  Tune in next week for another episode of "&lt;span style="font-style:italic;"&gt;And they told us computers would save time...&lt;/span&gt;".  :o)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9013148337555241633-6240669501025662612?l=selfdocumentingcode.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://selfdocumentingcode.blogspot.com/feeds/6240669501025662612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9013148337555241633&amp;postID=6240669501025662612' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6240669501025662612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9013148337555241633/posts/default/6240669501025662612'/><link rel='alternate' type='text/html' href='http://selfdocumentingcode.blogspot.com/2007/09/set-arbitrary-text-to-clipboard-using.html' title='Set Arbitrary Text To The Clipboard Using Javascript'/><author><name>Verbose Philosopher</name><uri>http://www.blogger.com/profile/12350168666303344236</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
