Thursday, June 03, 2004

VBScript (and Jscript) MSI Custom Actions (don't have to) suck

One of the greatest things about blogging and its popularity (especially at Microsoft) is that you can get solid information and advice straight from the horse's mouth. In the Windows Installer world, the sole blogger at Microsoft (that I am aware of) is Rob Mensching. A recent post by him entitled VBScript (and Jscript) MSI Custom Actions suck was one that struck some discord with me.

Script custom actions do not have to "suck," contrary to what Rob points out. I prefer to use the KISS concept. There are several concepts that ANY developer, REGARDLESS of using script or C++ Custom Actions must understand.

  • Debugability - If this is a real word, it would mean the ability of an individual to debug the Custom Action. In C++, use of DebugBreak() after attaching the debugger to the process is a simple way. In script, I have not found any way of attaching a debugger to a Custom Action (if you know of a way, that would be a great feedback point). In either case, it is difficult, if not impossible, to debug a Custom Action gone bad in the field. Turning on logging, with judicious use of Session.Message is one tactic regardless of Custom Action language. As an aside, I don't understand why the MSI does not allow the author to specify some minimum level of logging.
  • Understand your Lowest Common Denominator (LCD) - If you are attempting to instantiate an ADO object on an otherwise vanilla NT4 machine, you deserve what you get - a failure. If the application you are trying to install requires something, make sure it is already installed via a LaunchCondition, or that it is going to be installed. If you depend on it in a Custom Action, make sure the install action takes place BEFORE you attempt to use it. In the C++ world, a missing dynamic link library such as MFC could get you into trouble...
  • Use the right language for the job - Lets say you ignore Rob's advice and make a script custom action to use ADO. Some ADO objects take variables by reference. VBScript supports this, JScript does not. This is no different from the debate on which language you used to code your application. You can code yourself into a corner using the "easier" languages, but on the other hand C++ can sometimes be overkill.
  • Other Considerations - With the plethora of third party software and networking techniques in use today, a developer must be fluent in new technologies. It is uncommon for a system to have no virus/worm protection. Products such as Symantec's Norton Antivirus have script blocking technologies to block against certain objects being instantiated in script that are typically used in worms and viruses. Instantiating the FileSystemObject will likely fail on systems with this type of protection. If your script is dependent on actions or objects outside the Session or Installer object, I would suggest using only C++ CA's to ensure the installation does not suffer in the future. Additionally, some firewalls prevent applications from accessing the internet (even XP SP2). If your setup uses or relies on these capabilities, be aware of the target audience and its possible setup.

Rob's assertion that a robust script Custom Action cannot be written is indefensible. I can (and surely have) written unrobust C++ Custom Actions. The beauty of software development is you can be as robust as you want to be, no matter the language. You, as the Custom Action author, are responsible for providing a meaningful error messages that can direct the user to the appropriate action to get the installation to work correctly.

To play Devil's Advocate, one point against script custom actions he didn't make include obscurity. Since MSI is easily decompileable, and the scripts can easily be viewed, edited, and replaced, it is likely there are some things you would like your competition to devote more time to reverse-engineering.

InstallShield provides its own scripting engine that can be used in Custom Actions. Although there is additional debugability and no antivirus blocking concerns, be aware that the size of the MSI increases (it has to install the scripting engine), and you are locked into InstallShield until the action is rewritten. I was able to quickly migrate almost everything from Wise for Windows Installer to InstallShield because I stuck to the MSI standards and ignored Wise's custom functionality. Better yet, I can move back if Wise leaps in front of InstallShield.


Vagmi said...

Nice Blog. There are a few more blogs for the Windows Installer world. Here are a few for starters: (Thats me)

Hope you find them interesting.

Vagmi said...

I would definitely not recommend InstallScript custom actions. They are an abomination. They leave behind the scripting engine and there is no clear way to remove them. The IDriver.exe is notorious for its problem and it should be avoided under all circumstances. Further assigning and publishing MSI packages with InstallScript custom action is a big pain. Have you ever come across the leaked MSI handle issue or the infamous ROT table errors or the random 1628 error messages. Boy! Are they a pain in the neck.