I rendered a special Apophysis flame just for the occasion.
Sorry it’s shrunken. If you’d like a full render or the flame file, just shoot me an email.
I call it “Snowflakes”
Have a great holiday and a happy New Year!
I have an InstallShield-authored MSI installation for an application I work on.
In testing one of the recent interations, I ran into a peculiar problem.
It installed perfectly fine, and after an uninstall, virtually everything was removed properly, except for one particular component.
It didn’t go away.
I turned verbose MSI logging on (see here for details how), and reran the install/uninstall.
For the install, somewhere toward the top of the log, you should see a block that looks like this:
MSI (s) (9C:D8) [16:43:17:376]: Feature: Some Feature; Installed: Absent; Request: Local; Action: Local
MSI (s) (9C:D8) [16:43:17:376]: Feature: Some other feature; Installed: Absent; Request: Local; Action: Local
MSI (s) (9C:D8) [16:43:17:376]: Component: InstallMSXML6; Installed: Absent; Request: Null; Action: Null
MSI (s) (9C:D8) [16:43:17:376]: Component: InstallSQLSMO; Installed: Absent; Request: Null; Action: Null
Notice the Installed state is absent and the action is local, meaning that the feature/component doesn’t already exist on the machine and it’s going to be installed locally (the normal installation type).
After an uninstall, the log will contain a similar block, but just reversed:
MSI (s) (9C:B8) [17:00:19:887]: Feature: Some Feature; Installed: Local; Request: Absent; Action: Absent
MSI (s) (9C:B8) [17:00:19:887]: Feature: Some Other feature; Installed: Local; Request: Absent; Action: Absent
MSI (s) (9C:B8) [17:00:19:887]: Component: InstallMSXML6; Installed: Absent; Request: Null; Action: Null
MSI (s) (9C:B8) [17:00:19:887]: Component: InstallSQLSMO; Installed: Absent; Request: Null; Action: Null
Note the Installed state of Local but the action is now absent (at least on the two features noted above).
However, my problem component looked like this
MSI (s) (9C:B8) [17:00:19:887]: Component: ProblemComponent; Installed: Local; Request: Absent; Action: Null
And what stumped me was, why a null action? The Request was absent, so why wasn’t the action?
I researched the problem a little and got nowhere, then tried tweaking the install several different ways; still no joy.
I finally broke down and put a call into Macrovision. Ended up talking to one of their guys (Thanks, Cary!) and the first thing he asked was, “Search for Disallow” in the log starting at the top and see if there’s anything mentioned.”
Ok. And sure enough, I had several lines like this.
MSI (s) (9C:B8) [17:00:19:626]: Disallowing uninstallation of component: {997FA962-E067-41D1-9396-00A0C90F27F9} since another client exists
After a little GUID spelunking (you can find GUIDs easily in InstallShield by opening the direct editor
clicking on the component table and sorting by the component ID)
I was able to determine that the problem component, was indeed one of those whose uninstallation was disallowed.
(You might see a number of “Disallowing” lines in your log, often as a result of including Merge modules of standard libraries, like the COM libraries or the VB runtime files, so you have to just ignore them).
So I figured, just search the registry for the GUID in question and remove whatever junk was left over, probably from an aborted install.
No dice. The component information used to track reference counting (which is how MSI knows to “disallow uninstallation since another client exists”) is locked up in a binary registry entry, from what I can tell.
In the end, you’ll generally have two options.
Not fun, but not too bad.
I have some pretty in-depth experience working with the VB6 exception handling mechanism. I still get an occasional email about my article on Try-Catch exception handling in VB6 in the Sept 2001 Visual Basic Programmer’s journal.
So when I finally got a chance to crack open the Enterprise Application Block and check out the Exception Handling App Block, I was hoping for some pretty nice stuff, or at least something to give me a few ideas.
But what’s there seems pretty underwhelming.
The good news is that most of the stack tracing and related informational-type things that you really had to work very hard at with VB6, are part and parcel to VB.NET. The bad news is that the exception handling application block doesn’t seem to contain much at all to actually make handling exceptions any easier than piling mountains of Try-Catch lines into your source.
Hmm, Try…Catch…Finally, or On Error Goto Handler…Handler: …Resume next
Under the covers, I know they’re very different, but seriously, what I see is just syntactic shuffling.
I’ve always believed that virtually all exception handling in an app should be attributable to individual routines. That’s the way my exception handler for VB6 worked, just without all the syntactic niceties of .NET.
For instance, why shouldn’t I be able to attribute a routine as to how exceptions within it ought to be handled?
<HandleExceptionsByContinuing> _
Public Sub MySub(arg1, arg2, arg3)
x = 1 / 0
End Sub
In this case, I’ve declared that for this particular method, exceptions ought to be handled by simply continuing execution of the code.
Other cases might raise a specific error, reraise the original error, reraise the original error wrapped in an outer exception, etc. Granted, my example may not be great here.
Most routines are supposed to be so small that having more than one TRY statement would be lame anyway, right? And most of the code I’ve looked at containing Try Catch blocks only contain one in a method anyway.
For those routines where you definitely need to handle specific exception in specific ways, you still have the Try statement to fall back on, but even then, I tend to believe that every exception in an app should be routed through a single handler that can be configured to do certain things, be it emailing the exception, logging it, or (and I’m not recommending this, mind you!) ignoring it altogether.
Littering the workings of your code with boilerplate Try Catch filler strikes me as equally onerous as those comments like:
'Increase the count variable by one
Count = Count + 1
Ugh.
But, just like a well placed comment, when the workings of the code are better explained with inline exception handling, TRY away!
Might be time for my own Enterprise Exception Handling Block…
If you’re not familiar with steampunk, it’s the illegitimate offspring of retro-futurism, a mid-1800’s Sears catalog, The Jetsons, and This Old House.
That god awful Will Smith movie, Wild Wild West, is probably the most, er, public, of examples. Kenneth Branagh surely should have known better.
But a guy calling himself Datamancer has to have created one of the nicest examples I’ve ever seen, the steampunk laptop, complete with winding key for an off/off switch, brass lions claw feet, and a watch-gears guts under a hardwood framed glass viewing window. According to the site, the thing actually works.
This is just one picture, and it doesn’t really do it justice. Check out his site for lots more, plus some unbelievable steampunk keyboards he sells.
I’ve seen a very nice effect on a number of blogs where code snippets were formatted and (somewhat) syntax highlighted.
I finally got a chance to do some digging and turned up the very cool javascript package called dp-highlighter.
In a nutshell, you put the dp-highlighter files in a folder on your website, then add the following code toward the bottom of any page that needs code highlighted:
<link type="text/css" rel="stylesheet" href="./dphighlighter/SyntaxHighlighter.css"></link> <script language="javascript" src="./dphighlighter/shCore.js"></script> <script language="javascript" src="./dphighlighter/shBrushVB.js"></script> <script language="javascript" src="./dphighlighter/shBrushXml.js"></script> <script language="javascript"> dp.SyntaxHighlighter.ClipboardSwf = 'dphighlighter/clipboard.swf'; dp.SyntaxHighlighter.HighlightAll('code'); </script>
Make sure you change the shBrushVB.js to whichever language parser you want to use. Also, I put the files in a dphighlighter folder, but you can put them anywhere, really, just be sure to update the paths above.
Finally, for code you want to highlight, just stick it in a <PRE> tag, and add NAME=”code” CLASS=”VB”, like this
<pre name="code" class="vb">
if you got it right, you’ll end up with something like this:
Public Property Let HelpFile(ByVal NewValue$) If rbPrologueActivated Then rExc.HelpFile = NewValue$ Else VBA.Err.HelpFile = NewValue$ End If End Property
There’s lots more documentation and examples at the link above.
I got up this morning and was helping Gillian, my daughter (she’s almost 4) downstairs to get dressed, when she asked (quite out of nowhere, I might add):
“Daddy, can you help me built a giant robot butterfly that I can fly around on?”
Awesome.
I’m working my way through the quite laborious installation of Visual Studio Team Foundation Server when I came across this gem (seriously, it’s in the TFSInstall-v071203.chm Team Foundation Server installation guide):
Before you install Visual Studio 2005 Team Foundation Server Service Pack 1,
you must first download and install the Visual Studio Team Foundation Server Quiescence GDR.
Now, I love big words as much as any logophile, but to name a service pack a Quiescence GDR? And what the hell is that, anyway? It means “At rest or still”. So… That SP is for all your machines that aren’t installed in motor vehicles, maybe?
I’m already waiting for agonizing install processes and prerequisites. Now MS is improving my vocabulary, too. Grrr.
Who said IT isn’t just one big wild and crazy ride!
Tell me I’m missing something here.
Team Foundation Server is this massive, be-all behemoth from Microsoft that rolls defect tracking, worklists, source code control, and your mother’s favorite recipes all into one Visual-Studio integrated package.
Sounds good.
But is this for real?
Granted, the post is from 2005, but looking at the latest TFS 2008 docs online, there doesn’t appear to be any newer method.
Essentially, what it says is that to add a field to the bug tracking form, or the task form, or to change the lookup values in existing fields on those forms, or to edit a form in pretty much any way, you have to:
Did I just fall backwards into a Delorean and hit the ’85 button?
You can’t throw a Dilbert Doll these days without hitting a bug tracking solution and I haven’t seen one in recent memory that didn’t have some kind of integrated forms designer. Actually, I can’t say I’ve ever seen one that didn’t. Hell, Outlook has an integrated forms designer.
So, I’ve gotta be missing something, right?
Right?
I recently had the need to burn several duplicates of a CD I made, and I’ve always used Nero Burning Rom for that in the past.
This time, however, I’d upgraded to Vista, and my copy of Nero (a version that came in the box with a DVD drive I bought some time ago) wouldn’t run any longer.
Strike 1
I fire up VMWare, thinking I could install it to a VM. Unfortunately, it doesn’t look like VMWare supports the virtualization of a DVD RW or CD RW drive yet.
Strike 2
So I start rummaging around the net for something.
What I found was a mountain of programs to do the job, but they all seemed lacking in one respect or another. Worse, they generally sell for 20-50$, which isn’t bad, but considering this is Vista, I’d have thought a decent CD/DVD package would have been in the box.
Eventually, I came across BurnAtOnce, www.burnatonce.net, a freeware front-end to the open source cdrdao and cdrtools programs (which are linux-bred command line apps, and not the friendliest things in the world to work with).
It’s a bit old, and from what I could gather, it’s not being actively developed anymore, but… it’s small, simple, free, and best of all, it seems to work great for grabbing images of a disk, no matter what the format, burning from the images, and in general, doing disk dupe and backup operations.
Good stuff.
I also found an app called DeepBurner. They do have a PRO version for 25$, but the freeware version (and better, the portable freeware version), seems to do everything with ISO files I’d need to do. Great for data only cd’s. And that portable version is just copy and go. No install necessary.