我正在创建一个 Visual Studio 安装项目,该项目为目标计算机上的现有程序安装插件。我的文件需要进入该应用程序的安装目录。我希望能够干净地安装和卸载我的插件,而不会对应用程序本身产生不必要的影响。
现有程序的安装路径可以在注册表项中找到,并且在各个安装之间可能会有所不同。
我可以将 Visual Studio 安装项目配置为从该注册表项读取值,然后将插件文件放入注册表指定的目录(或其子目录)吗?我是否需要使用自定义操作,或者可以使用标准安装项目功能来实现吗?
我注意到,在“启动条件”窗口中,我可以设置注册表搜索启动条件,该条件根据特定注册表项设置安装程序属性。我可以使用它来检索在"file"窗口中使用的 key 的实际值,还是仅出于启动条件的目的设置真/假值?
最佳答案
啊,在MSDN documentation中找到了答案毕竟。无需自定义操作即可实现!
摘要:
- 在“启动条件”窗口的“搜索目标计算机”节点下,添加注册表搜索操作。配置“RegKey”和“Value”属性以指定包含插件需要安装到的安装路径的注册表项值的名称。将注册表搜索操作的“属性”属性设置为一个合理的名称,例如“产品安装路径”
- (可选)在启动条件节点下,添加启动条件并将其 Condition 属性设置为 [ProductInstallPath]。我认为这将在安装程序运行时检查注册表项值是否存在且不为空。
- 在安装项目的“文件系统”窗口中,右键单击“目标计算机上的文件系统”,然后选择“添加特殊文件夹”、“自定义文件夹”
- 将新文件夹的“默认位置”属性设置为 [ProductInstallPath]
编辑:叹息。这在 x64 上不起作用,因为 Visual Studio 安装项目中存在错误,该错误至少自 VS2008 以来一直存在,并且在 VS2015 中仍然存在。即使安装项目平台设置为 x64,注册表搜索操作始终搜索 x86 注册表配置单元,并且看不到 x64 HKLM\SOFTWARE 键值。
详细信息:生成的 MSI 文件中的 RegLocator 表包含注册表搜索的数据。 Type 字段包含 msidbLocatorType64bit 值,该值导致搜索为 64 位 native 注册表。添加此值以纠正该问题。手动(使用 Orca)是测试功能的快速方法。 RegLocator table
我获得有效安装程序的最终解决方案是使用 WiX 创建基本安装程序,并完全放弃 Visual Studio 安装项目。
但是,在完全切换到 WiX 之前,我创建了一个小型 C# 控制台应用程序,可以将其作为构建后事件调用,以编辑 Visual Studio 安装项目生成的 MSI 文件。控制台应用程序基于部署工具基础 (DTF),它包含在 WiX Toolset 中。 。 DTF 提供用于编辑 MSI 文件的 C# API。这是它的主要内容,可能对 future 的用户有用。
using System;
using System.IO;
using Microsoft.Deployment.WindowsInstaller;
/// <summary>
/// This program patches the registry search key action in the MSI file produced by the Visual Studio Setup project,
/// to correct x64 compatibility bugs in Visual Studio Setup Projects.
/// </summary>
/// <remarks>
/// The two bugs are:
/// 1) The Visual Studio setup project incorporates the 32-bit version of InstallUtilLib.dll, which can't load x64 assemblies for reflection
/// See https://blogs.msdn.microsoft.com/heaths/2006/02/01/64-bit-managed-custom-actions-with-visual-studio/
/// 2) Registry search actions don't set the x64 bit and therefore only search the 32-bit registry
/// See https://social.msdn.microsoft.com/Forums/windows/en-US/40a2c1ee-7dd4-4289-a7d2-30b97239ae25/vs2005-setup-project-launch-conditions-registry-problem-on-x64-operating-systems
/// </remarks>
class SetupPatcher
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("ERROR: Specify the name of the MSI file as the first parameter when calling this exe");
Environment.Exit(1);
}
String msiName = args[0];
using (var db = new Database(msiName, DatabaseOpenMode.Direct))
{
PatchInstallUtilLib(db);
PatchRegLocator(db);
}
}
/// <summary>
/// Replace 32 bit InstallUtilLib.dll with x64 version
/// </summary>
/// <param name="db"></param>
private static void PatchInstallUtilLib(Database db)
{
using (View view = db.OpenView(@"UPDATE `Binary` SET `Data` = ? WHERE `Name` = 'InstallUtil'"))
{
using (Record rec = new Record(1))
{
String path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
@"Microsoft.NET\Framework64\v4.0.30319\InstallUtilLib.dll");
rec.SetStream(1, path);
view.Execute(rec);
db.Commit();
}
}
}
private static void PatchRegLocator(Database db)
{
// MSI SQL syntax documented here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372021.aspx
// Schema of RegLocator table given at https://msdn.microsoft.com/EN-US/library/aa371171.aspx
// Look for reg search actions of the Raw type in the HKLM registry root
String registryKey = @"SOFTWARE\VendorName\ProductName";
using (View view =
db.OpenView(
@"UPDATE `RegLocator` SET `Type` = ? WHERE `Type` = {0} AND `Root` = {1} AND `Key` = '{2}'",
(Int32) LocatorTypes.RawValue, (Int32) RegistryRoot.LocalMachine, registryKey))
{
using (Record rec = new Record(1))
{
rec.SetInteger(1, (Int32) (LocatorTypes.SixtyFourBit | LocatorTypes.RawValue));
view.Execute(rec);
db.Commit();
}
}
}
}
关于visual-studio-2015 - 使用 Visual Studio 安装项目将文件安装到现有程序的安装路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48273612/