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

November 21, 2006

Using InstallShield 12 to Install .NET Framework 3.0

Microsoft recently released .Net Framework v3.0. Regardless of the fact that the next release of Visual Studio codenamed ORCAS is not yet released ( and therefore you are very unlikely to need to deploy any WinFX applications yet), one installation vendor has made a big deal of their `exclusive` support to target the new framework. They point to this as one of the reasons that makes them the `only viable alternative` to InstallShield. Well to quote a famous proverb:

"Give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime."

InstallShield 12 comes with a series of `Setup Prerequisites`. In a nutshell, these are XML project files that describe the contents, conditions, execution and other attributes of a redistributable package that you need your setup.exe bootstrapper to install prior to running your main MSI installation package. Additionally there is a Setup Prerequisite Editor that allows developers to fully define their own prerequisites.

So let's walk through creating our own Setup Prerequisite:

Download the full redistributable from Microsoft. While it's downloading review this whitepaper that tells you everything you need to know to implement the setup prerequisite.

Open up your InstallShield project and select Tools Prerequisite editor. First do a File Save As. Next we'll start with the properties tab. Add in a description:


Next click on the conditions tab and add our conditions. Were going to tell it to install when a certain registry key is missing and the OS is XP or 2003.


Now let's add the file we downloaded from Microsoft.

Now we teach InstallShield how to install the package silently and check to see if a reboot is needed.

Finally, let's set some attributes that complete describing the installation story to InstallShield.


Next we save the prereq and add it to our Project.


Now it's time to build and deploy to a test machine that doesn't have .Net 3.0.


That's all there is to it. When you run your setup.exe the redist is installed and then your MSI package is installed. When you run setup.exe again it skips installing .Net and goes to servicing your install.

November 20, 2006

WiX Heat Website Problems

Some developers love to hate InstallShield. I've met a few who felt strongly on this topic. Let me be blunt: Frankly they didn't have a technical bone to stand on. They just seemed to fixate on a couple minor little annoyances or otherwise make a big deal out of a non-issue because of their lack of understanding of the underlying technology. One thing that was always in common was a `my grass is greener` attitude when they would reccomend some other tool or worse try to invent one themselves.

Eitherway, I try to keep my options and opinions as open as possible so occasionally I'll evaluate other tools. Recently I look at WiX to see how it's going.

Derek Cicerone once wrote in his blog:

"Heat has the capability, today, to capture IIS web sites. Simply run 'heat.exe
website "My WebSite Name" -out sourceFile.wxs' to harvest a web site and all its
files. You can then compile and link with the WixIIsExtension to create an
entire web site setup in minutes! "


Wow, such glowing optimistic comments. Ok, so let's give it a try: ( Website name changed to product the innocent )

C:\data> heat website MyWebSite -out sourceFile.wxs

Microsoft (R) Windows Installer XML Toolset Harvester version
3.0.2211.0Copyright (C) Microsoft Corporation 2006. All rights
reserved.
heat.exe : error HEAT0001 : Exception from HRESULT:
0x80005006.
Exception Type:
System.Runtime.InteropServices.COMException
Stack Trace: at
System.DirectoryServices.Interop.IAds.GetEx(String bstrName) at
System.DirectoryServices.PropertyValueCollection.PopulateList() at
System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry,
String propertyName) at
System.DirectoryServices.PropertyCollection.get_Item(String
propertyName) at
Microsoft.Tools.WindowsInstallerXml.Extensions.IIsWebSiteHarvester.HarvestWebSite(DirectoryEntry
webSiteEntry) at
Microsoft.Tools.WindowsInstallerXml.Extensions.IIsWebSiteHarvester.HarvestWebSite(String
name) at
Microsoft.Tools.WindowsInstallerXml.Extensions.IIsWebSiteHarvester.Harvest(String
argument) at
Microsoft.Tools.WindowsInstallerXml.Harvester.Harvest(String
argument) at
Microsoft.Tools.WindowsInstallerXml.Tools.Heat.Run(String[] args)

Hmmmm, ok maybe I'm passing the website name wrong. Lets's see what it does with a site that I know doesn't exist:


C:\data> heat website foo -out sourceFile.wxs

Microsoft (R) Windows Installer XML Toolset Harvester version
3.0.2211.0Copyright (C) Microsoft Corporation 2006. All rights
reserved.
heat.exe : error HEAT5158 : The web site 'foo' could not be
found. Please check that the web site exists, and that it is spelled
correctly (please note, you must use the correct case).

Ok, that's different. So obviously the first time it did find my website. So what happens if you don't pass a web site name? Let's see......

Microsoft (R) Windows Installer XML Toolset Harvester version
3.0.2211.0Copyright (C) Microsoft Corporation 2006. All rights
reserved.
heat.exe : error HEAT0001 : Value cannot be null.Parameter name:
argument
Exception Type: System.ArgumentNullException
Stack
Trace: at
Microsoft.Tools.WindowsInstallerXml.Harvester.Harvest(String
argument) at
Microsoft.Tools.WindowsInstallerXml.Tools.Heat.Run(String[] args)

Wow, that's pretty. Don't even bother trying to catch the error and give the user something useful to work with. Just throw an exception and blog chunks. And the InstallShield haters say the quality of InstallShield is bad.

November 10, 2006

InstallScript CA Performance Issue Revisited

In a previous post I wrote about the run time initialization cost associated with the new InstallScript 12 design. There was also a thread over at InstallShield Community discussing exceptional slowness ( and occasional termination )on Windows Vista. This has been resolved with a hotfix as documented in this KB article. I strongly encourage all InstallShield 12 users to download the hotfix and rebuild their setups against the newer embedded engine in order to prevent problems down the roads when your setup packages are eventually used by customers running Windows Vista. Fortunatly for InstallScript developers it's this easy. C++ developers will have to rebuilt their CA's with the /NXCOMPAT setting.

As an aside, InstallShield goes on to say the problem manifested itself when Data Execution Protection is enabled on a dual-core processor on Vista. At about the same time a new post also appeared on the Windows Installer Team Blog. It seems the root cause of this problem actually stemmed from security changes in Windows Vista.

A future KB article is summarized as:

KB Title:

Custom Action code that is not NX compliant will not run on
Windows Vista.


Summary:

Software developers should be aware that starting
with Vista, msiexec.exe is NXCOMPAT. (i.e., it is compiled with the /NXCOMPAT
switch.) This ensures that non-executable code is not run by msiexec.exe.
Msiexec.exe is the image for Windows Installer service, a Windows Installer
client and any custom action sand-box processes. What this means is that any
custom code that is not NX compliant would not be run and would result in a
forceful shutdown by the Vista NX sub-system.


More Information:

If your Windows Installer (MSI) package use libraries that are not NX compatible, then they might not work on your Vista systems. It is recommended that you recompile your setups using the new NX compatible libraries. Older versions of ATL
(pre-Visual C++ 8.0) are known to be not NX-Compatible. Using ATL shipped with
Visual C++ 8.0 is NX compliant.

November 09, 2006

Happy 231st Birthday Marines!

Man I feel old today! It seems like just yesterday at was my 217th birthday. To all you devil dogs out there ( past, present and future ), I salute you.

(1) On November 10, 1775, a Corps of Marines was created by a resolution of Continental Congress. Since that date many thousand men have borne the name "Marine". In memory of them it is fitting that we who are Marines should commemorate the birthday of our corps by calling to mind the glories of its long and illustrious history.
(2) The record of our corps is one which will bear comparison with that of the most famous military organizations in the world's history. During 90 of the 146 years of its existence the Marine Corps has been in action against the Nation's foes. From the Battle of Trenton to the Argonne, Marines have won foremost honors in war, and is the long eras of tranquility at home, generation after generation of Marines have grown gray in war in both hemispheres and in every corner of the seven seas, that our country and its citizens might enjoy peace and security.
(3) In every battle and skirmish since the birth of our corps, Marines have acquitted themselves with the greatest distinction, winning new honors on each occasion until the term "Marine" has come to signify all that is highest in military efficiency and soldierly virtue.
(4) This high name of distinction and soldierly repute we who are Marines today have received from those who preceded us in the corps. With it we have also received from them the eternal spirit which has animated our corps from generation to generation and has been the distinguishing mark of the Marines in every age. So long as that spirit continues to flourish Marines will be found equal to every emergency in the future as they have been in the past, and the men of our Nation will regard us as worthy successors to the long line of illustrious men who have served as "Soldiers of the Sea" since the founding of the Corps.

John A. Lejeune,Major General Commandant