2013-02-20 79 views
2

我一直在努力使用WIX安装CAB帮助文件(从MSHC生成)。我试图遵循的基本配方是:Installing Help with Help Library Manager and WiX如何安装VS帮助在x64平台上使用WIX x86安装程序?

在我的特殊情况下,我并没有真正与配方苦苦挣扎,而是使用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\ 

因此很明显维克斯改变字符串值我从注册表中读取。

任何人都可以向我解释什么是正确的方法来解决这个问题?

回答

2

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

不幸的是,32位安装程序无法写入x64机器上的“Program Files”文件夹。安装期间,来自操作系统的WOW重定向控制着这一点。

要直接在HKLM \ Software下创建注册表项,而不是在HKLM \ Software \ Wow6432Node下创建注册表项,则可以简单地将其组件标记为64位。不幸的是,这对于文件来说并不一样,即使文件的组件被标记为64位,操作系统仍然会将程序文件(x86)下的所有文件和文件夹重定向。

编辑:

我最惊讶的是,从注册表中读取字符串值被改变(见倾销的属性值)

我知道,当我第一次发生这种事时,我也感到很惊讶。

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

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

+0

谢谢...但是,我不想写一个文件,我试图启动一个可执行文件。我最惊讶的是,从注册表读取的字符串值正在改变(请参阅转储的属性值) - 我甚至没有尝试访问任何东西......该注册表项可用于x86和x64并具有相同的值。 – atlaste 2013-02-21 10:38:52

+0

看到我上面的回复,我编辑了我的答案。 – 2013-02-21 12:04:16

+0

这是丑陋的...所以这意味着我想我必须在2个安装程序(这很糟糕)或基于你如何解决这个(这也很糟糕)的优秀信息非常丑陋的黑客之间进行选择......我想我' m认真考虑以前的毒药并禁用WIX中其他平台的安装程序......我想我的第一个假设是它做了“替换”是错误的,而且我犯了一个错误,但是您确认它确实是*那*丑陋...该死的。谢谢。 – atlaste 2013-02-21 12:17:17

0

我想要完整的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(0200)表示在64位的Windows 应用程序应在32位注册表视图操作。此标志是 被32位Windows忽略。有关更多信息,请参阅访问 备用注册表视图。

此标志必须使用OR运算符与此表中其他标志 进行组合,该标志可以查询或访问注册表值。

Windows 2000:此标志不受支持。

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

此标志必须使用OR运算符与此表中其他标志 进行组合,该标志可以查询或访问注册表值。

Windows 2000:此标志不受支持。