I see two different ways how shortcuts in the start menu are being created in Wix (3.8.):
1)
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="CompanyMenuFolder" Name="Company">
<Component Id="MenuFolderComponent" Guid="*">
<RegistryValue Root="HKCU" Key="Software\Company\Product"
Name="MenuFolderComponent" Type="integer"
Value="1" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
<!-- [...] -->
<Component Id='ManualComponent' Guid='*'>
<File Id='Manual' Name="Product.pdf" DiskId='1'
Source="Product.pdf" KeyPath="yes" >
<Shortcut Id="ManualStartmenuShortcut"
Directory="CompanyMenuFolder" Name="Product Manual" />
</File>
</Component>
2)
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="CompanyMenuFolder" Name="Company">
<Component Id="MenuFolderComponent" Guid="*">
<Shortcut Id="StartmenuShortcut" Directory="CompanyMenuFolder"
Name="Product" WorkingDirectory='INSTALLDIR'
Icon="Product.exe" IconIndex="0"
Target="[#ProductExecutable]" />
<RemoveFolder Id='CompanyMenuFolder' On='uninstall' />
<RegistryValue Root="HKCU" Key="Software\Company\Product"
Name="MenuFolderComponent" Type="integer" Value="1"
KeyPath="yes"/>
</Component>
</Directory>
</Directory>
Is any of these methods preferred and if so, why?
Thanks :)
A shortcut can be "advertised" - pointing to a component contained in a product, or "non-advertised" - pointing to a specific target path (Shortcut element documentation).
Option 2) is setting the target field of the non-advertised shortcut to Target="[#ProductExecutable]" - which is a property identifier that seems to point to the projects main executable in this case. It can point to a folder and an URL too as examplified here.
Option 1) also creates a non-advertised shortcut since the advertised attribute defaults to no, but here you have left out the Target field and it hence defaults to its parent component's key file.
In essence flexibility is allowed to account for the creation of different types of shortcuts and to allow for the concept of advertised and non-advertised shortcuts.
Related
My installer created with MS WiX installs a component (some files) into an existing folder in the user's App Data directory. This existing folder is empty. Thus, when uninstalling, the installer will remove this folder - which it shouldn't do.
So how to prevent this?
The code is:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder" Name="AppData">
<Directory Id="OtherCompanysFolder" Name="OtherCompany">
<Directory Id="OtherProductsFolder" Name="Product">
<Directory Id="AddOnsFolder" Name="AddOns">
<Directory Id="MyAddOnFolder" Name="MyAddOn">
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment Id="AddOnFiles">
<ComponentGroup Id="ProductComponents" Directory="MyAddOn">
<Component Id="ProductComponent" Guid="{xxx}">
<RegistryKey Root="HKCU" Key="Software\$(var.Manufacturer)\$(var.Product)">
<RegistryValue Type="string" Value="" KeyPath="yes" />
</RegistryKey>
<RemoveFolder Id="RemoveMyAddOnFolder" On="uninstall" Directory="MyAddOnFolder" />
<RemoveFolder Id="RemoveAddOnsFolder" On="uninstall" Directory="AddOnsFolder" />
<RemoveFolder Id="RemoveOtherProductsFolder" On="uninstall" Directory="OtherProductsFolder" />
<RemoveFolder Id="RemoveOtherCompanysFolder" On="uninstall" Directory="OtherCompany" />
<File Id="Executable" Source="path\to\My.exe" />
</Component>
</ComponentGroup>
</Fragment>
The problem is, if I remove the nodes
<RemoveFolder Id="RemoveAddOnsFolder" On="uninstall" Directory="AddOnsFolder" />
<RemoveFolder Id="RemoveOtherProductsFolder" On="uninstall" Directory="OtherProductsFolder" />
<RemoveFolder Id="RemoveOtherCompanysFolder" On="uninstall" Directory="OtherCompany" />
The Light and Ice will complain:
error LGHT0204 : ICE64: The directory AddOnsFolder is in the user profile but is not listed in the RemoveFile table.
Keepting these nodes makes Light and Ice happy, but it will remove AddOnsFolder (which it shouldn't do).
Any ideas what I could do?
PS: In the comment section it was recommended to suppress the error message with a flag (-sice:ICE64). This is NO solution. While the installer now compiles, the AddOn folder is still removed (which must not happen)
I have created an installer of a c# application. Now I want to add a Desktop shortcut: I have followed the WiX official documentation as well as the other suggested answers on this site but still my installer doesn't create the shortcut.
No errors occur during the compilation. My .wsx file is the following:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="APPLICATIONROOTDIRECTORY" Name="Myapp">
<Component Id="Trojan2CostCalculator.exe" Guid="*">
<File Id="Myapp.exe" Source="$(var.Myapp.TargetPath)" KeyPath="yes" Checksum="yes"/>
</Component>
<Directory Id="DesktopFolder" Name="Desktop">
<Component Id="ApplicationShortcutDesktop" Guid="*">
<Shortcut Id="ApplicationDesktopShortcut"
Name="Myapp"
Description="Made by me"
Target="$(var.Myapp.TargetPath)Myapp.exe"
WorkingDirectory="APPLICATIONROOTDIRECTORY" />
<RemoveFolder Id="DesktopFolder" On="uninstall"/>
<RegistryValue
Root="HKCU"
Key="Software\Myapp"
Name="installed"
Type="integer"
Value="1"
KeyPath="yes" />
</Component>
</Directory>
...
and I have added the component:
<Feature Id="MainApplication" Title="Main Application" Level="1">
<ComponentRef Id="ApplicationShortcutDesktop"/>
</Feature>
The installation succesfully completes but no shortcut is created. What am I missing?
I think your Shortcut's 'Target' is wrong. You're passing it the build time source path. It should be something like "[APPLICATIONROOTDIRECTORY]Myapp.exe". See - wixtoolset.org/documentation/manual/v3/xsd/wix/shortcut.html
I have a msi that has its InstallScope set to "perMachine" and it creates a shortcut which is available to all the users:
<Directory Id="ProgramMenuFolder">
<Directory Id="CompanyShortcutsDir" Name="My Company" />
</Directory>
<Component Id="CMP_MainExeShortcut"
Directory="CompanyShortcutsDir"
Guid="{B857CD9E-XXXX-YYYY-F2090C50C985}">
<Shortcut Id="MyExeStartShortcut"
Name="My Product"
Description="$(var.WIX_PRODNAME)"
Target="[APPLICATIONFOLDER]MyApp.exe"
WorkingDirectory="APPLICATIONFOLDER"
Icon="my.ico" />
<RemoveFolder Id="RemoveCompanyShortcutsDir"
On="uninstall" />
<RegistryValue Root="HKCU"
Key="Software\MyCompany"
Name="MainExeShortcut"
Type="integer"
Value="1"
KeyPath="yes" />
</Component>
and the shortcut does indeed appear for all the users - so far so good !!
But I also have this fragment of code:
<Component Id="CMP_MainExeShortcutCompat"
Directory="CompanyShortcutsDir"
Guid="{C748B7C6-XXXX-YYYY-7CB1823774DC}">
<RegistryValue Root="HKMU"
Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
Name="[APPLICATIONFOLDER]MyApp.exe"
Type="string"
Value="~ WIN7RTM"
KeyPath="yes"/>
</Component>
who's purpose is to set the "Compatibility Mode" on the shortcut to be "Windows 7" - but this only happens for the user that installed our product, it doesn't get set on the shortcut for the other users who are likely to login to the PC.
Does anyone know how I can set this flag on the shortcut for all the users ?
Many Thanks,
Chris.
I have an app that is being installed with WiX 3 - most of the install works fine by now, but trying to get the desktop shortcut to work seems to cost me my mind...
I have my app being installed and I already have a shortcut on the Start Menu folder - works just fine. But how do I get the desktop shortcut up and running?
<Product Id="*" Name="....." UpgradeCode="MY-GUID">
<Package Id="*" InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="foobar.cab" EmbedCab="yes" />
<Property Id="ALLUSERS">1</Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="FooBar"/>
</Directory>
<Directory Id="DesktopFolder" SourceName="Desktop"/>
<Directory Id="ProgramFilesFolder">
<Directory Id="FoobarDir" Name="FOOBAR">
<Directory Id="INSTALLLOCATION" Name="FooApp">
<Component Id="MainFiles" Guid=".....">
<File Id="FooMainApp" Source="FooMainApp.exe" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
....
<!-- this shortcut here works just fine ... -->
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="AppShortcut" Guid="...">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="FooBarApp" Description="..."
Target="[INSTALLLOCATION]FooMainApp.exe"
WorkingDirectory="INSTALLLOCATION"/>
</Component>
</DirectoryRef>
<!-- but this shortcut here never seems to work .. ... -->
<DirectoryRef Id="DesktopFolder">
<Component Id="DesktopShortcut" Guid="....." >
<Shortcut Id="DesktopAppShortcut"
Advertise="no"
Name="FooBarApp" Description="...."
Target="[INSTALLLOCATION]FooMainApp.exe"
WorkingDirectory="INSTALLLOCATION"/>
</Component>
</DirectoryRef>
The errors I keep getting are:
ICE18: KeyPath for Component:
'DesktopShortcut' is Directory:
'DesktopFolder'. The
Directory/Component pair must be
listed in the CreateFolders table.
ICE38: Component DesktopShortcut
installs to user profile. It must use
a registry key under HKCU as its
KeyPath, not a file.
ICE43: Component
DesktopShortcut has non-advertised
shortcuts. It should use a registry
key under HKCU as its KeyPath, not a
file.
I do not understand what on earth WiX 3 / Windows Installer is trying to tell me here.... anyone??
Both components, AppShortcut and DesktopShortcut, are in fact part of the "main" feature - I don't see any issue there. I can't figure out what on earth could be wrong here....
Update: ok, so I added some registry key stuff to my desktop shortcut
<Component Id="DesktopShortcut" Guid="BF3587B4-F52E-411E-8814-CFCBF8201C0D">
<RegistryKey Root="HKCU" Key="Software\Foo Inc\FooBarApp\Installed"
Action="createAndRemoveOnUninstall">
<RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes"/>
</RegistryKey>
<Shortcut Id="DesktopShortcut" Directory="DesktopFolder"
Name="FooBar" WorkingDirectory="INSTALLLOCATION"
Icon="foobar.ico"
Target="[INSTALLOCATION]FooMainApp.exe"/>
</Component>
now the ICE messages are gone, but when I try to install the app, I get Error 1909 - the target folder doesn't exist, or you do not have permission to write to it (or something like that)
Update 2: the above sample code provided does work on Win XP, but it keeps failing on Win Server 2003 :-( Any further ideas??
Here's a working example from our live production code...
<Fragment>
<Component Id="DesktopShortcut" Directory="APPLICATIONFOLDER" Guid="*">
<RegistryValue Id="RegShortcutDesktop" Root="HKCU"
Key="SOFTWARE\ACME\settings" Name="DesktopSC" Value="1"
Type="integer" KeyPath="yes" />
<Shortcut Id="desktopSC" Target="[APPLICATIONFOLDER]MyApp.exe"
Directory="DesktopFolder" Name="My Application"
Icon="$(var.product).ico" IconIndex="0"
WorkingDirectory="APPLICATIONFOLDER" Advertise="no"/>
</Component>
</Fragment>
This is based on #saschabeaumont's answer, but hopefully with some extra helpful hints for us WiX beginners (is it a nightmare for everybody to learn???).
First, create a fragment that contains the shortcut details itself:
<Fragment>
<Component Id="DesktopShortcut" Directory="INSTALLFOLDER" Guid="*">
<RegistryValue Id="RegShortcutDesktop"
Root="HKCU"
Key="Software\Company\ApplicationName"
Name="DesktopSC"
Value="1"
Type="integer"
KeyPath="yes" />
<Shortcut Id="desktopSC"
Target="[INSTALLFOLDER]ApplicationName.exe"
WorkingDirectory="INSTALLFOLDER"
Icon="icon.ico"
Directory="DesktopFolder"
Name="ApplicationName"
Advertise="no"/>
</Component>
</Fragment>
Next, note that this fragment will need including in the Product element, like this:
<Feature Id="ProductFeature" Title="Your Application Title" Level="1">
...
<ComponentRef Id="DesktopShortcut" />
</Feature>
The ProductFeature will likely contain other fragments, such as files, and the program menu shortcut fragment.
Also, the DesktopFolder will need a reference in the TARGETDIR directory element (which will very likely contain other folders, such as ProgramMenuFolder as you require), like this:
<Directory Id="TARGETDIR" Name="SourceDir">
...
<Directory Id="DesktopFolder" Name="Desktop"/>
</Directory>
Each of these ICE messages is basically complaining about the same thing: a component installing a shortcut should have a registry entry as its keypath. To fix this, add something like this to the component:
<RegistryValue Root="HKCU" Key="Software\MyCompany\MyApplicationName"
Name="desktopShortcut" Type="integer" Value="1" KeyPath="yes"/>
The same goes for the component installing the start menu shortcut. Take a look at the related wix documentation sample about creating a shortcut.
My purpose is to create an internet shortcut link and put to desktop. Here is the code that works for me:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="09F1B63D-FB03-43FD-A326-FD49F93D00C8" Name="TestProduct" Language="1033" Version="0.0.0.1" Manufacturer="WixEdit" UpgradeCode="6B2F9AB4-73A6-45CB-9EC4-590D1AAA6779">
<Package Description="Test file in a Product" Comments="Simple test" InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="simple.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Name="AAAA" Id="AAABBB">
<Component Id="AAAA">
<File Id="AAAA.EXE" Name="AAAA.exe" Source="U:\web\bin\x86\Release\AAAA.exe" />
</Component>
</Directory>
</Directory>
<Directory Id="DesktopFolder">
<Component Id="StartMenuShortcuts" Guid="E8EDD7BC-9762-4C3D-8341-FAEC983D318A">
<RemoveFolder Id="ProgramMenuDir" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]" Type="string" Value="" />
<util:InternetShortcut Id="WebsiteShortcut" Name="AAAA Website" Target="http://www.AAAA.com" />
</Component>
</Directory>
</Directory>
<Feature Id="DefaultFeature" Title="Main Feature" Level="1">
<ComponentRef Id="StartMenuShortcuts" />
<ComponentRef Id="AAAA" />
</Feature>
<UI />
</Product>
</Wix>
NOTE: you need to add the following to your candle and light command lines: -ext WiXUtilExtension
Not sure if this was available back in 2010, but this is how I do it in WiX 3.7:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="DesktopFolder" SourceName="Desktop" />
<Directory Id="MergeRedirectFolder">
<Component Id="MyExeComponent" Guid="{PUT-GUID-HERE}">
<File Id="MyExeFile" Source="$(var.ExeSourcePath)" KeyPath="yes">
<Shortcut
Id="DesktopShortcut"
Directory="DesktopFolder"
Name="$(var.ShortcutName)"
WorkingDirectory="MergeRedirectFolder" />
</File>
</Component>
</Directory>
</Directory>
In WIX, how do you create a non advertised shortcut in the allusers profile? So far I've only been able to accomplish this with advertised shortcuts. I prefer non-advertised shortcuts because you can go to the shortcut's properties and use "find target".
In the tutorials I've seen use a registry value for the keypath of a shortcut. The problem is they use HKCU as the root. When HKCU is used, and another user uninstalls the program (since it's installed for all users) the registry key is left behind. When I use HKMU as the root I get an ICE57 error, but the key is removed when another user uninstalls the program. I seem to be pushed towards using HKCU though HKMU seems to behave correctly (per-user vs all-users).
When I try to create the non advertised shortcut I get various ICE error such as ICE38, ICE43, or ICE 57. Most articles I've seen recommend "just ignore the ice errors". There must be a way to create the non advertised shortcuts, without creating ICE errors.
Please post sample code for a working example.
Sorry if it's bad etiquette to answer my own question.
Recently I stumbled upon the information on DISABLEADVTSHORTCUTS property. I created an install with advertised shortcuts and set the DISABLEADVTSHORTCUTS property to 1 which produced non-advertised shortcuts. This bypasses ICE43 errors because an advertised shortcut can use a file as a keypath. Because DISABLEADVTSHORTCUTS has been set Windows Installer will replace these advertised shortcuts with regular shortcuts.
I set the Package Element's InstallScope attribute to "perMachine". This sets the ALLUSERS property to 1. The values of ProgramMenuFolder and DesktopFolder will then resolve to the All Users profile.
For folders created under ProgramMenuFolder there is a RemoveFolder and RegistryValue element. The examples I've seen (ex1, ex2) use HKCU as the root for the RegistryValue. I changed this root to HKMU which resolves to HKCU or HKLM depending on the value of ALLUSERS.
In short, with DISABLEADVTSHORTCUTS set to 1 your advertised shortcuts will not produce ICE errors, but will be converted to non-advertised shortcuts when installed. A RegistryValue with root HKMU is fine for a KeyPath as long as it's not keypath for a non-advertised shortcut.
<?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>
Although this post is rather old it contains quite useful info and looks still active. I want to point out that in general you do NOT need a dummy registry key for your shortcut! AFAIK this is WiX tutorial thingy and is not MSI or certification requirement. Here is an example with no reg key:
<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>
Note that this will put your shortcut together with the executable in one component. If this bothers you then use dummy registry key (as in the very well explained accepted self answer).
Take a look at From MSI to WiX, Part 10 - Shortcuts by Alex Shevchuk.
Or Rob Menching's blog post How to create an uninstall shortcut (and pass all the ICE validation).
Basically ICE57 is rather annoying... but here's the (seems to be working) code I'm using for Desktop shortcuts :)
<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>