C# Windows安装程序:动态注册表项/值
我的问题摘要: 是否可以在VS2010中的Windows安装项目的注册表屏幕中使用您自己的自定义变量(您可以使用[TARGETDIR]的方式)?具体来说,我需要在注册表中存储程序集的强名称和程序集版本,以便在计算机上注册COM对象,而安装用户没有管理员权限 我已经尝试过使用自定义操作,如果可能的话,我不想继续这样做 以下是我尝试过的细节: 最近,我的雇主开始盲目地从他们的机器上删除所有员工的管理权限 我已经创建了一个暴露于COM的C#类,我在我的一些工作站上使用了该类,该类不再能够注册,因为我不再拥有HKEY#U CLASSES#ROOT下的相应权限 通过谷歌搜索,我发现了如何在HKCU*下注册所有合适的密钥,但现在我想在我的部署项目中实现这一点 我了解如何在Windows安装程序中使用注册表屏幕,但需要存储自定义键/值(安装文件夹、程序集强名称、版本) 我可以使用自定义操作,但理想情况下,我希望Windows安装程序管理我的注册表设置,因为(a)它比我在卸载时自动删除所有正确的键/值更好,(b)在安装过程中,注册表更改是事务性的&在安装错误时回滚,以及(c)注册表项安装/删除/事务的逻辑已经由Microsoft编写,我不必自己重写 直到今天,这个项目还在VS2008中,但我刚刚将它升级到VS2010,所以2008年到2010年之间可能发生了一些变化,允许这种行为 因此,有没有更好的方法来实现这一点,而不是使用自定义操作 编辑:我找到了答案,这似乎表明您可以访问安装项目中的Windows安装“注册表”表。不过,我不知道如何访问它。在过去,我似乎记得您可以通过特殊的外部工具(Orca)访问MSI数据库,但我不知道您是否可以在安装项目中访问这些表 编辑2:啊,我可能有什么想法;可能是生成后事件:C# Windows安装程序:动态注册表项/值,c#,visual-studio-2010,setup-project,C#,Visual Studio 2010,Setup Project,我的问题摘要: 是否可以在VS2010中的Windows安装项目的注册表屏幕中使用您自己的自定义变量(您可以使用[TARGETDIR]的方式)?具体来说,我需要在注册表中存储程序集的强名称和程序集版本,以便在计算机上注册COM对象,而安装用户没有管理员权限 我已经尝试过使用自定义操作,如果可能的话,我不想继续这样做 以下是我尝试过的细节: 最近,我的雇主开始盲目地从他们的机器上删除所有员工的管理权限 我已经创建了一个暴露于COM的C#类,我在我的一些工作站上使用了该类,该类不再能够注册,因为我不
- ,
- ,
*运行RegAsm两次-一次使用/codebase,一次不使用;两次都使用/regfile选项。然后将两个文件合并在一起(删除重复文件),并用HKCU\Software\Class替换所有HKCR引用。是的,可以这样做* 首先,创建一个控制台可执行文件,该文件将作为Windows安装项目的生成后事件的一部分运行。这将修改VS2010生成的MSI文件中的
注册表
表
注意:要编译以下代码,必须在COM下添加对“Microsoft Windows Installer对象库”的引用
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();
}
}
}
其次,创建一个.reg文件,其中包含安装时要创建的注册表项。在上面的代码中,我们通过将[AssemblyVersion]的所有实例替换为程序集版本,并将[AssemblyStrongName]的所有实例替换为程序集的强名称来修改编译后的MSI数据库
[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安装注册表屏幕
最后,在安装项目的“PostBuildEvent”属性中调用生成后可执行文件:
"C:\Path\To\Exe\Post-Setup Scripting.exe" [Path to MSI] [Path To DLL to extract strong name/version]
*这与使用[TARGETDIR]略有不同,因为[TARGETDIR]在安装时得到解析,而这些“变量”将在构建时得到解析。对于我的解决方案,我需要在构建时解析,因为我的版本号随着每个构建而增加
"C:\Path\To\Exe\Post-Setup Scripting.exe" [Path to MSI] [Path To DLL to extract strong name/version]