C# 运行时修改安装文件夹(msi)的更好方法

C# 运行时修改安装文件夹(msi)的更好方法,c#,wix,windows-installer,custom-action,wix3.9,C#,Wix,Windows Installer,Custom Action,Wix3.9,上下文: 这是一个安装旧软件的软件包。当我说老的时候,想想20岁。它是巨大的,我们依赖它,我们正在编写替换程序,但在准备好之前,我们将在未来几年内继续使用这个旧应用程序 问题: msi将通过推送,我们的IT部门坚持认为这意味着此msi包中不能有任何UI元素(如浏览安装路径)。 该程序必须安装在:卷+“:\”+companyabrevision。 默认路径为[WindowsVolume]CompanyAbVersion 我们还必须生成一些空文件夹,以便程序正常运行,如“传输” 为了实现这一点,在不

上下文:

这是一个安装旧软件的软件包。当我说老的时候,想想20岁。它是巨大的,我们依赖它,我们正在编写替换程序,但在准备好之前,我们将在未来几年内继续使用这个旧应用程序

问题:

msi将通过推送,我们的IT部门坚持认为这意味着此msi包中不能有任何UI元素(如浏览安装路径)。

该程序必须安装在:卷+“:\”+companyabrevision。 默认路径为[WindowsVolume]CompanyAbVersion

我们还必须生成一些空文件夹,以便程序正常运行,如“传输”

为了实现这一点,在不淹没在冰警告中的情况下,wix xml如下所示:

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="VOLUME_WindowsVolume_companyabbreviation" Name="WindowsVolume_companyabbreviation">
        <Directory Id="Directory_0_1_0" Name="subfolderA">
            <Directory Id="Directory_0_2_1" Name="subsubfolderAA" />
        </Directory>
        <Directory Id="Directory_0_1_0" Name="subfolderB" /> 
        <!-- and a lot more directories -->
        <Directory Id="Directory_0_2_6" Name="TRANSFER" />
    </Directory>
</Directory>

<!-- Component groups -->
    <ComponentGroup Id="FEATUREID_Directory_0_2_6" Directory="VOLUME_WindowsVolume_companyabbreviation">
        <Component Id="INSTALL_Directory_0_2_6" Guid="4a9cd25e-4d66-4398-af52-356a3b48c337">
            <CreateFolder Directory="Directory_0_2_6" />
            <RemoveFile Id="PurgeCacheFolderDirectory_0_2_6" Name="*.*" On="uninstall" />
            <RemoveFolder Id="Directory_0_2_6" On="uninstall" />
        </Component>
    </ComponentGroup>
<!-- more Component Groups, components, features, etc.. -->

<SetDirectory Id="VOLUME_WindowsVolume_companyabbreviation" Value="[WindowsVolume]companyabbreviation" />
<!-- information for the custom action -->
<Property Id="TRANSFER_ID" Value="Directory_0_2_6"/>
<!-- values below can be overwritten by the custom action:
     but unfortunately also this line also sets default paths,
     and in case of errors, it makes the directory tree above unreliable
     at least for humans that read it in the future.-->
<Property Id="Directory_0_2_6" Value="C:\companyabbrevation\TRANSFER\" />
然后是让事情发生的代码:

[CustomAction]
public static ActionResult UPDATE_FROM_REGISTRY(Session session)
{
    var view32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
    RegistryKey ProductKey = view32.OpenSubKey(@"secretPath\To\Applications\Key");

    /* instDir is the previous location of the folder */
    string instDir = ProductKey.GetValue("instDir ").ToString().Trim();
    session.Log("discovered a instDir  key: " + instDir );
    string BaseDir = instDir .Substring(0, DataDir.ToUpper().LastIndexOf("\\")).ToUpper();

    List<string> PRODUCT = new List<string>();
    ActionResult test = getCustomActionInfo(session, "companyabbreviation", ref PRODUCT );
    if (test != ActionResult.Success) return test;
    string BaseTarget = SABITC[4];
    session.Log("BaseTarget: " + BaseTarget + " == BaseDir: " + BaseDir.Replace(@"C:\", "[WindowsVolume]") + " ?? ");
   if (BaseTarget.ToUpper() == BaseDir.Replace(@"C:\", "[WindowsVolume]").ToUpper())
    {
        session.Log("\tdefault directory was used for SABITC, do nothing to change that :D ");
    }
    else
    {
        session.Log("\tinstall at old location: " + BaseDir);
        setCustomActionTarget(session, SABITC[1], BaseDir);  //here throws exception

        //TODO: update "target" and instdir in msi registry entries, to ensure information is not overwritten by defaults..
     }
}

如何使用注册表搜索来填充与目录标记关联的属性?如果找到注册表项,将填充目录属性。否则,将使用默认值。这是您已经考虑过的选项吗?看看Wix文档中的RegistrySearch元素,我还没有尝试过,你能澄清一下什么是“与目录标记关联的属性”吗。我真的希望避免在wix文件中使用任何定义路径的
标记。我觉得读取wix文件将要执行的操作会变得不必要的复杂。如果我能以某种方式找出目录的ID,那么我能在运行时添加属性吗?我的自定义操作是否总是覆盖
SetDirectory
action?directory ID=“directory\u 0\u 2\u 6”。这被视为目录id。目录\u 0\u 2\u 6可以被视为属性。将每个这样的id嵌套在注册表搜索元素下。注册表搜索元素将填充这些目录id的值,并将它们设置为在系统上找到的任何值(如果存在),并在运行时使用它们。这是一个选项吗?现在已经测试过了,这是一个选项,我发现如果我想在自定义操作中使用
setTargetPath(directory\u id,“d:\wird\path”)起作用。但是自定义操作需要在
cost finalize
使用注册表搜索填充与目录标记关联的属性如何?如果找到注册表项,将填充目录属性。否则,将使用默认值。这是您已经考虑过的选项吗?看看Wix文档中的RegistrySearch元素,我还没有尝试过,你能澄清一下什么是“与目录标记关联的属性”吗。我真的希望避免在wix文件中使用任何定义路径的
标记。我觉得读取wix文件将要执行的操作会变得不必要的复杂。如果我能以某种方式找出目录的ID,那么我能在运行时添加属性吗?我的自定义操作是否总是覆盖
SetDirectory
action?directory ID=“directory\u 0\u 2\u 6”。这被视为目录id。目录\u 0\u 2\u 6可以被视为属性。将每个这样的id嵌套在注册表搜索元素下。注册表搜索元素将填充这些目录id的值,并将它们设置为在系统上找到的任何值(如果存在),并在运行时使用它们。这是一个选项吗?现在已经测试过了,这是一个选项,我发现如果我想在自定义操作中使用
setTargetPath(directory\u id,“d:\wird\path”)起作用。但是自定义操作需要在
成本最终确定后运行
    public static void setCustomActionTarget(Session session, string ActionData, string TargetData)
    {
        session.Database.Execute("UPDATE CustomAction SET Target='" + TargetData + "' WHERE Action='" + ActionData + "'");
    }
[CustomAction]
public static ActionResult UPDATE_FROM_REGISTRY(Session session)
{
    var view32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
    RegistryKey ProductKey = view32.OpenSubKey(@"secretPath\To\Applications\Key");

    /* instDir is the previous location of the folder */
    string instDir = ProductKey.GetValue("instDir ").ToString().Trim();
    session.Log("discovered a instDir  key: " + instDir );
    string BaseDir = instDir .Substring(0, DataDir.ToUpper().LastIndexOf("\\")).ToUpper();

    List<string> PRODUCT = new List<string>();
    ActionResult test = getCustomActionInfo(session, "companyabbreviation", ref PRODUCT );
    if (test != ActionResult.Success) return test;
    string BaseTarget = SABITC[4];
    session.Log("BaseTarget: " + BaseTarget + " == BaseDir: " + BaseDir.Replace(@"C:\", "[WindowsVolume]") + " ?? ");
   if (BaseTarget.ToUpper() == BaseDir.Replace(@"C:\", "[WindowsVolume]").ToUpper())
    {
        session.Log("\tdefault directory was used for SABITC, do nothing to change that :D ");
    }
    else
    {
        session.Log("\tinstall at old location: " + BaseDir);
        setCustomActionTarget(session, SABITC[1], BaseDir);  //here throws exception

        //TODO: update "target" and instdir in msi registry entries, to ensure information is not overwritten by defaults..
     }
}
<!-- information for the custom action -->
<Property Id="TRANSFER_ID" Value="Directory_0_2_6"/>
<!-- values below can be overwritten by the custom action:
     but unfortunately also this line also sets default paths,
     and in case of errors, it makes the directory tree above unreliable
     at least for humans that read it in the future.-->
<Property Id="Directory_0_2_6" Value="C:\companyabbrevation\TRANSFER\" />
* change installation folder using information found in registry
* do not overwrite registry information for specific keys, if they are present.