Post-Build script to fix MSI issues in Vista for VS 2005 Setup and Deployment Projects
2009-09-01 18:06
676 查看
Problem: The setup project (MSI) output generated out of the VS 2005 IDE fails to run properly on Vista. Specifically it has two glaring, known issues:
The Deferred Custom Action is NOT marked with the NO_IMPERSONATE bit which results in the custom actions being run under the Stardard User mode.
If InstallException class is used in managed code custom action from the System.Configuration.Install namespace, the package throws an ugly "The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2869" instead of the user friendly error message defined in the exception class.
Reason:
The problem with the NO_IMPERSONATE bit is that the VS 2005 IDE has very limited support for creating Vista Compatible MSIs and as such "forgets" to mark the custom actions (both, the ones created out of the CustomActionsEditor as well as the managed code Installer class custom actions) with the No_Impersonate value of 0x00000800. As a result, when these custom actions execute in Vista, they will be under the Standard User mode, and any actions which tamper with the registry of invoke external application which need admin credentials start breaking.
The InstallException problem is a combination of the new architecture of Windows Installer 4.0 which is packaged with Visa and the 'limited'-ness of VS 2005 while creating MSI. Windows Installer 4.0 expects an entry in th error table for all error codes. The InstallException class throws an error with the code 1001, but this error code is not present in the MSI's error table due to which we get the ugly error! The funny part about this entire goof is that only Windows Installer 4.0 behaves like this with the previous version showing a proper error message to the user!
Solution:
The solution to the above two problems is to include the below javascript (which I have culled out of the various sources in Internet and have made it more robust) in the Post-Build event of the VS 2005 or in the MSBUILD task.
// PostBuildVistaFix.js <msi-file>
// Performs a post-build fixup of an msi to change all deferred custom actions to NoImpersonate and adds an entry in the error table
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1
var msiViewModifyUpdate = 2
var msiViewModifyAssign = 3
var msiViewModifyReplace = 4
var msiViewModifyDelete = 6
var msidbCustomActionTypeInScript = 0x00000400;
var msidbCustomActionTypeNoImpersonate = 0x00000800;
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " filename.msi");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql
var view
var record
var errorRecordFound = false;
try
{
// first set the NO_IMPERSONATE bit for all the custom actionss
sql = "SELECT `Action`, `Type`, `Source`, `Target` FROM `CustomAction`";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
while (record)
{
if (record.IntegerData(2) & msidbCustomActionTypeInScript)
{
record.IntegerData(2) = record.IntegerData(2) | msidbCustomActionTypeNoImpersonate;
view.Modify(msiViewModifyReplace, record);
}
record = view.Fetch();
}
// close the view.
view.Close();
//check whether a row exists in the error table, if it doesn't create it
sql = "SELECT `Error`, `Message` from `Error` where `Error`=1001" ;
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
if(record)
{
errorRecordFound = true;
}
view.Close();
if( !errorRecordFound )
{
// create a new view to insert an error row in the error table so
// that an error message is displayed in vista, instead of package error!
sql = "INSERT INTO `Error` (`Error`, `Message`) VALUES (1001, '[2]')";
view = database.OpenView(sql);
view.Execute();
view.Close();
}
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
Published Wednesday, April 25, 2007 7:53 AM by nikhiln
Filed under: Vista, Setup and Deployment, VS 2005, Build, MSI
Notes:
1. Add the following code in the PostBuildEvent property of setup project
cscript.exe "$(ProjectDir)PostBuildVistaFix.js" "$(BuiltOuputPath)"
2.Copy the PostBuildVistaFix.js to the release or debug folder of setup project.
The Deferred Custom Action is NOT marked with the NO_IMPERSONATE bit which results in the custom actions being run under the Stardard User mode.
If InstallException class is used in managed code custom action from the System.Configuration.Install namespace, the package throws an ugly "The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2869" instead of the user friendly error message defined in the exception class.
Reason:
The problem with the NO_IMPERSONATE bit is that the VS 2005 IDE has very limited support for creating Vista Compatible MSIs and as such "forgets" to mark the custom actions (both, the ones created out of the CustomActionsEditor as well as the managed code Installer class custom actions) with the No_Impersonate value of 0x00000800. As a result, when these custom actions execute in Vista, they will be under the Standard User mode, and any actions which tamper with the registry of invoke external application which need admin credentials start breaking.
The InstallException problem is a combination of the new architecture of Windows Installer 4.0 which is packaged with Visa and the 'limited'-ness of VS 2005 while creating MSI. Windows Installer 4.0 expects an entry in th error table for all error codes. The InstallException class throws an error with the code 1001, but this error code is not present in the MSI's error table due to which we get the ugly error! The funny part about this entire goof is that only Windows Installer 4.0 behaves like this with the previous version showing a proper error message to the user!
Solution:
The solution to the above two problems is to include the below javascript (which I have culled out of the various sources in Internet and have made it more robust) in the Post-Build event of the VS 2005 or in the MSBUILD task.
// PostBuildVistaFix.js <msi-file>
// Performs a post-build fixup of an msi to change all deferred custom actions to NoImpersonate and adds an entry in the error table
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1
var msiViewModifyUpdate = 2
var msiViewModifyAssign = 3
var msiViewModifyReplace = 4
var msiViewModifyDelete = 6
var msidbCustomActionTypeInScript = 0x00000400;
var msidbCustomActionTypeNoImpersonate = 0x00000800;
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " filename.msi");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql
var view
var record
var errorRecordFound = false;
try
{
// first set the NO_IMPERSONATE bit for all the custom actionss
sql = "SELECT `Action`, `Type`, `Source`, `Target` FROM `CustomAction`";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
while (record)
{
if (record.IntegerData(2) & msidbCustomActionTypeInScript)
{
record.IntegerData(2) = record.IntegerData(2) | msidbCustomActionTypeNoImpersonate;
view.Modify(msiViewModifyReplace, record);
}
record = view.Fetch();
}
// close the view.
view.Close();
//check whether a row exists in the error table, if it doesn't create it
sql = "SELECT `Error`, `Message` from `Error` where `Error`=1001" ;
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
if(record)
{
errorRecordFound = true;
}
view.Close();
if( !errorRecordFound )
{
// create a new view to insert an error row in the error table so
// that an error message is displayed in vista, instead of package error!
sql = "INSERT INTO `Error` (`Error`, `Message`) VALUES (1001, '[2]')";
view = database.OpenView(sql);
view.Execute();
view.Close();
}
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
Published Wednesday, April 25, 2007 7:53 AM by nikhiln
Filed under: Vista, Setup and Deployment, VS 2005, Build, MSI
Notes:
1. Add the following code in the PostBuildEvent property of setup project
cscript.exe "$(ProjectDir)PostBuildVistaFix.js" "$(BuiltOuputPath)"
2.Copy the PostBuildVistaFix.js to the release or debug folder of setup project.
相关文章推荐
- Steps to Create Setup and Deployment Project in Dot Net VS 2008
- How to use Wise SetupCapture in the Wise Packager for Deployment Server to create an MSI
- Post Build Event for CxxTest in Visual Studio 2005
- How to build an OLE DB application for SQL Server CE in Visual Studio 2005
- Unable to find the report in the manifest resources. Please build the project, and try again.
- This file is set to build for a version older than the project deployment target. Functionality may
- How to Change the Icon for a File Type in Windows 7 and Vista(转)
- How to install VS 2005 and MSDN for VS 2005 on XP without SP2
- VS 2005 Web Application Project and VS 2005 Web Deployment Project Updates[转]
- Flash Professional CS5 will enable you to build applications for iPhone and iPod touch using ActionScript 3.
- Shell script to build fdk-aac for use in iOS apps.
- How to fix the issue that GEM_HOME and/or GEM_PATH not set issue for rvm in mac version 10.12
- Fix the issues identified by lint, or add the following to your build script...
- xib This file is set to build for a version older than the project deployment target解决方法
- The project was not built due to "Could not delete ...".Fix the problem, then try refreshing this project and building it since it may be inconsistent.
- How to build & install GLFW 3 and use it in a Linux project
- How do I fix the linker error in project upgraded from VS2010 to VS2013 where the linker is looking
- How to build Multi-Language Web Sites with ASP.NET 2.0 and VS.Net 2005
- How to setup and configure Sonar for Groovy projects
- How to build Multi-Language Web Sites with ASP.NET 2.0 and VS.Net 2005