是的,这可以做到*。
首先,创建一个控制台可执行文件,它将作为 Windows 安装程序项目的构建后事件的一部分运行。这会修改Registry
已由 VS2010 构建的 MSI 文件中的表。
注意:您必须在 COM 下添加对“Microsoft Windows Installer Object Library”的引用,才能编译以下代码。
using System;
using WindowsInstaller;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Post_Setup_Scripting
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Incorrect args.");
return;
}
//arg 1 - path to MSI
string PathToMSI = args[0];
//arg 2 - path to assembly
string PathToAssembly = args[1];
Type InstallerType;
WindowsInstaller.Installer Installer;
InstallerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer = (WindowsInstaller.Installer)Activator.CreateInstance(InstallerType);
Assembly Assembly = Assembly.LoadFrom(PathToAssembly);
string AssemblyStrongName = Assembly.GetName().FullName;
string AssemblyVersion = Assembly.GetName().Version.ToString();
string SQL = "SELECT `Key`, `Name`, `Value` FROM `Registry`";
WindowsInstaller.Database Db = Installer.OpenDatabase(PathToMSI, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeDirect);
WindowsInstaller.View View = Db.OpenView(SQL);
View.Execute();
WindowsInstaller.Record Rec = View.Fetch();
while (Rec != null)
{
for (int c = 0; c <= Rec.FieldCount; c++)
{
string Column = Rec.get_StringData(c);
Column = Column.Replace("[AssemblyVersion]", AssemblyVersion);
Column = Column.Replace("[AssemblyStrongName]", AssemblyStrongName);
Rec.set_StringData(c, Column);
View.Modify(MsiViewModify.msiViewModifyReplace, Rec);
Console.Write("{0}\t", Column);
Db.Commit();
}
Console.WriteLine();
Rec = View.Fetch();
}
View.Close();
GC.Collect();
Marshal.FinalReleaseComObject(Installer);
Console.ReadLine();
}
}
}
我们将在 Windows 安装程序注册表屏幕中使用的“变量”在上述代码的这些行中被替换;这可以适应任何必要的项目。
string Column = Rec.get_StringData(c);
Column = Column.Replace("[AssemblyVersion]", AssemblyVersion);
Column = Column.Replace("[AssemblyStrongName]", AssemblyStrongName);
其次,创建一个 .reg 文件,其中包含您要在安装时创建的注册表项。在上面的代码中,我们在构建后修改 MSI 数据库,将 [AssemblyVersion] 的所有实例替换为程序集版本,并将 [AssemblyStrongName] 替换为程序集的强名称。
[HKEY_CURRENT_USER\Software\Classes\Record\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\[AssemblyVersion]]
"Class"="MyClass.MyClass"
"Assembly"="[AssemblyStrongName]"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="[TARGETDIR]MyClass.dll"
第三,将.reg文件导入到VS2010的Windows Setup注册表界面,右键“目标机器上的注册表”,点击“导入”。
最后,在安装项目的“PostBuildEvent”属性中调用构建后可执行文件:
"C:\Path\To\Exe\Post-Setup Scripting.exe" [Path to MSI] [Path To DLL to extract strong name/version]
* 这与使用 [TARGETDIR] 有点不同,因为 [TARGETDIR] 在安装时得到解析,而这些“变量”将在构建时得到解析。对于我的解决方案,我需要在构建时解决,因为我的版本号会随着每次构建而增加。