views:

3101

answers:

2

To solve a problem listed here I've got to change the InstallExecuteSequence .RemoveExistingProducts record in an MSI.

I want to do this as part of the build process rather than mucking around with Orca

+8  A: 

Modifying the MSI_SetProperty.js script gives

// MSI_SetActionSequence.js <msi-file> <table> <action> <sequence>
// Performs a post-build fixup of an msi to set the specified table/action/sequence

// Constant values from Windows Installer SDK
var msiOpenDatabaseModeTransact = 1;

var msiViewModifyInsert         = 1;
var msiViewModifyUpdate         = 2;
var msiViewModifyAssign         = 3;
var msiViewModifyReplace        = 4;
var msiViewModifyDelete         = 6;

if (WScript.Arguments.Length != 4)
{
    WScript.StdErr.WriteLine("Usage: " + WScript.ScriptName + " file table action sequence");
    WScript.Quit(1);
}

var filespec = WScript.Arguments(0);
var table = WScript.Arguments(1);
var action = WScript.Arguments(2);
var sequence = parseInt(WScript.Arguments(3));

var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);

WScript.StdOut.WriteLine("Looking for action:" + action);

try
{   
    var sql = "SELECT Action, Sequence FROM " + table + " WHERE Action = '" + action + "'";
    var view = database.OpenView(sql); 

    view.Execute();  
    var record = view.Fetch(); 

    if (record)
    {  
     while (record)
     {
      WScript.StdOut.Write("Found: " + record.StringData(0) + ", " + record.StringData(1) + ", " + record.StringData(2));
      if (record.IntegerData(2) != sequence)
      {
       WScript.StdOut.WriteLine(" - changing to " + sequence);
       record.IntegerData(2) = sequence;
       view.Modify(msiViewModifyUpdate,record);
      }
      else
       WScript.StdOut.WriteLine(" - OK");

      record = view.Fetch();
     }

     view.Close();
     database.Commit();
    }
    else
    {   
     view.Close(); 
     throw("Warning - Could not find " + table + "." + action);
    }
}
catch(e)
{
    WScript.StdErr.WriteLine(e);
    WScript.Quit(1);
}

To call this script to perform the change to the action sequence mentioned above you would put the following in a batch file and call that from the post build event e.g. PostBuildEvent = $(ProjectDir)PostBuild.bat

cscript.exe MSI_SetActionSequence.js YOURINSTALLER.MSI InstallExecuteSequence RemoveExistingProducts 1525
Ryan
Thanks so much!
RBear
The MS link also mentions removing the InstallExecute line. Is this required?
RBear
Erm - what MS link? I've been using this as is for over a year, seems to work just fine.
Ryan
The one in your other post you link to at top http://social.msdn.microsoft.com/forums/en-US/winformssetup/thread/519faa07-5b4e-4546-bfb3-6f233bf7286f Seams to work though either way.
RBear
A: 

Great! Thanks.

Igor