Setting scriptmaps: step two and a half

To register the scriptmaps for our new web site in the Web Setup Project's MSI, we need to convert the available strings "/LM/W3SVC/1" and "WebSite1Setup" into the form "W3SVC/1/ROOT/WebSite1Setup". As simple as it sounds, we need to write a custom action to remove something from an existing string. There are a number of Custom Action Types that we could use to accomplish this:

Type Description
1 CA in a binary DLL stored in Binary table
2 CA is an exe store in Binary table
5 CA is JScript stored in the Binary table
6 CA is VBScript stored in the Binary table
17 CA in a binary DLL installed with product
18 CA is exe installed with the product
21 CA is a JScript installed with the product
22 CA is a VBScript installed with the product
37 CA is a JScript with the content in the Target field
38 CA is a VBScript with the content in the Target field
50 CA is an existing exe already on the machine
53 CA is a JScript with the content in a Property value
54 CA is a VBScript with the content in a Property value

While Custom Actions written in script are not generally recommended, the specific requirement for this case is so simplistic that it seems appropriate to use JScript instead of C++.  Script is actually better suited to manipulating strings than is C++, and this is not a case where we need to do any more than trivial error handling.  If we were instantiating a COM object or doing any more processing than called for here, we'd use C++ or C#, but in this case the right tool for the job looks like JScript.

While we have a number of ways to store the script code in the MSI, using the Binary table (type 5) was the simplest to implement with the script employed later by the PostBuildEvent to update the MSI.  Data stored in the Binary table is generally not installed on the target machine; it's for internal use by the MSI.  The same code could easily have been employed in type 37 or type 53 Custom Actions.

Here's the script used to build the parameter we need for aspnet_regiis:

Log("Entering CA_SetServerPath");

var strLM = Session.Property("TARGETSITE");
var strVDir = Session.Property("TARGETVDIR");

Log("TARGETSITE = " + strLM);
Log("TARGETVDIR = " + strVDir);

if(0 == strLM.indexOf("/LM/"))
{
 strSrvrPath =  TerminateWith(strLM.substr(4), "/");
 strSrvrPath += "ROOT/" + strVDir;
 Session.Property("SRVRPATH") = strSrvrPath;
}
else
{
 Session.Property("SRVRPATH") = TerminateWith(strLM, "/") + strVDir;
}

Log("SRVRPATH = " + strSrvrPath);
Log("Exiting CA_SetServerPath");


function Log(str)
{
 var rec = Session.Installer.CreateRecord(2);
 rec.StringData(1) = str;
 Session.Message(0x04000000, rec);
}

function TerminateWith(str, termChar)
{
 if(str.charAt(str.length-1) != termChar)
  str += termChar;
 return str;
}

We access the properties with Session.Property and employ a function to ensure that there's a trailing "/" on the TARGETSITE property.  While our sampling of the log file indicated that we need not expect this, it's highly advisable to make few assumptions and play it safe in a Custom Action.  If our TARGETSITE string doesn't match the format we expect at all, we fall back on just combining the two strings.

Note that we also log enough detail to verify our assumptions and explain our results.  If something goes wrong with our registration of scriptmaps it's likely to go wrong here, and without explicit logging we get very little information to help us troubleshoot.  With the calls included we get output which is easy to locate in the log file, and which includes information that ensures this CA worked as expected, or reveals where errors occurred.

On completion this CA creates the property SRVRPATH and sets its value.  Note that the property did not need to be declared in advance or initialized in the Properties table.  To set up this step in the installation process, we need to add the Custom Action:

Action Type Source Target
SSMCA_SetServerPath 5 SetSrvrPath  

The Binary table entry:

Name Data
SetSrvrPath [Table Data] *
* More on this later in the section describing the script

And the InstallExecuteSequence entry:

Action Condition Sequence
SSMCA_SetServerPath REGIISPATH 6475

This schedules the action after the SSMCA_CreateRegIISPath Custom Action described in part 1 and executes it only on the condition that REGIISPATH was set by that Custom Action, effectively duplicating the conditions of the earlier CA.

Now, if we're installing, and it's not an Administrative Install, and Remove is not being executed, we finally have a property containing the location of the utility application which will set the scriptmaps, and another property which contains the path to the website to be registered.  We're ready at last.

Published 12 September 06 12:17 by vank

Comments

No Comments
Anonymous comments are disabled

Search

This Blog

Syndication

Page view tracker