WIX If...else 条件使用注册表 [英] WIX If...else condition using registry

查看:19
本文介绍了WIX If...else 条件使用注册表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过检查注册表值在 WIX 中使用 if...else 条件.

<RegistrySearch Id='WinVersion' Type='raw'Root='HKLM' Key='SOFTWARE\Microsoft\Windows NT\CurrentVersion' Name='ProductName'/></属性><?if [WINDOWS_VERSION] = "Windows 10 Enterprise"?><Directory Id="INSTALLDIR" Name="ETMS"><目录 ID ="BinDir" 名称 ="BIN"><目录 ID ="AssemblyDir" 名称 ="Assembly"><组件 ID ="BinAssemblyFilesFse" Guid ="$(var.BinAssemblyFilesGuid)"><!-- 此部分应包含需要部署到 Bin Assembly 文件夹的任何文件 --><?include BinAssemblyFiles.wxi?></组件><!-- 由于 WIX 中的错误,快捷方式始终指向组件中的第一个文件因此,快捷方式需要放在它们自己的组件中.--><Component Id="MainExecutable" Guid="$(var.MainExecutableGuid)"><File Id="EtmsFse.exe" Name ="EtmsFse.exe" Source ="$(var.BuiltComponents)"><!-- 将此文件的快捷方式添加到创建的 ETMS 程序菜单文件夹中.--><Shortcut Advertise="yes" Id="StartMenuEtmsFse" Directory="EtmsProgramMenuDir" Name="ETMS"WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" ><!-- 设置 AppID 以使 toasts 工作--><ShortcutProperty Key="System.AppUserModel.ID" Value="FSE"></ShortcutProperty><!-- 设置 ToastActivatorCLSID 以便在操作中心获取通知--><ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{3BD0C45A-B130-4709-BF6F-E786195E7FF9}"></ShortcutProperty></快捷方式><Shortcut Advertise="yes" Id="desktopEtmsFse" Directory="DesktopFolder" Name="ETMS"WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" ><!-- 设置 AppID 以使 toasts 工作--><ShortcutProperty Key="System.AppUserModel.ID" Value="FSE"></ShortcutProperty><!-- 设置 ToastActivatorCLSID 以便在操作中心获取通知--><ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{3BD0C45A-B130-4709-BF6F-E786195E7FF9}"></ShortcutProperty></快捷方式></文件><RemoveFolder Id="DelProgramMenuDir" On="uninstall" Directory="EtmsProgramMenuDir"/></组件></目录><?其他?><Directory Id="INSTALLDIR" Name="ETMS"><目录 ID ="BinDir" 名称 ="BIN"><目录 ID ="AssemblyDir" 名称 ="Assembly"><组件 ID ="BinAssemblyFilesFse" Guid ="$(var.BinAssemblyFilesGuid)"><!-- 此部分应包含需要部署到 Bin Assembly 文件夹的任何文件 --><?include BinAssemblyFiles.wxi?></组件><!-- 由于 WIX 中的错误,快捷方式始终指向组件中的第一个文件因此,快捷方式需要放在它们自己的组件中.--><Component Id="MainExecutable" Guid="$(var.MainExecutableGuid)"><File Id="EtmsFse.exe" Name ="EtmsFse.exe" Source ="$(var.BuiltComponents)"><!-- 将此文件的快捷方式添加到创建的 ETMS 程序菜单文件夹中.--><Shortcut Advertise="yes" Id="StartMenuEtmsFse" Directory="EtmsProgramMenuDir" Name="ETMS"WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" ></快捷方式><Shortcut Advertise="yes" Id="desktopEtmsFse" Directory="DesktopFolder" Name="ETMS"WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" ></快捷方式></文件><RemoveFolder Id="DelProgramMenuDir" On="uninstall" Directory="EtmsProgramMenuDir"/></组件></目录><?endif?>

我非常确定注册表中的值 I 是Windows 10 Enterprise",但不知何故它没有进入 if 条件.有谁知道这是怎么回事?

谢谢!

[更新]我想添加 Toast 通知,但此功能仅从 Windows 8 开始可用.这就是我尝试执行 if...else 条件以检查 Windows 版本的原因.Toast 通知需要以下行...

 <ShortcutProperty Key="System.AppUserModel.ID" Value="FSE"></ShortcutProperty><!-- 设置 ToastActivatorCLSID 以便在操作中心获取通知--><ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{3BD0C45A-B130-4709-BF6F-E786195E7FF9}"></ShortcutProperty>

解决方案

正如 Brian 指出的那样您使用的预处理器构造/指令仅在编译时影响事物.如果您想为企业组件编译单独的 MSI,这些构造非常有用 - 使用与编译其他 MSI 版本相同的 WiX 源.如果您想将所有内容整合到一个设置中,您通常会使用功能.

所以,我想答案是您需要使用企业组件的功能,然后使用您从该注册表搜索中填充的属性作为条件来确定它是否设置为安装与否.

我最近写了几个描述功能使用的答案,也许我会链接到它们:

基本上,您可以使用上面第二个链接中描述的 INSTALLLEVEL 和功能安装级别机制来为相关功能定义功能条件.然而,有时这种方法在部署过程中会失败,因为企业应用程序打包者最大化 INSTALLLEVEL 属性以防止任何功能不安装(错误的做法,但很常见).这有多严重取决于产品.在某些情况下,它可能会安装不应该安装的文件 - 例如平板电脑操作系统功能,或者在过去应该是 Unicode 的文件的 ANSI 版本 - 还有更多的例子让我无法理解.

除了列出的技术问题之外,某些功能还可能包含对于不需要它们的用户来说安装不安全的组件.例如,开发人员调试工具 - 出于安全原因,它们可能不应该对每个人都可用,还因为它们占用了大量磁盘空间和机器资源.

另一种方法是在直接检查系统后,使用自定义操作在运行时以编程方式修改特征选择.上述两种方法都在上面的链接中进行了描述.特别是在第二个链接中.

最后,如您将在上述链接之一中看到的,您可以创建一个 setup.exe 引导程序,如果用户在企业操作系统上安装,它将安装企业 MSI.

简而言之:通过使用功能将所有内容捆绑在同一设置中,并以某种方式控制安装的功能选择(功能条件、自定义操作),或者使用预处理器构造分别使用普通和企业组件编译单独的设置.然后,您可以通过 setup.exe 引导程序/启动程序以智能方式安装 MSI 文件,如果不需要,您可以跳过安装企业 MSI.

<小时>

快速模型

今晚我没有时间对此进行适当的测试,但为了让您继续前进,让我们试一试.这是我做的一个小实验,看看我们是否可以防止打包程序最大化 INSTALLLEVEL 属性的问题:

<RegistrySearch Id='WinVersion' Type='raw'Root='HKLM' Key='SOFTWARE\Microsoft\Windows NT\CurrentVersion' Name='ProductName'/></属性>

<Condition Level="1"><![CDATA[MYCHECK="Windows 10 Enterprise" OR ACTION="ADMIN"]]></Condition><!--<ComponentGroupRef Id="TestComponents"/>--></功能>

<块引用>

UPDATE:测试表明在管理安装期间根本不会提取任何设置为 Level=0 作为默认值的功能,无论设置要安装的功能的任何功能条件如何.一世猜测暂定结论是不设置任何特征Level=0,但设置 Level=1 然后将它们设置为 Level=0评估为真的特征条件.这样的功能可能是隐藏在常规安装中,但所有功能 - 与相关文件 - 在管理员安装期间提取.条件的 OR ACTION="ADMIN") 部分似乎不需要.暂时保留上面的示例.

需要指出的几点:

  • WiX 设置的默认 INSTALLLEVEL 似乎是 1.每个功能都有一个级别属性(见上文).如果功能的功能级别等于或低于 INSTALLLEVEL,则默认安装.否则默认取消选中.
  • 将功能级别设置为 0 - 就像我上面做的 - 将阻止其显示,我相信,它的安装(如果 ADDLOCAL 设置为 ALL - 技术细节,暂时不用担心).
  • 因此,将 TestFeature 级别设置为 0,应该会阻止其显示和安装,除非您的条件评估为真(我们在企业机器上).
  • 一旦条件为真,功能的级别就会设置为条件指定的级别.在这种情况下 1 - 这足以显示它并默认安装.
  • 更新:此部分并非 100% 正确.请阅读上面的彩色块引用.注意条件中的 OR.我试图解释这样一个事实,即具有级别 0 的功能显然也不会由管理安装安装.我没有时间对此进行测试 - 明天就会发生.在所有计算机上进行管理安装期间,此条件应为真,即使它们不是企业安装.

正如你所知,这里有很多东西要测试,我现在不能做.请尝试一下,并进行测试.我也不确定您获得 Windows 10 版本的方式是否正确,以及它是否适用于所有语言环境.例如,您认为该键的中文或韩文或阿拉伯文是什么?可能是一样的,但我们怎么知道?DWORD 或类似的会更可靠.

有一些特定于部署的论坛(只是我脑海中的一小部分) - 您可以在其中查看更多信息:

<小时>

链接:

I am trying to use if...else condition in WIX by checking the registry value.

<Property Id="WINDOWS_VERSION">
  <RegistrySearch Id='WinVersion' Type='raw'
    Root='HKLM' Key='SOFTWARE\Microsoft\Windows NT\CurrentVersion' Name='ProductName' />
</Property>

<?if [WINDOWS_VERSION] = "Windows 10 Enterprise"?>
        <Directory Id="INSTALLDIR" Name="ETMS">
      <Directory Id ="BinDir" Name ="BIN">
        <Directory Id ="AssemblyDir" Name ="Assembly">
          <Component Id ="BinAssemblyFilesFse" Guid ="$(var.BinAssemblyFilesGuid)">
            <!-- This section should include any files that need to be deployed to Bin Assembly folder -->
            <?include BinAssemblyFiles.wxi?>
          </Component>
          <!-- Due to a bug in WIX, the shortcut is always pointing to the first file in a component
           as a result shortcuts need to be put in their own components. -->
          <Component Id="MainExecutable" Guid="$(var.MainExecutableGuid)">
            <File Id="EtmsFse.exe" Name ="EtmsFse.exe" Source ="$(var.BuiltComponents)">
              <!-- Add shortcut for this file to the created ETMS Program Menu Folder. -->
              <Shortcut Advertise="yes" Id="StartMenuEtmsFse" Directory="EtmsProgramMenuDir" Name="ETMS"
                        WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" >
                <!-- Set the AppID in order to get toasts to work -->
                <ShortcutProperty Key="System.AppUserModel.ID" Value="FSE"></ShortcutProperty>
                <!-- Set the ToastActivatorCLSID in order to get notifications working in Action Center -->
                <ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{3BD0C45A-B130-4709-BF6F-E786195E7FF9}"></ShortcutProperty>
              </Shortcut>
              <Shortcut Advertise="yes" Id="desktopEtmsFse" Directory="DesktopFolder" Name="ETMS"
                        WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" >
                <!-- Set the AppID in order to get toasts to work -->
                <ShortcutProperty Key="System.AppUserModel.ID" Value="FSE"></ShortcutProperty>
                <!-- Set the ToastActivatorCLSID in order to get notifications working in Action Center -->
                <ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{3BD0C45A-B130-4709-BF6F-E786195E7FF9}"></ShortcutProperty>
              </Shortcut>
            </File>
            <RemoveFolder Id="DelProgramMenuDir" On="uninstall" Directory="EtmsProgramMenuDir"/>
          </Component>
        </Directory>
<?else?>
        <Directory Id="INSTALLDIR" Name="ETMS">
      <Directory Id ="BinDir" Name ="BIN">
        <Directory Id ="AssemblyDir" Name ="Assembly">
          <Component Id ="BinAssemblyFilesFse" Guid ="$(var.BinAssemblyFilesGuid)">
            <!-- This section should include any files that need to be deployed to Bin Assembly folder -->
            <?include BinAssemblyFiles.wxi?>
          </Component>
          <!-- Due to a bug in WIX, the shortcut is always pointing to the first file in a component
           as a result shortcuts need to be put in their own components. -->
          <Component Id="MainExecutable" Guid="$(var.MainExecutableGuid)">
            <File Id="EtmsFse.exe" Name ="EtmsFse.exe" Source ="$(var.BuiltComponents)">
              <!-- Add shortcut for this file to the created ETMS Program Menu Folder. -->
              <Shortcut Advertise="yes" Id="StartMenuEtmsFse" Directory="EtmsProgramMenuDir" Name="ETMS"
                        WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" >

              </Shortcut>
              <Shortcut Advertise="yes" Id="desktopEtmsFse" Directory="DesktopFolder" Name="ETMS"
                        WorkingDirectory='Bin' Icon="EtmsFse.exe" IconIndex="0" >

              </Shortcut>
            </File>
            <RemoveFolder Id="DelProgramMenuDir" On="uninstall" Directory="EtmsProgramMenuDir"/>
          </Component>
        </Directory>
<?endif?>

I am very sure that the value I from the registry is "Windows 10 Enterprise" but somehow it doesn't goes to the if condition. Does anyone know what's wrong with it?

Thanks!

[Update] I wanted to add Toast notification but this feature only available starting from Windows 8. That's why I am trying to do a if...else condition to check the Windows version. Toast notification need the line below...

 <!-- Set the AppID in order to get toasts to work -->
            <ShortcutProperty Key="System.AppUserModel.ID" Value="FSE"></ShortcutProperty>
            <!-- Set the ToastActivatorCLSID in order to get notifications working in Action Center -->
            <ShortcutProperty Key="System.AppUserModel.ToastActivatorCLSID" Value="{3BD0C45A-B130-4709-BF6F-E786195E7FF9}"></ShortcutProperty>

解决方案

As Brian has pointed out you are using a pre-processor construct / directive which only affects things at compile time. These constructs are useful if you want to compile a separate MSI for the enterprise components - using the same WiX source as you use to compile other MSI editions. If you want to put everything in one setup you normally resort to using features.

So, I guess the answer is that you need to use a feature for the enterprise components and then use the property you populate from that registry search as the condition to determine if it is set for installation or not.

I have written a couple of answers recently describing feature use, perhaps I'll just link to them:

Essentially you can use the INSTALLLEVEL and feature install level mechanism described in the second link above to just define a feature condition for the feature in question. However, sometimes this approach fails during deployment because corporate application packagers max out the INSTALLLEVEL property to prevent any features from not installing (wrong practice, but very common). How serious this is depends on the product. In some cases it may install files that should never be installed - for example Tablet OS features, or in the olden days ANSI versions of files that should be Unicode - and there were further examples that escape me.

In addition to technical issues such as those listed, some features can contain components that are unsafe to install for users who do not need them. Developer debugging tools for example - they should probably not be available for everyone for security reasons, and also because they take up a lot of disc space and machine resources.

The alternative is to use a custom action to programmatically modify the feature selection at runtime after inspecting the system directly. Both the above approaches are described in the links above. Particularly in the second link.

Finally, as you will see in one of the links above, you can create a setup.exe bootstrapper that will install an enterprise MSI if the user is installing on an enterprise OS.

So in short: bundle everything in the same setup by using features and control the feature selection for installation in some fashion (feature conditions, custom action), or compile separate setups with the normal and enterprise components respectively using pre-processor constructs. Then you can install the MSI files via a setup.exe bootstrapper / launcher in an intelligent fashion where you skip installing the enterprise MSI if it is not needed.


Quick Mock-Up

I do not have time to test this properly tonight, but in the interest of getting you going, let's give it a try. This is a little experiment I made to see if we can prevent the problem where packagers max out the INSTALLLEVEL property:

<Property Id="MYCHECK">
  <RegistrySearch Id='WinVersion' Type='raw'
    Root='HKLM' Key='SOFTWARE\Microsoft\Windows NT\CurrentVersion' Name='ProductName' />
</Property>

<Feature Id="TestFeature" Title="TestFeature" Level="0">
  <Condition Level="1"><![CDATA[MYCHECK="Windows 10 Enterprise" OR ACTION="ADMIN"]]></Condition>
  <!--<ComponentGroupRef Id="TestComponents" />-->
</Feature>

UPDATE: Testing indicates that any feature set to Level=0 as default will not be extracted during an administrative install at all, regardless of any feature conditions setting the feature to install. I guess the tentative conclusion is to not set any features to Level=0, but set Level=1 and then set them to Level=0 with a feature condition that evaluates to true. This way the feature may be hidden in a regular installation, but all features - with associated files - are extracted during admin installation. The OR ACTION="ADMIN") part of the condition appears to not be needed. Leaving the sample above as it is for now.

A few things to point out:

  • The default INSTALLLEVEL for WiX setups appears to be 1. Each feature has a level attribute (see above). If a feature's feature-level is equal or lower than the INSTALLLEVEL, it is defaulted for installation. Otherwise it is deselected by default.
  • Setting a feature level to 0 - like I do above - will prevent its display, and I believe, its installation (probably also if ADDLOCAL is set to ALL - technical detail, don't worry about it yet).
  • So setting the TestFeature level to 0, should prevent its display and installation unless your condition evaluates to true (we are on an Enterprise machine).
  • Once the condition is true, the feature's level is set to the level specified by the condition. In this case 1 - this is sufficient to show it and default it for installation.
  • UPDATE: This section is not 100% correct. Please read block quote in color above. Note the OR in the condition. I try to account for the fact that a feature with level 0 will apparently not be installed by an administrative installation either. I have not had time to test this - it will happen tomorrow. This condition should be true during administrative installations on all computers, even if they are not Enterprise installations.

As you understand there is a lot to test here, which I can not do right now. Please have a go at this, and test. I am also not sure that the way you get the Windows 10 edition is the right way, and that it will work in all locales. What do you think that key reads in Chinese or Korean or Arabic for example? It could be the same, but how do we know? A DWORD or similar would be more reliable.

There are some deployment-specific forums (just a small selection off the top of my head) - where you can check for more information:


Links:

这篇关于WIX If...else 条件使用注册表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆