Wix创建所有用户/每台机器的非广告快捷方式

88
在WIX中,如何创建一个未广告的快捷方式在所有用户配置文件中?到目前为止,我只能使用广告快捷方式完成这个任务。我更喜欢非广告快捷方式,因为您可以进入快捷方式属性并使用“查找目标”功能。
在我看过的教程中,他们使用注册表值作为快捷方式的键路径。问题是,他们使用HKCU作为根。当使用HKCU时,并且另一个用户卸载程序(因为它是安装给所有用户的),则注册表键将留下。当我使用HKMU作为根时,我会得到ICE57错误,但是当另一个用户卸载程序时,该键会被删除。尽管HKMU似乎行为正确(按用户与按所有用户),但我似乎被推向使用HKCU。
当我尝试创建非广告快捷方式时,会出现各种ICE错误,例如ICE38、ICE43或ICE57。大多数文章都建议“只需忽略ice错误”。必须有一种方法可以创建非广告快捷方式,而不会创建ICE错误。
请发布一个工作示例的样本代码。
3个回答

116

如果自己回答自己的问题是不好的礼节,我很抱歉。

最近我发现了有关DISABLEADVTSHORTCUTS属性的信息。我创建了一个带广告快捷方式的安装程序,并将DISABLEADVTSHORTCUTS属性设置为1,从而产生非广告快捷方式。这可以绕过ICE43错误,因为广告快捷方式可以使用文件作为关键路径。因为设置了DISABLEADVTSHORTCUTS,Windows Installer将替换这些广告快捷方式为常规快捷方式。

我将Package Element的InstallScope属性设置为“perMachine”。这会将ALLUSERS属性设置为1。然后,ProgramMenuFolderDesktopFolder的值将解析为所有用户配置文件。

对于在ProgramMenuFolder下创建的文件夹,存在RemoveFolder和RegistryValue元素。我看到的示例(ex1, ex2)使用HKCU作为RegistryValue的根。我将此根更改为HKMU,它会根据ALLUSERS的值解析为HKCU或HKLM。

简而言之,当DISABLEADVTSHORTCUTS设置为1时,您的广告快捷方式不会产生ICE错误,但在安装时将被转换为非广告快捷方式。对于关键路径,根为HKMU的RegistryValue很适合非广告快捷方式。

<?xml version="1.0" encoding="utf-8"?>
<!-- This example is based on SampleFirst by Gábor DEÁK JAHN, Tramontána:
        http://www.tramontana.co.hu/wix/lesson1.php#1.3
    Original SampleFirst:
        http://www.tramontana.co.hu/wix/download.php?file=samples/samplefirst.zip&type=application/zip -->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Name="Foobar 1.0" Id="YOURGUID-21F1-4026-ABD2-7CC7F8CE4D18" UpgradeCode="YOURGUID-AFA4-46C6-94AA-EEE3D104F903" Language="1033" Codepage="1252" Version="1.0.0" Manufacturer="Acme Ltd.">
        <Package Id="*" Keywords="Installer" Description="Acme's Foobar 1.0 Installer" Comments="Foobar is a registered trademark of Acme Ltd." Manufacturer="Acme Ltd." InstallerVersion="100" Languages="1033" Compressed="yes" SummaryCodepage="1252" InstallScope="perMachine" />
        <Media Id="1" Cabinet="Sample.cab" EmbedCab="yes" DiskPrompt="CD-ROM #1" />
        <Property Id="DiskPrompt" Value="Acme's Foobar 1.0 Installation [1]" />
        <Property Id="DISABLEADVTSHORTCUTS" Value="1" />
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder" Name="PFiles">
                <Directory Id="Acme" Name="Acme">
                    <Directory Id="INSTALLDIR" Name="Foobar 1.0">
                        <Component Id="MainExecutable" Guid="YOURGUID-3E4F-47A2-86F1-F3162E9C4798">
                            <File Id="FoobarEXE" Name="FoobarAppl10.exe" DiskId="1" Source="FoobarAppl10.exe" KeyPath="yes">
                                <Shortcut Id="startmenuFoobar10" Directory="ProgramMenuDir" Name="Foobar 1.0" WorkingDirectory="INSTALLDIR" Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
                                <Shortcut Id="desktopFoobar10" Directory="DesktopFolder" Name="Foobar 1.0" WorkingDirectory="INSTALLDIR" Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
                            </File>
                        </Component>
                        <Component Id="HelperLibrary" Guid="YOURGUID-C7DA-4C02-A2F0-A6E089FC0CF3">
                            <File Id="HelperDLL" Name="Helper.dll" DiskId="1" Source="Helper.dll" KeyPath="yes" />
                        </Component>
                        <Component Id="Manual" Guid="YOURGUID-FF92-4BF4-A322-819A3B2265A0">
                            <File Id="Manual" Name="Manual.pdf" DiskId="1" Source="Manual.pdf" KeyPath="yes">
                                <Shortcut Id="startmenuManual" Directory="ProgramMenuDir" Name="Instruction Manual" Advertise="yes" />
                            </File>
                        </Component>
                    </Directory>
                </Directory>
            </Directory>
            <Directory Id="ProgramMenuFolder" Name="Programs">
                <Directory Id="ProgramMenuDir" Name="Foobar 1.0">
                    <Component Id="ProgramMenuDir" Guid="YOURGUID-D1C2-4D76-BA46-C6FA79862E77">
                        <RemoveFolder Id="ProgramMenuDir" On="uninstall" />
                        <RegistryValue Root="HKMU" Key="Software\[Manufacturer]\[ProductName]" Type="string" Value="" KeyPath="yes" />
                    </Component>
                </Directory>
            </Directory>
            <Directory Id="DesktopFolder" Name="Desktop" />
        </Directory>
        <Feature Id="Complete" Level="1">
            <ComponentRef Id="MainExecutable" />
            <ComponentRef Id="HelperLibrary" />
            <ComponentRef Id="Manual" />
            <ComponentRef Id="ProgramMenuDir" />
        </Feature>
        <Icon Id="Foobar10.exe" SourceFile="FoobarAppl10.exe" />
    </Product>
</Wix>

7
好的回答。但是假设我有一个桌面快捷方式在一个单独的组件中(因为我有条件地安装它)。如果我尝试添加Advertise =“ yes”,即使使用DISABLEADVTSHORTCUTS,也会出现错误CNDL0035,我理解这样的快捷方式无法被广告。您能否想到一种使用HKMU注册表键来创建这样的快捷方式的方法? - marcin
11
如果你已经找到了好的解决方法,回答自己的问题并不算不礼貌,我非常感谢你这样做,并且提供了一个很好的答案。加一分! - fzwo
不要将图标引用到可执行文件。图标会被复制到特殊目录(Windows\Installer{GUID}),快捷方式将使用来自该位置的图标(而不是INSTALLDIR中的可执行文件),因此最好使用单独的图标文件。 - Dmitry Azaraev
1
非常感谢。我花了几个小时来解决这个问题。对于DISABLEADVTSHORTCUTS一无所知。 - Jason Hughes
基本上是“欺骗”编译器认为它是公开的,然后通过公共属性来颠覆它。聪明。 - Drazen Bjelovuk
显示剩余4条评论

10

虽然这篇文章已经有点老了,但它包含了非常有用的信息并且看上去仍然活跃。我想指出的是,通常情况下你不需要为你的快捷方式创建一个虚拟注册表键!据我所知,这是WiX教程的东西,而不是MSI或认证要求。这里是一个没有注册表键的示例:

<Fragment Id="Folders">
  <Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="ProgramFilesFolder">
      <Directory Id="INSTALLFOLDER" Name="MyApp">
      </Directory>
    </Directory>
    <Directory Id="ProgramMenuFolder">
      <Directory Id="MyAppStartMenuDir" Name="MyApp"/>
    </Directory>
  </Directory>
</Fragment>
<Fragment Id="Components">
  <Component Id="MyAppComp" Directory="INSTALLFOLDER" ...>
    <!--The advertise flag below is to bypass ICE errors in WiX, the actual shortcut will not be advertises if those are disabled globally with DISABLEADVTSHORTCUTS-->
    <File ..." KeyPath="yes">
      <Shortcut Id="MyAppStartMenuLink" Directory="MyAppStartMenuDir" Advertise="yes" ... />
    </File>
    <RemoveFolder Id="StartMenuDirRemoved" Directory="MyAppStartMenuDir" On="uninstall" />
  </Component>
</Fragment>

请注意,这将把您的快捷方式与可执行文件放在同一个组件中。如果这让您感到困扰,请使用虚拟注册表键(如已接受的自答案中所解释得很清楚)。


1
请记得将 <Property Id="DISABLEADVTSHORTCUTS" Value="1" /> 添加到产品元素中。 - sartoris
@sartoris 这应该添加到答案中。没有它就不起作用。 - Alex Zhukovskiy

2
请查看Alex Shevchuk的博客文章《从MSI到WiX,第10部分——快捷方式》
或者是Rob Menching的博客文章《如何创建卸载快捷方式(并通过所有ICE验证)》
基本上,ICE57相当烦人......但这是我正在使用的(似乎有效的)桌面快捷方式代码 :)
<Component Id="DesktopShortcut" Directory="APPLICATIONFOLDER" Guid="*">
    <RegistryValue Id="RegShortcutDesktop" Root="HKCU" Key="SOFTWARE\My App\1.0\settings" Name="DesktopSC" Value="1" Type="integer" KeyPath="yes" />
    <Shortcut Id="desktopSc" Target="[APPLICATIONFOLDER]MyApp.exe" Directory="DesktopFolder" Name="My Applications" Icon="myapp.ico" IconIndex="0" WorkingDirectory="APPLICATIONFOLDER" Advertise="no"/>
    <RemoveFolder Id="RemoveShortcutFolder" On="uninstall" />
    <Condition>DT_SHORTCUT=1</Condition>
</Component>

10
你提供的示例使用"HKCU"作为键路径。如果一个用户安装了该应用程序,另一个用户卸载了该应用程序,注册表键将仍然存在。第一个链接中使用HKCU作为注册表键。第二个链接使用文件作为键路径,这会产生ICE43和ICE57错误。 - mcdon
1
注册表键,是的。但不包括快捷方式本身 :) - saschabeaumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接