如何在x64平台上使用WIX x86安装程序安装VS-help?
我一直在努力使用WIX安装CAB帮助文件(由MSHC生成)。我尝试遵循的基本配方如下: 在我的特殊情况下,我并不是真的在与配方抗争,而是与x64/x86目标抗争。我已经阅读了WIX提示,其中描述了如何制作2个安装程序,每个目标一个。然而,由于我更喜欢只有一个安装程序而不是两个,所以我选择只实现x86目标 当我使用x64平台安装时,一切正常。当我尝试对x86执行同样的操作时,它抱怨找不到如何在x64平台上使用WIX x86安装程序安装VS-help?,wix,windows-installer,platform,Wix,Windows Installer,Platform,我一直在努力使用WIX安装CAB帮助文件(由MSHC生成)。我尝试遵循的基本配方如下: 在我的特殊情况下,我并不是真的在与配方抗争,而是与x64/x86目标抗争。我已经阅读了WIX提示,其中描述了如何制作2个安装程序,每个目标一个。然而,由于我更喜欢只有一个安装程序而不是两个,所以我选择只实现x86目标 当我使用x64平台安装时,一切正常。当我尝试对x86执行同样的操作时,它抱怨找不到HelpLibManager.exe。仔细检查,这似乎是合理的,因为它安装在64位C:\Program File
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"/>
显然Wix改变了我从注册表读取的字符串值
有人能给我解释一下解决这个问题的正确方法吗?重定向到(x86)文件夹是由Windows Installer自动完成的,而不是由WiX完成的。如果您正在使用too创建包,也会发生同样的情况
不幸的是,32位安装程序无法写入x64机器上的“程序文件”文件夹。在安装过程中,来自操作系统的WOW重定向将控制这一点
要直接在HKLM\Software下而不是在HKLM\Software\Wow6432Node下创建注册表项,只需将其组件标记为64位即可。不幸的是,这对文件不起同样的作用,即即使文件的组件被标记为64位组件,操作系统仍将重定向程序文件(x86)下的所有文件和文件夹
编辑:
最让我吃惊的是,从注册表读取的字符串值正在被更改(请参阅转储的属性值)
我知道,当这件事第一次发生在我身上时,我也很惊讶
要从该文件夹启动文件,如果您编写了一个。您可以在自定义操作中获取搜索值,对其进行解析,如果存在,则手动删除“(x86)”部分。然后,启动文件,然后重新启用WOW重定向
别忘了在自定义操作上设置一个条件,只运行设置了的VersionNT64属性,并且只在安装时运行。我想用一个示例来完成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;
}
}
公共部分类自定义操作
{
#区域编组RegCreateKeyEx RegOpenKeyEx RegCloseKey RegSetValueEx
[旗帜]
公共枚举RegOption
{
非易失性=0x0,
Volatile=0x1,
CreateLink=0x2,
BackupRestore=0x4,
OpenLink=0x8
}
[旗帜]
公共枚举RegSAM
{
QueryValue=0x0001,
设置值=0x0002,
CreateSubKey=0x0004,
枚举子键=0x0008,
通知=0x0010,
CreateLink=0x0020,
WOW64_32Key=0x0200,
WOW64_64Key=0x0100,
WOW64_Res=0x0300,
读取=0x00020019,
写入=0x00020006,
执行=0x00020019,
AllAccess=0x000f003f
}
公共枚举结果
{
CreatedNewKey=0x00000001,
OpenedExistingKey=0x00000002
}
//[StructLayout(LayoutKind.Sequential)]
//公共类安全属性
//{
//公共国际长度;
//公共不安全字节*lpSecurityDescriptor;
//宾利山公共区;
//}
[StructLayout(LayoutKind.Sequential)]
公共类安全属性
{
公共国际长度;
公共IntPtr lpSecurityDescriptor;
宾利山公共区;
}
[DllImport(“advapi32.dll”,SetLastError=true)]
静态外部int RegCreateKeyEx(
香港国际机场,
字符串子键,
保留整数,
字符串类,
RegOption dwOptions,
雷格森,
安全属性lpSecurityAttributes,
out UIntPtr phkResult,
输出结果(LPDW配置);
[DllImport(“advapi32.dll”,CharSet=CharSet.Unicode,EntryPoint=“RegOpenKeyEx”)]
静态外部int RegOpenKeyEx(
香港国际机场,
字符串子键,
uint选项,
雷格萨姆,
out UIntPtr phkResult);
[DllImport(“advapi32.dll”,SetLastError=true)]
静态外部int RegCloseKey(
UIntPtr hKey);
[DllImport(“advapi32.dll”,SetLastError=true)]
静态外部uint RegSetValueEx(
UIntPtr hKey,
[Marshallas(UnmanagedType.LPStr)]
字符串lpValueName,
保留整数,
RegistryValueKind dwType,
[Marshallas(UnmanagedType.LPStr)]字符串lpData,
int cbData);
常量int KEY_WOW64_64KEY=0x0100;
const int KEY_READ=0x20019;
#端区
私有静态uint WriteValue_字符串(UIntPtr hKey、字符串sName、字符串sValue)
{
uint setRes=RegSetValueEx(hKey、sName、0、Microsoft.Win32.RegistryValueKind.String、SVValue、SVValue.Length+1);
返回设置;
}
///
///通过更改系统注册表项“DefaultUserName”、“DefaultPassword”和“AutoAdminLogon”的值来启用自动登录
///在“HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon”中
///
///
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;
}
}