ISWIX, LLC View Christopher Painter's profile on LinkedIn profile for Christopher Painter at Stack Overflow, Q&A for professional and enthusiast programmers

April 29, 2008

You Can't Escape .NET



There is a reason that the experts are all unanimously saying that managed custom actions are a bad idea. You are free to ignore all that accumulated expertise but it doesn't seem like a wise thing to do.

- Rich Thomson

And BTW, this topic is obviously an old beaten horse...
http://robmensching.com/blog/archive/2007/04/19/Managed-Code-CustomActions-no-support-on-the-way-and-heres.aspx

- Holmgren Mathias

The conversation of Managed Code Custom Actions once again came up on the WiX-Users list and naturally the thought police were out in full force faithfully enforcing the will of their Master, Rob Mensching. Rich's comment is my personal favorite. Has he really polled EVERY Windows Installer Expert or is he just taking the opinion of a few vocal experts who happen to work for Microsoft as settled law? I know many of the experts that I speak to are in favor of Managed Code CA's as are (currently) 72% of my readers who have voted on the topic.

This question isn't a dead horse, it's an 800lb Gorilla that will not go away, will not be ignored and will not keep quite. Managed Code is the future of Windows development and it's time MSI
recognizes that 100% declarative is a great goal but it will never succeed and that writing tomes of C++ code is not what developers expect in 2008. Thank God InstallShield feels differently.

And just so I know I'm not loosing my mind, here is the opinion of GreenAJ as expressed on the WiX-Users list:

I have head people preach diligently about the evil of managed custom actions.

Let me just say a few things. Often we need tools such as SMO to better configure a database and the "in-box" custom action in Wix don't do quite what you need. In some of the installs I have worked on, I need to migrate old databases, Restore, Detach, Attach, run very large batch scripts, hook into the batches to echo "Print" SQL statements to the MSI logs.

Also, setting up a Web Service in IIS7 is unsupported.

In comes .NET in a Custom Action to the rescue. This logic can now be coded in a more affordable way than vast tomes of C++.

What I have font to work greatly is to use a Unmanaged C++ harness to load .NET assemblies and run the custom action logic. The C++ harness uses the unmanaged .NET API for setting up the app domain and firing off the .NET code in the assembly. All the .NET code is run as a DLL custom action. NOTE: These are not the "Installer Components" that leave their carcasses in the installed product. They are simple extracted in the install, ran, and then deleted (the DLLs are loaded by the unmanaged C++ in another App Domain so they can be chucked).

-GreenAJ

April 26, 2008

Where would you go?

I've been a bit exhuasted and cranky lately as we get into the tail end of my wife's chemotherapy treatments. (Only 3 more to go!) We really need a vacation badly but we probably won't get a chance until this fall. Other then the obvious answer ( Wherever your wife wants to go! ) Where would you go spend a week to relax if you had a chance?

As an aside, I sometime look at my referral logs and some of you guys live in places I'd really love to visit.

April 24, 2008

Having a Clue Shouldn't Be Optional

I was browsing the blogosphere tonight when I came across this frustrating blog post from a frustrated blogger who fits a growing stereotype: a hubris software developer who is clueless about Setup Development and loves to blame his own shortcomings on InstallShield.

He posts twice ( here and here ).... I'm trying to be gentle tonight but here a goes dissection:

It's a .NET 2.0 Winform project, which for some god-awful reason uses InstallShield instead of the free installer that comes with Visual Studio


I guess just because VDPROJ is part of Visual Studio ( which, btw, is not free ) is must be good, right? I mean, it's obviously the better choice then InstallShield and anyone who would think otherwise must be an idiot! ( Do I need to enumerate it's weaknesses here? )
So in order to add any kind of logging or streamlining to this abomination of an application, I have to learn this language.
Hmm, he never says what project type he's using but I'm guessing it's not Windows Installer. If he was, InstallShield has a project setting to turn logging on automatically and if that's not enough information, a call to MsiProcessMessage() here and there would certainly add any additional information you could need without requiring a whole lot of coding.

Why don't I like it? Well, first there's the obvious: Nobody should have to learn a whole extra language just for their installer; it costs money when we already have a free product that works better
Oh I see, Setup Development isn't Development! You shouldn't have to actually learn anything, it just be super easy. OK fine...he's got a little bit of a clue here, that sure would be great... but it's still SETUP DEVELOPMENT. Oh but VDPROJ works better (not).

Then there's the less obvious stuff: No Framework accessibility, needing to deal with handles and memory pointers (Unsafe code; oh noes!), and no try/catch/finally block equivalent. This thing is just a big ol' turd.


I'm sorry, is this guy using the same tool that I'm using? InstallShield has THE BEST .NET framework accessibility model out there. For a couple years now you can instantiate .NET classes using CoCreateObjectDotNet() and DotNetCoCreateObject() and in InstallShield 2009 you've got the ability to declarative invoke .NET code including passing the handle and using Interop to communicate back with the Installer. This kicks the ass out of the crappy InstallUtil pattern that the .NET Framework and VDPROJ dumped on the world. Also InstallScript has had exception handling since about 1999 or so when IS 6.0 came out. (PS: Maybe he should come vote Yes for my Managed Code Custom Action Poll )

Project Newgood, which will replace Project Convergence, will use the installer built into Visual Studio. When coding a VB.NET application, does it not make sense to code your installer in VB.NET as well?

Code your Install in VB.NET? Oh my, it sounds like he's going to be using InstallUtil and VDPROJ. May the force be with him....

So by now your either laughing, nodding your head up or down or already surfed to your next web page. If you've hung in this long I promise I'm almost done.... just a few more thoughts:

1) Part of this problem is Microsoft/InstallShields fault. So little has been done to foster the professionalism and education in this space. Search for help from your local development ecosystem and you'll likely hardly find anything. No code camps, no user groups, few few few MVP's ( seriously, every software shop in the world ships product but there are around a dozen MVP's worldwide! ) You'll find precious few books on the shelves of your local bookstore; the ones that exist are ancient and/or completely get it wrong. I want to say college courses barely touch this area but I'll leave that to Colby to comment on since he's got a better perspective. There is also no certification tracks.

For the last 12 years I've been writing Installs I've seen over and over that you get very little respect. Every time I change jobs I have to once again destroy misconceptions and ignorance and show the mighty developers ( who typically want write anti patterns into the requirements if there is a requirements document ) how to do things correctly. Almost always there has never been a dedicated installation professional following industry best practices. It's always some junior CM analyst or developer who gets stuck writing the installs and is now happy to dump it like a hot potato.

2) Another part of the problem is InstallShield has a really positive yet really negative image problem. On one hand they are THE brand name trusted product and yet they are also a huge target of developers who get frustrated and then blame InstallShield instead of blaming themselves. They then flood the blogosphere with `InstallShield Sucks`. This is read by other equally clueless developers and a vicious feedback cycle is formed.

This probably wasn't a problem 10 years ago, but in today's ever connected world, the damage will penetrate more and more regardless of whether the complaints are based on reality. InstallShield can't risk keeping quite like they have in the past. Real efforts need to occur to educate and foster loyalty from the development community or otherwise I see a really bad future. Especially once Visual Studio comes out with a decent WiX authoring tool.

April 21, 2008

VSTO Lessons Learned

A few months ago I was asked to write an Install that deployed a few .NET 3.5 features:

Tray Application (required)
Office 2003 Word Add-In ( Optional )
Office 2007 Word Add-In ( Optional)

At the time I blogged I was exploring these technologies and asked if anyone had already done it. Lately several people have emailed me asking if I ever figured it out. I have figured it out and during the process I confirmed that ClickOnce/VSTO Installer/Per-User Installs are STILL a BAD IDEA!! Using this process you can streamline (merge) multiple VSTO add-ins, other system components and related setup prereqs into a single All-Users install that can be deployed using traditional techniques.

I've been meaning to write a white paper with sample code on this subject but I've been too busy. Until then, here's a quick recipe using InstallShield 2008 ( InstallShield 2009 would be a little cooler using chained feature conditioned Setup Prereqs to streamline the relationship between the prereqs and the features. )


You'll need to bring a bunch of things together:

1) Download the .NET 3.5 Prereq ( Web downloader of Full Install from InstallShield )

2) Create the VSTO 2005SE and Office 2003 PIA Prereqs ( Conditioned for installation if Office 2003 Installed and made optional)

3) Create the VSTO 3.0 Prereq ( Conditioned for installation if Office 2007 Installed and made optional)

4) Blocking SystemSearch/Launch Conditions to check .NET 3.5 is installed.

5) SystemSearch / FeatureConditions to disable Add-In features if related Office versions aren't installed.

6) `Feature Constraints` to not allow the user to select the Office-Addins if the related Office versions aren't installed.

7) A .NET Class for calling referencing the System.Security.Cryptography namespace for calling the BCL methods for installing various certificates. These will be needed to backup the add-in manifest for run time verification purposes. ( Get rid of an annoying dialog that is bad if the user says no. )

8) A .NET class for calling the System.Random class to generate a random number.

9) Office 2007 doesn't allow Add-Ins to be installed Per-Machine but it does expose a rather interesting pattern for migrating data down to the user profile without invoking an MSI repair scenario. Unfortunately this pattern requires that you create a registry key during the uninstall ( which MSI doesn't support ) so you'll need a custom action for that also.

To understand this registry migration pattern, how Office loads Add-In manifests and the roll of signing, read through the following articles.... ( make your .NET developer read it also so that he can get on the right track of knowing how to build his code and where to expect the runtime execution to occur on the file system )

Deploying your VSTO Add-In to All Users (Part I)

Deploying your VSTO Add-In to All Users (Part II)

MSDN Forums: Merge (VSTO) Setups

New Poll: Managed Code Custom Actions

I have a new poll, are you in support of Manged Code custom actions?

Note: I'm not talking about horrible Installer Class CA's here, I'm talking about CA's that can actually communicate with the MSI handle and truly support silent operation without 1001 error message pop-ups even in silent mode.

If you aren't sure or don't understand the debate, please research the topic before voting.

Blog Articles Pro Managed Code Custom Actions:

Writing managed code custom actions

A New Approach to Managed Custom Actions

More Fun with CoCreateObjectDotNet

Managed Code CAN Access the MSIHANDLE

InstallShield 2009 Beta Part II ( Managed CA's )

.NET CA's are NOT (always) Evil

Blog Articles Against Managed Code Custom Actions:

Managed Code CustomActions, no support on the way and here's why.

Don't use managed code to write your custom actions!

Custom Action Guidelines

April 19, 2008

Dealing with Bullies

In the past, I've made observations that WiX doesn't do a whole lot to help setup developers create a UI for their package. I mentioned that most `Hello World` examples show a simple Component element snippet as evidence of how `easy` WiX is. Unfortunately the resultant packages don't actually have a UI.

Professionally, I think this is unacceptable for the vast majority of situations. I've always been a fan of the patterns discussed by Leslie Easter long before MSI ever came out. The concept of interviewing the user and having a point of no return. I don't like the click, fire in the whole pattern unless the user opts in for this behavior via a /s or /qn type command.

Of course the author of WiX couldn't possibly admit that this was a weakness. While he and his cronies will judge everyone else to exacting standards, this no-UI story was just completely fine. After all, he's a self-professed command line / notepad kind of developer so why would anyone else need a UI?

Unfortunately newbie setup developer pick up his tools and follows the provided examples and assume that the resultant packages are normal best practice.

Why do I think this? Read this article where I found a trend of UI less packages authored in WiX. The trend was so powerful that I could `identify` a WiX package just by the fact that it installed without ever showing a UI.

Over time,WiX has improved (some) and does now provide a basic UI experience. Of course most WiX packages all look the same because making changes to that UI experience is less then easy since the tool doesn't have any designers. InstallShield on the other hand lets you completely extend the UI experience ( either using Basic MSI or by using InstallScript MSI with an external UI handler ) and also allows you to pick default skins/templates to make fast and radical changes to the appearance.

The other day, the author of WiX was talking about how it was obvious Google used WiX because the UI was Red instead of Blue. Now I probably read into this a bit, but based on previous comments of "I never cared much for InstallAware. Their MSI authoring tool just looked like an InstallShield clone..." I detected a certain bit of pride that WiX packages were somehow better looking because they are all red while the rest of the industries use blue. After all, he's hates InstallShield clones and all of the WiX toolset ( icons, votive, ectera ) is all branded in a red color scheme. Sure, I might have read into this too much, but I don't think I'm that far off the mark here.

Well, I think the whole red vs blue thing is silly. I decided to post a blog showing how much farther InstallShield can take the UI experience.

Well, I obviously struck a nerve with Rob because he decided to post a personal attack against me calling me a troll and claiming that all of my points have no merit. Well, I have several thoughts in response to his unprofessional, shameful hit job:

1) I'm not surprised Rob resorted to such personal attacks. After all, the fact that he would take a confidential business meeting between employees of Microsoft and InstallAware ( negative impression, sleazy and unprofessional ) and post it on his blog tells a lot.

2) My observations about the shortcomings of WiX are very valid no matter how much he attempts to dismiss them as troll posts. I've been doing installation work for 12 years and whether he believes it or not, my knowledge of this space is well vetted.

3) His characterization of me as a `troll` is completely invalid. Per his own linked definition:

An Internet troll, or simply troll in Internet slang, is someone who posts controversial and usually irrelevant or off-topic messages in an online community, such as an online discussion forum, with the intention of baiting other users into an emotional response[1] or to generally disrupt normal on-topic discussion.


This website isn't an online discussion forum. It's MY blog where I post MY observations and opinions. I also invite other setup developers whom I trust to contribute their observations and opinions and allow readers to provide their feedback via comments to help balance the perspective. But there is no attempt to disrupt normal discussion because we choose what to discuss, not the online community. Therefore, I can not be a troll ( in this context at least ).

It's up to my readers to judge my content and decide to visit again or not. Based on the feedback I get and the growing number of repeat visitors, I believe I'm doing fine.

However, if Rob finds my opinion so objectionable, he is more then welcome to not visit my blog. I will continue to visit his blog though because while I don't agree with much of his ideological rhetoric ( custom actions are (generally) an admission of failure ) I have enough knowledge and experience to pick apart what I read and adopt the pieces that I find reasonable.

Anyways, that's the last I'm going to say on this matter. I'm much more interested in blogging about pushing the boundries of MSI to support managed code custom actions rather then simply accepting that it's wrong to do so. While certain people at Microsoft don't seem willing to step up and support this, the people at InstallShield have been stepping up I'm very busy putting together some sample projects to demonstrate why this is a good thing.

April 17, 2008

Red Installs vs Blue Installs

The other day I was reading a blog where Rob Mensching was very proud that WiX installs tend to be Red instead of Blue:

"Blam! Right out of the gate I knew I was looking at a package built by WiX. How? Look at the red. All the other installation vendors out there like blue."


Well, I suppose that's better then the way I used to know that a package was built using WiX. You know..... No Dialogs At All!

Anyways, since Red is somehow better then Blue, I thought I'd mention a feature called Themes that InstallShield introduced back in IS2008. It tries to pretty up the install while still using internal UI capabilities provided by Windows Installer. Naturally, if that's not good enough, they also provide an external UI handler to extend to your hearts desire.

So first is the `Classic` Blue that everyone is so familiar with:



Here are a few of the provided alternatives in case you don't feel like making your own theme:








ComponentID GUID Sloppiness Observation

Brent Rockwood recently made a comment on the WiX-Users List:

Last night I fixed a bug in my installer where I had accidentally duplicated GUIDs on two different components. Luckily I caught this before we ship, but if I had missed it, it would obviously have been a big problem. Is there any good reason that the compiler/linker should not warn about this? It's pretty tricky to spot and Google tells me it's a pretty common error.


It seems that Brent isn't running validation as this problem would have been easily identified. Judging from what Brent reports, many people using WiX aren't running validation either. In InstallShield this usually isn't a problem because when you author a component it automatically generates the GUID for you. But WiX is writing installs in notepad/vi/intellisense and there is no automatic GUID generator so developers do what developers do:

Copy and Paste

But component rule sloppiness was raised to a all time high in my mind when I ran validation against wixedit-0.6.1762.msi. An ICE08 error popped up ( among others ) telling me that there was a component rule violation. A quick look at the Component table showed just how bad it was. About half of the ComponentId's were manually generated using a less then statistically unique algorithm:

WixBinaries.2.0.lib {DEADBEEF-DEAD-BEEF-DEAD-BEEFDEAD3010}
WixBinaries.2.0.doc {DEADBEEF-DEAD-BEEF-DEAD-BEEFDEAD3009}
WixBinaries.3.0.doc {DEADBEEF-DEAD-BEEF-DEAD-BEEFDEAD3009}
Templates.UISample {DEADBEEF-DEAD-BEEF-DEAD-BEEFDEAD0014}

Wow, I'm not sure what to say. It would be bad enough if this was some random setup developer, but this is coming from a developer who is writing their own setup developer tools and trying to convince the world that they have a better mouse trap.

I frequently get anonymous comments on my blog talking about how great WiXEdit is and that it's `Free`. Well all I can say is WiXedit may be free but this observation is Priceless!

April 14, 2008

Let The Consolidation Begin

I was just reading Google News when I noticed an article reporting that Delta and Northwest have agreed to a merger. This follows multiple airlines going defunct ( Aloha, ATA, Skybus, Skyway and soon Champion Air ) and basically a very bad week for American Airlines.

But the thing interesting to me is that a lot of other airlines are ready to get hitched.... they just didn't seem to want to be the first to walk up to the middle of the dance floor.

So let the dominos fall cause consolidation is starting. Let's see how fast my old friends at Continental get married to United.

Upcoming New Poll

I'm closing out the previous Tools Diversity Winner ( final results here ) to make room for our next poll topic:

Windows Installer and Managed Code CA's

Since I can't change a poll once it's been voted on, I'm interested in hearing how people think the question should be worded and what some of the choices should be.

April 13, 2008

Interesting WiX Build Observations

I spend a lot of time working on builds. I've done it for years for many companies and in many environments. Recently I suggested in the WiX-Users list that it would be a good thing to refactor the NAnt/CVS/SourceForge system into a clean MSBuild/TFS/CodePlex system. Naturally my opinion was ripped as always by Bob Arnson who claimed that it was too distruptive and a bad ROI.

Course the interesting thing is WiX hasn't had a weekly build in over a month now and a recent blog by Rob explains why. It seems that the Visual Studio team is providing a developer resource to do some build refactoring and that the entire code baseline is currently unstable.

Very interesting indeed...

Personally I don't understand the concept of `holding off on builds for awhile` though. I've always been tought to build early and build often. As many refactorings that I've done over the years, I don't believe I've ever brought a build down for an entire month and counting.

April 07, 2008

.NET Download Pain

Back in December, I posted an article about the incredible size of the .NET 3.5 framework. In it I complained that the framework redist package has bloated at an astounding rate.

Since that time I had a couple of responses from both ends of the spectrum. Aaron Stebner defended the size claiming (without mentioning my name):

I have seen some size comparison charts that show the .NET Framework size growing from 20 megabytes in 1.0 up to 50 megabytes in 3.0 and then 200 megabytes in 3.5. It looks like this type of size chart was based on the size of this full install package for the .NET Framework 3.5. That isn't really an accurate comparison though.


On the other hand, many agreed with me. Such was the case with Microsoft C# MSVMP Rich Strahl. He recently wrote a blog entry about the challenges of adopting the 3.5 framework.

At the time, my observations were mostly academic. We can argue back and forth over whether it's `fair` or not to talk about the framework being a 57MB package or a 197MB `union of packages` but the reality is that it still needs to be serviced in a variety of deployment models.

Recently I delivered a project to a client that had several dependencies. The application was a tray app ( .NET 3.5 ), an optional Office 2003 add-in ( VSTO2005SE - 6MB ) and an optional Office 2007 add-in ( VSTO 3.0 - 2MB ). The application is intended for web download distribution rather then physical media distribution.

With this in mind, I decided to consume the VSTO runtimes into the installer but only consume the web download version for the framework installer. According to `those in the know` this is the way it's intended to be since the download bootstrapper can pull only the pieces the target system needs.

Now that the installer has been kicked around a bit in the wild, I've only recieved one negative feedback: "It's painful to wait 20 minutes while the framework downloads. Can you do anything about it?"

If anyone reading my blog has a suggestion, I'm listening. But from where I sit, there isn't a whole lot I can do about it. I can't get the developer to drop WPF. I can't drop support for either version of Office and the customer doesn't want to use a physical media distribution model.

I guess all I can really do is hope that people will use Windows Update and that .NET 3.5 penetration will rise. Because while it's really easy for an ISV to develop vertical applications using .NET, deploying them painlessly is an entirely different story.

April 01, 2008

Rob Mensching Quits? (April Fools?)

In a short blog that makes me wonder if it's an April Fool joke, Rob Mensching has just announced that he's quit Microsoft.

He mentions that he plans on staying Active in WiX, but I can't help wonder how practical that expectation is.

Detecting Windows Server 2008 installed with Server Core option

I recently needed to modify an MSI installation to detect when the target system is running a version of Windows Server 2008 installed with the Server Core installation option. Why, you ask? Because several of the UI utilities installed with the product won't work on a system that doesn't have the Windows Explorer user interface installed so I needed to optionally disable the features associated with those utilities when running on a Server Core instance of Windows Server 2008.

To my dismay, I discovered that MSI doesn't natively expose the ProductType values returned by the GetProductInfo Function. [Hey MSI team, how about adding this in 4.5?]

Given this fact, the proper way to detect a Windows Server 2008 OS installed with the Server Core option would be to write a custom action that queries the aforementioned API and sets an MSI property when any of the *_CORE* values are returned by the pdwReturnedProductType parameter (such as PRODUCT_DATACENTER_SERVER_CORE or PRODUCT_ENTERPRISE_SERVER_CORE or PRODUCT_STANDARD_SERVER_CORE or PRODUCT_WEB_SERVER_CORE, etc.).

As Chris pointed out when I discussed this with him, if you're using a vendor tool to create your MSI installation then the tool may have an alternate method of detecting Server Core (InstallShield can do this via an InstallScript CA).

However, if you're not using a vendor tool or if creating a CA to query GetProductInfo isn't desirable in your situation, you can detect a Windows Server 2008 installed with the Server Core option by the fact that the Windows Explorer user interface isn't installed on Server Core.

To do this, add a search for "explorer.exe" located in the %windir% folder (see MSI example table records below). Then use the public property set by your search in combination with the VersionNT and MsiNTProductType MSI private properties to detect Server Core.

AppSearch Table Record:

  • OS_SUPPORTS_UI findWindowsExplorer

DrLocator Table Record:

  • findWindowsExplorer [WindowsFolder] 0

Signature Table Record:

  • findWindowsExplorer explorer.exe 5.0

Conditional Statement (true if Server Core running)

  • VersionNT=600 AND MsiNTProductType>1 AND NOT OS_SUPPORTS_UI

In fact, assuming MS doesn't depricate explorer.exe in a future version [big assumption], just remove the OS version and product type values from the condition and specify 'NOT OS_SUPPORTS_UI' for a condition that should work on both WS2K8 Server Core as well as future versions of Windows w/o UI support).