Tuesday, April 6, 2010

IIS 7 with InstallShield 2009

One of the recent situations we are addressing is not having the latest InstallShield software. Doing this and relying on their functionality can create complications. One we recently encountered was a defect that occurs with IIS 7 when virtual directories are created.

If you happen to have an installer that creates a virtual directory which also contains a subfolder by the same name for the virtual directories path, it will create an additional virtual directory at the subfolder's location. This was a very odd bug which was raised by only one of our products, but it of course causes it to fail because the path is now invalid.

In our efforts to use more built in capabilities, usually for MSI tables, but on some occasions InstallShield as well, we started using the IIS view in InstallShield. Up until 2009 I used to write custom actions to handle IIS tasks. Now I am no programmer, I guess I could be called a scripter, so my custom actions were not as robust as they could be, but they were functional. The driving force to using custom actions was that InstallShield was not properly handling a dynamic site id in previous versions.

To address the defect of the second virtual directory, I decided to start using c# custom actions after years of VBScript(I know, I'm awful) use. The necessary namespace I was using was based on sample code I found that referenced System.DirectoryServices. Intially I used InstallShield's built in managed code custom actions, but I converted to using the Custom Action project type you get with WiX and then adding MSI DLL custom actions. This worked far easier as this will demonstrate because you are using the session object. My main issue was I wanted to be writing to the Windows Installer log file at run time. Here is my simple code to address the defect:

using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using Microsoft.Deployment.WindowsInstaller;

namespace AutoIISCAUtils
{
public class CustomActions
{
[CustomAction]

public static ActionResult DeleteVDir(Session session)
{
string AutoLogPrefix = "### COMPANY MESSAGE ### ";

// setup variables using properties from MSI database
string IISSiteID = session["IISSITEID"];
string AppName = session["APPNAME"];
string VDirName = session["VIRTUALDIR"];
session.Log(AutoLogPrefix + "Properties are " + IISSiteID + "|" + AppName + "|" + VDirName);

string VDirPath = @"IIS://localhost/W3SVC/" + IISSiteID + "/Root/" + AppName + "/" + VDirName;
session.Log(AutoLogPrefix + "deletion will occur on: " + VDirPath);

try
{
DirectoryEntry VDir = new DirectoryEntry(VDirPath);
if (VDir != null)
{
DirectoryEntry parent = VDir.Parent;
if (parent != null)
{
parent.Children.Remove(VDir);
parent.CommitChanges();
session.Log(AutoLogPrefix + "changes were successfully committed to the Virtual Directory " + VDir.Name + " which has now been removed.");
}
}
}
catch (Exception e)
{
session.Log(AutoLogPrefix + "exception thrown was " + e.Message);
return ActionResult.Failure;
}
return ActionResult.Success;
}
After the project is built it will generate two binaries that are dlls. The file to reference when you create the MSI DLL custom action is the .ca.dll version. Add the entry for the function name to call, change the execution and insert in the sequence. Make sure to add .Net as a prerequisite as well.

My reference for this task can be found here:

No comments:

Post a Comment