【问题标题】:How to install VS help using WIX x86 installer on a x64 platform?如何在 x64 平台上使用 WIX x86 安装程序安装 VS 帮助?
【发布时间】:2013-06-24 15:40:41
【问题描述】:

我一直在努力使用 WIX 安装 CAB 帮助文件(从 MSHC 生成)。我尝试遵循的基本配方是这里的:Installing Help with Help Library Manager and WiX

在我的特殊情况下,我并没有真正为配方而苦苦挣扎,而是在 x64/x86 目标上苦苦挣扎。我已经阅读了来自WiX tricks and tips 的 WIX 提示,其中描述了如何制作 2 个安装程序,每个目标一个。但是,由于我更喜欢​​只有一个安装程序而不是 2 个,所以我选择只实现一个 x86 目标。

当我使用 x64 平台安装时,一切正常。当我尝试为 x86 做同样的事情时,它抱怨找不到HelpLibManager.exe。仔细观察,这似乎是合理的,因为它安装在 64 位 C:\Program Files\Microsoft Help Viewer\v1.0\HelpLibManager.exe 中,而 WIX 使用 x86 文件夹 C:\Program Files (x86)\Microsoft Help Viewer\v1.0\HelpLibManager.exe

为了解决这个问题,我尝试从包含安装 HelpLibManager 的注册表中读取正确的路径:

<Property Id="HELPLIB">
  <RegistrySearch Id="HelpLib"
                  Root="HKLM"
                  Key="Software\Microsoft\Help\v1.0"
                  Name="AppRoot"
                  Type="raw" />
</Property>

<SetProperty Id="HELPLIBMANAGER"
         Value="[HELPLIB]HelpLibManager.exe"
         After="InstallInitialize"
         Sequence="execute"/>

当您查看注册表时(当然是在Wow6432Node 内),它告诉我这个键的值是:c:\Program Files\Microsoft Help Viewer\v1.0\ - 这是正确的。但是,当我查看 MSI 的日志时,它显示为 "C:\Program Files (x86)\Microsoft Help Viewer\v1.0\HelpLibManager.exe",这是不正确的:

Property(S): HELPLIB = C:\Program Files (x86)\Microsoft Help Viewer\v1.0\

显然,Wix 更改了我从注册表中读取的字符串值。

谁能向我解释解决这个问题的正确方法是什么?

【问题讨论】:

    标签: wix windows-installer platform


    【解决方案1】:

    重定向到 (x86) 文件夹是由 Windows 安装程序自动完成的,而不是由 WiX 完成的。如果您也使用other setup authoring tools 创建包,也会发生同样的情况。

    很遗憾,32 位安装程序无法写入 x64 机器上的“Program Files”文件夹。在安装过程中,来自操作系统的 WOW 重定向控制了这一点。

    要直接在 HKLM\Software 下而不是在 HKLM\Software\Wow6432Node 下创建注册表项,您只需将其组件标记为 64 位即可。不幸的是,这对文件不起作用,即即使文件的组件被标记为 64 位,操作系统仍将重定向 Program Files (x86) 下的所有文件和文件夹。

    编辑:

    最让我惊讶的是,从注册表中读取的字符串值被更改了(查看转储的属性值)

    我知道,当我第一次发生这种情况时,我也很惊讶。

    如果你写一个small custom action C#, with a DLL as output,你仍然有机会从那个文件夹中启动一个文件,使用一个小技巧。您可以在自定义操作中获取搜索的值,对其进行解析,如果存在,手动删除“(x86)”部分。然后temporarily disable WOW redirection,启动您的文件,然后重新启用 WOW 重定向。

    不要忘记在自定义操作上设置条件,仅设置 VersionNT64 属性,并且仅在安装时运行。

    【讨论】:

    • 谢谢...但是,我不想写文件,我正在尝试启动一个可执行文件。我最惊讶的是从注册表读取的字符串值正在更改(请参阅转储的属性值) - 我什至没有尝试访问任何内容......注册表项可用于 x86和 x64 并且具有相同的值。
    • 噢,这很丑...所以这意味着我想我必须根据您关于如何解决这个问题的出色信息(这也很糟糕),在 2 个安装程序(这很糟糕)或一个非常丑陋的黑客之间做出选择...我想我会认真考虑以前的毒药并禁用 WIX 中其他平台的安装程序...我认为我第一个假设它确实“替换”是错误的并且我犯了一个错误,但是你确认它真的是那个丑陋的......该死的。谢谢。
    【解决方案2】:

    我想用一个例子来完成 Bogdan Mitrache 的回答。 为此,我使用 C# 自定义操作来访问注册表并控制 WOW 行为。

    public partial class CustomActions
        {
    
            #region marshalling RegCreateKeyEx RegOpenKeyEx RegCloseKey RegSetValueEx
            [Flags]
            public enum RegOption
            {
                NonVolatile = 0x0,
                Volatile = 0x1,
                CreateLink = 0x2,
                BackupRestore = 0x4,
                OpenLink = 0x8
            }
    
            [Flags]
            public enum RegSAM
            {
                QueryValue = 0x0001,
                SetValue = 0x0002,
                CreateSubKey = 0x0004,
                EnumerateSubKeys = 0x0008,
                Notify = 0x0010,
                CreateLink = 0x0020,
                WOW64_32Key = 0x0200,
                WOW64_64Key = 0x0100,
                WOW64_Res = 0x0300,
                Read = 0x00020019,
                Write = 0x00020006,
                Execute = 0x00020019,
                AllAccess = 0x000f003f
            }
    
            public enum RegResult
            {
                CreatedNewKey = 0x00000001,
                OpenedExistingKey = 0x00000002
            }
    
            //[StructLayout(LayoutKind.Sequential)]
            //public class SECURITY_ATTRIBUTES
            //{
            //    public int nLength;
            //    public unsafe byte* lpSecurityDescriptor;
            //    public int bInheritHandle;
            //}
            [StructLayout(LayoutKind.Sequential)]
            public class SECURITY_ATTRIBUTES
            {
                public int nLength;
                public IntPtr lpSecurityDescriptor;
                public int bInheritHandle;
            }
    
            [DllImport("advapi32.dll", SetLastError = true)]
            static extern int RegCreateKeyEx(
                        RegistryHive hKey,
                        string lpSubKey,
                        int Reserved,
                        string lpClass,
                        RegOption dwOptions,
                        RegSAM samDesired,
                        SECURITY_ATTRIBUTES lpSecurityAttributes,
                        out UIntPtr phkResult,
                        out RegResult lpdwDisposition);
    
            [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegOpenKeyEx")]
            static extern int RegOpenKeyEx(
                RegistryHive hKey,
                string subKey,
                uint options,
                RegSAM sam,
                out UIntPtr phkResult);
    
            [DllImport("advapi32.dll", SetLastError = true)]
            static extern int RegCloseKey(
                UIntPtr hKey);
    
            [DllImport("advapi32.dll", SetLastError = true)]
            static extern uint RegSetValueEx(
                 UIntPtr hKey,
                 [MarshalAs(UnmanagedType.LPStr)]
         string lpValueName,
                 int Reserved,
                 RegistryValueKind dwType,
                 [MarshalAs(UnmanagedType.LPStr)] string lpData,
                 int cbData);
    
            const int KEY_WOW64_64KEY = 0x0100;
            const int KEY_READ = 0x20019;
    
            #endregion
    
       private static uint WriteValue_String(UIntPtr hKey, string sName, string sValue)
            {
                uint setRes = RegSetValueEx(hKey, sName, 0, Microsoft.Win32.RegistryValueKind.String, sValue, sValue.Length + 1);
                return setRes;
            }
    
            /// <summary>
            /// Enable AutoLogon by changing the values of the system registry keys "DefaultUserName", "DefaultPassword" and "AutoAdminLogon" 
            /// in "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
            /// </summary>
            /// <param name="session"></param>
            /// <returns></returns>
            [CustomAction]
            public static ActionResult EnableAutoLogon(Session session)
            {
                _session = session;
                LogUtil.WriteDebugInfo(session, "Enter Function");
                try
                {
    
                    SECURITY_ATTRIBUTES secAttribs = new SECURITY_ATTRIBUTES();
    
                    UIntPtr hKey;
                    RegResult regResult;
    
                    LogUtil.WriteDebugInfo(session, "RegOpenKeyEx");
                    int result = RegOpenKeyEx(
                        RegistryHive.LocalMachine,
                        @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon",
                        0, //must be 0
                        RegSAM.WOW64_64Key | RegSAM.SetValue,
                        out hKey);
    
                    LogUtil.WriteDebugInfo(session, "WriteValue_String");
                    uint setRes = WriteValue_String(hKey, "DefaultUserName", "admin");
                    setRes = WriteValue_String(hKey, "DefaultPassword", "admin");
                    setRes = WriteValue_String(hKey, "AutoAdminLogon", "1");
    
                    LogUtil.WriteDebugInfo(session, "RegCloseKey");
                    int closeRes = RegCloseKey(hKey);           
                }
                catch (System.Exception ex)
                {
                    LogUtil.WriteDebugInfo(session, "Exception occured : " + ex.Message + "\n" + ex.StackTrace);
                    LogUtil.WriteDebugInfo(session, "Exit Function");
                    return ActionResult.Failure;
                }
                LogUtil.WriteDebugInfo(session, "Exit Function");
                return ActionResult.Success;
            }
     }
    

    KEY_WOW64_32KEY (0x0200) 表示 64 位应用程序 Windows 应该在 32 位注册表视图上运行。这个标志是 被 32 位 Windows 忽略。有关详细信息,请参阅访问 备用注册表视图。

    此标志必须使用 OR 运算符与其他标志组合 在此表中查询或访问注册表值。

    Windows 2000:不支持此标志。

    KEY_WOW64_64KEY (0x0100) 表示 64 位应用程序 Windows 应该在 64 位注册表视图上运行。这个标志是 被 32 位 Windows 忽略。有关详细信息,请参阅访问 备用注册表视图。

    此标志必须使用 OR 运算符与其他标志组合 在此表中查询或访问注册表值。

    Windows 2000:不支持此标志。

    【讨论】:

      猜你喜欢
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多