Wix toolset: How to remove Shortcut on install? - wix

We recently changed the name of our application from let's say test1app to test2app. So now when our customers update my application from the old version to this new one I want the shortcuts for test1app to get removed because I have already removed all the files with that name(I removed them with RemoveFile and RemoveFolder).
Is it possible to remove .lnk files with RemoveFile as well?
I have one shortcut on the desktop and one in the program files.
I have tried to remove the .lnk file with remove file but it does not get removed. I even tried to add a plain .txt file and remove it from the desktop but it does not get removed either so maybe I am calling the wrong Dictionary or something?
This is a snipped from my code:
`<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationStartMenuDirectory" Name="Test2"/>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>`
`<DirectoryRef Id="ProgramMenuFolder">
<Component Id="delete_test1_shortcuts" Guid="*">`
//Here I am trying to remove the shortcut from the Application start menu dir
`<RemoveFile Directory="ApplicationStartMenuDirectory" Id="test1.lnk_shortcut" Name="test1.lnk" On="install" />
<RegistryValue Root="HKCU" Key="Software\Company\test1" Name="installed" Type="integer" Value="1" KeyPath="yes"/>`
//Here I am trying to remove the desktop shortcut
`<RemoveFile Directory="DesktopFolder" Id="desktop_test1.lnk" Name="test1.lnk" On="install" />
</Component>`
`</DirectoryRef>`
//then reference the component
`<Feature Id="MainApplication" Title="testapp" Level="1">
<ComponentRef Id="delete_test1_shortcuts"/>
</Feature>`
The goal is that when the customers upgrade their version that the all the test1 shortcuts get removed so they only see the test2 shortcuts on install.

Please try this:
Remove the old component containing the old binary (EXE) AND the shortcut (and whatever other content is there).
Add a new component with the new binary (EXE) AND the new shortcut with the new name (important). Make sure it has a new component GUID.
This is all related to how component reference counting is done in MSI: Change my component GUID in wix?
Essentially: there is a 1:1 match between absolute installation path and the component GUID. If one changes, change the other and the older component will be uninstalled as a whole entity: all settings will be removed. There should be no overlapping resources between the components (not the same name shortcut for example).

I am not sure, why it did not work for you, I just had to do the same and the code below worked for me (some properties omitted for clarity). Wix 3.11.2
<DirectoryRef Id="ProgramMenuFolder">
<Component Id="StartMenuShortcut" Guid="{guid}">
<Shortcut Id="StartMenuShortcut"
Name="Myapp"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<!-- added the line below -->
<RemoveFile Id="RemoveOldStartMenuShortcut" On="install" Name="MyOldShortcut.lnk"/>
</Component>
</DirectoryRef>
<DirectoryRef Id="DesktopFolder">
<Component Id="DesktopShortcut" Guid="{guid}">
<Shortcut Id="DesktopShortcut"
Name="Myapp"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<!-- added the line below -->
<RemoveFile Id="RemoveOldDesktopShortcut" On="install" Name="MyOldShortcut.lnk"/>
</Component>
</DirectoryRef>

Related

WIX :Adding a shortcut to StartMenu folder Windows 10

I have an application that will install a shortcut to Start Menu folder. It is working perfectly in Win7. But shortcut is not coming when I install the application in Windows 10 machine. The shortcut entry in my WIX file is given below.
<Component Id="cmptest" Guid="*" KeyPath="yes">
<Shortcut Id="test.exe2" Directory="StartMenuFolder"
Name="test" Target="[#test.exe]" Hotkey="0" IconIndex="0" Show="normal" />
</Component>
Before getting into too much detail:
Are you sure the shortcut really isn't there? The Windows 10 start menu is so strange that I find I have to look twice very often to find shortcuts that are actually there. Just checking.
For that matter, are you sure the install actually completes in Windows 10? Perhaps it rolls back and you didn't notice?
The Directory StartMenuFolder does not compile for my test project, until I add it as a directory under TARGETDIR myself:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="StartMenuFolder" />
</Directory>
I assume you already have this folder added there to make your setup compile. You could also try ProgramMenuFolder for testing and see if the shortcut shows up.
Where is the rest of your WiX source? I can't see if you actually install the file you reference: #test.exe? Does the component that hosts that file actually get installed on Windows 10?
And for some extra strangeness: I haven't seen this much, but since the problem manifests itself on Windows 10, maybe have a read of this answer and see if it rings any bells: Wix Uninstall Shortcut not working
Essentially some shortcuts are hidden auto-magically in Windows 8 and probably upwards. I don't see any reason why your shortcut should be hidden though.
I have been able to get the shortcuts for to show up using the ProgramMenuFolder suggested by Stein Asmul for testing. Below is my setup which is working, with the exception being that my icons not showing up.
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Barcode Printer App" />
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="BarcodePrinterAppShortcuts" Name="Barcode Printer App" />
</Directory>
</Directory>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent">
<File Id="BarcodeAppExe" Source="$(var.BarcodePrinterHelperApp.TargetPath)" >
<Shortcut Id="BarcodeAppShortcut"
Directory="BarcodePrinterAppShortcuts"
Name="Barcode Printer App"
WorkingDirectory="INSTALLFOLDER"
Advertise="yes"
Icon="icon.ico"
IconIndex="0"
>
</Shortcut>
</File>
<RemoveFolder Id="DeleteTheBarcodeAppShortcut"
Directory="BarcodePrinterAppShortcuts"
On="uninstall" />
</Component>
</ComponentGroup>
<Component Id="UninstallShortcut" Guid="*" Directory="BarcodePrinterAppShortcuts">
<Shortcut Id="UninstallThisProduct"
Name="Uninstall Barcode Printer App"
Description="Uninstalls Barcode Printer App"
Target="[System64Folder]msiexec.exe"
Arguments="/x [ProductCode]" />
<RegistryValue Root="HKCU" Key="Software\Powerserve\BarcodePrinterApp" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
It could be permission issue. Try to run your installation As Administrator (or, open Command Prompt as Administrator) and run your installation from there. Also, you may want to check User Account Control settings and lower the slider if it's too restrictive.

WiX Ice64 error for shortcut parent directory

I am trying to create a start menu shortcut for an application using WiX, the problem is that I am receiving an Ice64 error stating that the parent directory of the shortcut directory is not in the RemoveFile table.
I do not want to remove this parent folder (organisation folder) on uninstall as other applications may have shortcuts in other children of it.
My code looks like
<Feature Id="ProductFeature" Title="MyApplication" Level="1">
<ComponentGroupRef Id="Components" />
<ComponentRef Id="ProfilesShortcut"/>
</Feature>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="OrgDir" Name="OrganisationName">
<Directory Id="AppDir" Name="MyApplication" />
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ProgFilesOrgDir" Name="OrganisationName">
<Directory Id="ProgFilesAppDir" Name="MyApplication" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="ProgFilesAppDir">
<Component Id="ProfilesShortcut" Guid="*">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="MyApplication"
Description="My Application"
Target="[#MyApplication.exe]"
WorkingDirectory="AppDir"/>
<RemoveFolder Id="ProgFilesAppDir" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Organisation\MyApplication" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
</Fragment>
Feel free to add the remove file element to your shortcut component.
Remove an empty folder if the parent component is selected for installation or removal.
The RemoveFolder element will only remove empty folders so if your product is not the only part of that suite installed it will leave the parent folder alone since other products will have put files/folders there. Consider the scenario where your product is either the only one installed (should remove the folder) or is the last one to be uninstalled from the suite (should remove the folder). In these two cases the folder should get removed. The order of RemoveFolder elements get defined might matter so I would test putting the ProgramFilesOrgFolder remove element before and after ProgFilesAppDir remove element just to see if one of them fails.
Alternatively you can just suppress ICE64 but then you will leave a folder behind once all the products are uninstalled. Not a huge deal really but might be annoying to some users.

Can I use auto-generated GUIDS with a merge module?

I use auto-guids in my <Product> but can't figure out how to use them with <Module>. I only get this error:
The component X has a key file with path 'TARGETDIR\company...'.
Since this path is not rooted in one of the standard directories (like
ProgramFiles Folder), the component does not meet the criteria for
having an automatically generated guid.
Above, company is the value mapped to !(loc.ProductManufacturerFolderName).
The only problem is that's not true. My directories are rooted in ProgramFiles just like my product is and my product works fine:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="MODULEINSTALLLOCATION" Name="!(loc.ProductManufacturerFolderName)">
<Directory Id="Data" Name="Data">
All my component declarations look roughly like this:
<Component Id="DocumentationParty_Business_TestCases_v1xlsx.component" Guid="{YOURGUID-1234-1234-84B3-C595A63428AD}" MultiInstance="yes">
<File Source="../../Development/Integration/SSIS/Documentation/Party_Business_Test Cases_v1.xlsx" KeyPath="yes" Id="DocumentationParty_Business_TestCases_v1xlsx.file" />
</Component>
Breaking it is easy, you only have to change the GUID to * and the above error results. This is broken:
<Component Id="DocumentationParty_Business_TestCases_v1xlsx.component" Guid="*" MultiInstance="yes">
<File Source="../../Development/ClaimsIntegration/SSIS/Documentation/Party_Business_Test Cases_v1.xlsx" KeyPath="yes" Id="DocumentationParty_Business_TestCases_v1xlsx.file" />
</Component>
I have a .wxs file for each directory to which components will be installed. All my component-holding .wxs files have the following structure:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<ComponentGroup Id="DatabasePolicy_Files">
<ComponentRef Id="DatabasePolicyCreateDatabasecmdtemplate.component" />
</ComponentGroup>
<DirectoryRef Id="DataPolicy">
<Component Id="DatabasePolicyCreateDatabasecmdtemplate.component" Guid="*" MultiInstance="yes">
<File Source="../../Development/Database/Policy/CreateDatabase.cmd.template" KeyPath="yes" Id="DatabasePolicyCreateDatabasecmdtemplate.file" />
</Component>
</DirectoryRef>
</Fragment>
</Wix>
Each <ComponentGroup> is included in my master .wxs file through a <ComponentGroupRef>. This works in all my MSI projects and breaks only now that I've started working with merge modules. Also, I've tried commenting out all components except for which matches the above definition and it still breaks on the same error.
What is the problem?
I've had this similar issue myself and based on your error message it's probably the same.
Try adding a ComponentGuidGenerationSeed, that should solve your issue. The ComponentGuidGenerationSeed acts on all subfolders as well so a single one at the top-level is sufficient for all folders.
Example:
<Directory Id="DOCUMENTATIONFOLDER" Name="Documentation" ComponentGuidGenerationSeed="a9f690d3-22b3-488f-bdac-bb665c25933c"/>
http://wixtoolset.org/documentation/manual/v3/xsd/wix/directory.html
The Component Guid Generation Seed is a guid that must be used when a
Component with the generate guid directive ("*") is not rooted in a
standard Windows Installer directory (for example, ProgramFilesFolder
or CommonFilesFolder).

After install different versions of my application side-by-side, uninstall one version doesn't remove shortcut from program menu.

I created an installer using WIX. As part of the installation, two shortcuts (launch and uninstall) are added to "ProgramMenu->MyCompany->MyProductName".
After I install two versions of the same application side by side. I tried to use the uninstall shortcut to uninstall one version.
The uninstall removes all the files and folders for the version. But failed to remove the shortcuts. And when I click on uninstall again. The following error shows:
"This action is only valid for products that are currently installed"
Then I run the uninstall for the other version, this time both shortcuts for THAT version are removed successfully. But leave the shortcuts for the failed version stuck in "ProgramMenu->MyCompany->MyProductName" forever. I had to manually delete them.
Here is the code I use to create the shortcuts. Anything I did wrong?
<Directory Id="ProgramMenuFolder">
<Directory Id="MyCompanyShortcutDir" Name="MyCompany">
<Directory Id="MyProductShortcutDir" Name="MyProduct">
<Component Id="cmpMyProductShortcut" Guid="*">
<Shortcut Id="MyAppShortcut" Name="My App" Description="My Application" Target="[INSTALLFOLDER]MyApp.exe" />
<RemoveFolder Id="RemoveMyCompanyShortcutDir" On="uninstall" Directory="MyCompanyShortcutDir" />
<RegistryValue Root="HKCU" Key="Software\My Company\My Product\" Name="Installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
<Component Id="cmpUninstall" Guid="*">
<Shortcut Id="UninstallShortcut" Name="Uninstall" Description="Uninstall My App"
Target="[System64Folder]msiexec.exe" Arguments="/x [ProductCode] /Lv d:\uninstall.log " Directory="MyProductShortcutDir" />
<RegistryValue Root="HKCU" Key="[Software\My Company\My Product\" Name="Uninstall" Type="integer" Value="1" KeyPath="yes" />
<RemoveFolder Id="removeShortcut" On="uninstall"/>
</Component>
</Directory>
</Directory>
</Directory>
I solved this issue myself, basically two things needed:
Change the ProductCode to *, this allows side-by-side install of two versions.
Make sure the Component Guid for Shortcut to be * as well

Copy file from setup location to another location in wix on install

I have created an msi setup file which includes some files in a "Sample" folder which should be copied to a temp folder. Anybody suggest how to do this?
Something like this:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="MyVendor" Name="MyVendor">
<Directory Id="INSTALLDIR" Name="MyDir">
<Component Id="MyFileId" Guid="...G1...">
<File Id="MyFileId" Name="MyFile" Source="...blabla...\MyFile" KeyPath="yes" >
</File>
</Component>
<DirectoryRef Id="TARGETDIR">
<Component Id="MyFileCopyId" Guid="...G2...">
<RemoveFile Id="MyFileRemoveId" Name="MyFile" On="install" Directory="MyCopyDir" />
<CopyFile Id="MyFileCopyId" FileId="MyFileId" DestinationDirectory="MyCopyDir" />
</Component>
<Feature Id="MyFeature" ... >
<ComponentRef Id="MyFileId" />
<ComponentRef Id="MyFileCopyId" />
The important Xml element is CopyFile. You need to create a new component that is a copy of the first one (with different ids, guids, ... of course). Both components needs to be declared in a feature.
CopyFile element is your friend. You can nest it under the original File element a number of times, depending on how many times you need to copy it. Put the correct destination folder(s) and let Windows Installer do the rest.