WIX - Rename shortcut in MSP - wix

I am not that experienced with WiX and I am having a problem when renaming a shortcut during update via MSP. In my previous MSI I have created a desktop shortcut using the following
<DirectoryRef Id="TARGETDIR">
<Directory Id="DesktopFolder" Name="Desktop">
<Component Id="MyShortcut" Guid="38EF1A86-5D1B-4D78-AD66-DD1AA6635A9B" Win64="$(var.Variables_Win64)" MultiInstance="no">
<Shortcut Id="MyShortcut"
Directory="DesktopFolder"
Icon="MyIcon"
Name="My Application"
Description="Runs my application"
Target="[URL]" />
<RemoveFolder Id='DesktopFolder' On='uninstall'/>
</Component>
</Directory>
</DirectoryRef>
In my MSP I want to rename the schortcut as such
<DirectoryRef Id="TARGETDIR">
<Directory Id="DesktopFolder" Name="Desktop">
<Component Id="MyShortcut" Guid="38EF1A86-5D1B-4D78-AD66-DD1AA6635A9B" Win64="$(var.Variables_Win64)" MultiInstance="no">
<Shortcut Id="MyShortcut"
Directory="DesktopFolder"
Icon="MyIcon"
Name="My New Application"
Description="Runs my new application"
Target="[URL]" />
<RemoveFolder Id='DesktopFolder' On='uninstall'/>
</Component>
</Directory>
</DirectoryRef>
What I get when I run my upgrade is a new desktop shortcut as well as the orphaned old shortcut. I understand why this is happening from this post why two shortcuts after Major upgrade (migration)? but I am not sure how I can work around this behaviour and either update the original shortcut name or delete the orphaned one instead. I cannot build an MSI it has to be an MSP so any advice would be welcome.
Thank you in advance ;-)

The solution appears to be add in a RemoveFile but with the full name including extension to the shortcut. I had initially tried this approach before posting but had not specified the .lnk on the name so it did not work.
<DirectoryRef Id="TARGETDIR">
<Directory Id="DesktopFolder" Name="Desktop">
<Component Id="MyShortcut" Guid="38EF1A86-5D1B-4D78-AD66-DD1AA6635A9B"
Win64="$(var.Variables_Win64)" MultiInstance="no">
<Shortcut Id="MyShortcut"
Directory="DesktopFolder"
Icon="MyIcon"
Name="My New Application"
Description="Runs my new application"
Target="[URL]" />
<RemoveFolder Id='DesktopFolder' On='uninstall'/>
<RemoveFile Id='LegacyShortcut ' Name='My Application.lnk' On='install'/>
</Component>
</Directory>
</DirectoryRef>

Related

How do I tell wix to install a file in a directory set in a property?

I want to do the following where XLSTART is defined as:
<CustomAction Id="AssignXLSTART" Return="check" Execute="firstSequence" Directory ='XLSTART' Value='[AppDataFolder]\Microsoft\Excel\XLSTART'>
</CustomAction>
And then I have a subsequent CustomAction that calls some C# code that may change this value.
And then in the list of files to install I have:
<Directory Id="XlStartFolderId" Name="[XLSTART]">
<Component Id="ExcelMacro_xla" Guid="26D21093-B617-4fb8-A5E7-016493D46055" DiskId="1">
<File Id="ExcelXLA" Name="AutoTagExcelMacro.xlam" ShortName="XLMacro.xla" Source="$(var.srcFolder)\AutoTagExcelMacro.xlam"/>
</Component>
</Directory>
But the above puts it in the INSTALLDIR[XLSTART]. How do I get it to read this as a property?
You should be able to install to the userprofile directory you refer to like this:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="Microsoft" Name="Microsoft">
<Directory Id="Excel" Name="Excel">
<Directory Id="XLSTART" Name="XLSTART">
<Component Id="ExcelAddIn" Feature="MyFeature" Guid="{11111-1111-GUID-HERE-YOURGUIDHERE}">
<File Source="C:\SourceFiles\MyAddin.xla" />
<RemoveFolder Id="Microsoft" On="uninstall" Directory="Microsoft" />
<RemoveFolder Id="Excel" On="uninstall" Directory="Excel" />
<RemoveFolder Id="XLSTART" On="uninstall" Directory="XLSTART" />
<RegistryValue Root="HKCU" Key="Software\MySoftware" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
I would suggest you use the per-machine xlstart folder instead - if it still exists. I am not sure it does. The the addin is loaded for every user on the box on every launch. Generally I prefer this. It has been ages since I looked at this, so this could have changed in newer Office versions - in fact I am sure it has, but the details are unclear to me.
System Folder Properties: There are a number of System Folder Properties that can be used in MSI files to specify installation location - LocalAppDataFolder is just one of them: https://learn.microsoft.com/en-us/windows/win32/msi/property-reference#system-folder-properties
Figured it out. You need to install to the INSTALLDIR and then use CopyFile
<!-- place it in C:\Program Files (x86)\Microsoft Office\Root\Office16\XLSTART\ -->
<Component Id="ExcelMacro_xla" Guid="26D21093-B617-4fb8-A5E7-016493D46055" DiskId="1">
<File Id="ExcelXLA" Name="AutoTagExcelMacro.xlam" ShortName="XLMacro.xla" Source="$(var.srcFolder)\AutoTagExcelMacro.xlam">
<CopyFile Id='CopyXlMacro' DestinationProperty='XLPATH' DestinationName='AutoTagExcelMacro.xlam'/>
</File>
</Component>

Placing multiple Shortcuts in a Wix Installer

I'm trying to add multiple shortcuts under a certain folder using Wix. The code looks like this:
<DirectoryRef Id ="TARGETDIR">
<Directory Id="DesktopFolder" Name="DesktopFolder">
<Component Id="DesktopP" Guid="61AE5ABE-9ED2-43B0-98C4-3050A40BF061">
<Shortcut Id="DesktopMyProgramShortcut" Name="$(var.MyProgramLabelShortcut)" Target="[#MyProgramcsproja015777b77a239eeb0bd49c2dafdbe31]" WorkingDirectory="bin"/>
<RemoveFolder Id="DesktopFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="SOFTWARE\Example\Shortcuts" Name="167CE804-4A37-45B8-B010-EB6B3E73BE54" Type="string" Value="" KeyPath="yes"/>
</Component>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id ="ProgramMenuFolderMyProgram" Name ="$(var.MyProgramLabelShortcut)">
<Component Id="ProgramMenuMyProgram" Guid="A7B4A27B-9367-4AFF-B8CC-D6651B18FBFD">
<Shortcut Id="ProgramMenuMyProgramShortcut" Name="$(var.MyProgramLabelShortcut)" Target="[#MyProgramcsproja015777b77a239eeb0bd49c2dafdbe31]" WorkingDirectory="bin"/>
<Shortcut Id="ProgramMenuMyProgramManual" Name="$(var.MyProgramLabelShortcut)" Target="[documents]" Icon="shell32.dll" IconIndex="45"/>
<RemoveFolder Id="ProgramMenuFolderMyProgram" On="uninstall"/>
<RegistryValue Root="HKCU" Key="SOFTWARE\Example\Shortcuts" Name="167CE804-4A37-45B8-B010-EB6B3E73BE54" Type="string" Value="" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
</DirectoryRef>
The weird behavior is that, when I try to place more than one shortcut, only the second one is added. I've tried placing the Shortcut in separate Components but still acts that way. In Windows7 works perfectly by the way.
Any suggestion about how to fix it?
Thanks in advance!
The problem had to do with the name of the shortcuts. I guess that, since their names were equal, the first shortcut was overwritten by the second one. I've fixed it changing the name of the second shortcut.

Add resource files in wix installer

I have created a multi lingual app that uses 2 diferent resource files to manage the UI language, so when I build and execute my program, in my bin directory I have my app files and two folders, en-GB and pt-PT.
I am now trying to create a installer with Wix, for that I am defining the following directories:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="App" >
<Directory Id="LOCALEEN" Name="en-GB"/>
<Directory Id="LOCALEPT" Name="pt-PT"/>
</Directory>
</Directory>
</Directory>
</Fragment>
And then, I define the following components:
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="App.resources.en.GB.dll" Guid="...">
<CreateFolder />
<File Id="App.resources.en.GB.dll" Name="App.resources.dll" Source="$(var.App.App_TargetDir)en-GB\App.resources.dll" />
</Component>
<Component Id="App.resources.pt.PT.dll" Guid="...">
<CreateFolder />
<File Id="App.resources.pt.PT.dll" Name="App.resources.dll" Source="$(var.App.App_TargetDir)pt-PT\App.resources.dll" />
</Component>
... Other components...
</ComponentGroup>
</Fragment>
When I rebuild my solution I get the following error:
'App.resources.dll' is installed in '[ProgramFilesFolder]\App\' by two
different components on an LFN system: 'App.resources.en.GB.dll' and
'App.resources.pt.PT.dll'. This breaks component reference counting.
I understand the problem, both resources dll are being copied to the installation folder, and not to the specific resources file... But I don't know how to solve it. Anyone can give any hints on how to solve this?
Just reference the directory where you want your components eg. Directory="LOCALEEN". There is no need to specify <CreateFolder />
I also recomend to maintain some kind of naming convention. Your Components and Fils have the same id. See https://stackoverflow.com/a/1801464/4634044. So this should do what you expect:
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="C_EnglishLocale" Guid="..." Directory="LOCALEEN">
<File Id="Fi_EnglishLocale" Name="App.resources.dll" Source="$(var.App.App_TargetDir)en-GB\App.resources.dll" />
</Component>
<Component Id="C_PolnishLocale" Guid="..." Directory="LOCALEPT">
<File Id="Fi_PolnishLocale" Name="App.resources.dll" Source="$(var.App.App_TargetDir)pt-PT\App.resources.dll" />
</Component>
</ComponentGroup>
</Fragment>

Why do we get an ICE57 error for non advertised shortcuts in per machine installations?

This question is asking whether one of the ICE57 validators creates a false positive error report.
I am using WIX 3.9 to generate an installer. I want a per machine installation with non advertised shortcuts.
This WXS example installs a text file and a shortcut to open the text file:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="ShortcutTest" Language="1033"
Version="1.0.0.0" Manufacturer="Widget Co"
UpgradeCode="--YOUR GUID1--">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="ShortcutTest" Level="1">
<ComponentRef Id="TextFile" />
<ComponentRef Id="ShortCut" />
</Feature>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="ShortcutTest">
<Component Id="TextFile" Guid="--YOUR GUID2--">
<File Id="File" Name="TextFile.txt" Source="TextFile.txt" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="Shortcut Test">
<Component Id="ShortCut" Guid="--YOUR GUID3--">
<RegistryValue Root="HKMU" Key="Software\WidgetCo\ReadMeTextFile\TextFile" Name="Installed" Type="string" Value="yes" KeyPath="yes"/>
<Shortcut Id="Shortcut"
Name="Open Text File"
Description="Opens a text file"
Target="[INSTALLFOLDER]TextFile.txt"
WorkingDirectory="INSTALLFOLDER"/>
<RemoveFolder Id="ApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall"/>
</Component>
</Directory>
</Directory>
</Directory>
</Product>
</Wix>
If you build the above example into an MSI package, you get this Internal Consistency Evaluator (ICE) error:
D:\Robert\Documents\Visual Studio 2013\Projects\ShortcutTest\Product.wxs(27,0): error LGHT0204: ICE57: Component 'ShortCut' has both per-user data and a keypath that can be either per-user or per-machine.
ICE57 is implying an inconsistency between per-user and per-machine data. But, the key path of the component is HKMU, which in a per machine installation resolves to HKLM (HKEY_LOCAL_MACHINE). The location of the shortcut derives from 'ProgramMenuFolder', which in a per-machine installation resolves to C:\ProgramData\Microsoft\Windows\Start Menu\ (on Windows 8.1). None of the component's resources appear to have any per-user association.
You can build the installer package into an MSI by suppressing ICE57. The resulting MSI package installs without any obvious errors. Multiple users can log on and access the shortcut. Any user can un-install the package and all of the resources in the package are removed.
The answer to Wix create non advertised shortcut for all users / per machine has an interesting workaround, which is to author advertised shortcuts and then turn off advertising. Seems a round about way of creating un-advertised shortcuts.
A common fix for the ICE57 error is to change the <RegistryValue...> root to HKCU (HKEY_CURRENT_USER). However this creates an installer that can leave a user registry key behind when un-installed. For example if user A installs the package, a registry entry is added to user A's registry hive. If user B removes the package, the registry entry is not removed from user A's registry hive.
In this scenario is the ICE57 error a bug in the Internal Consistency Evaluators? Or is there something I have miss-understood?
While researching another problem I found this comment on http://sourceforge.net/p/wix/mailman/message/26687047/ from Rob Mensching:
IIRC, this is a bug in ICE57. The Windows Installer team didn't look at
ALLUSERS property when evaluating these values... that was a long time ago
though so my memory may have decayed a bit.
It looks like a bug in ICE57.
Move your Shortcut to the be a child of File and add the Adversite="yes" attribute. The RegistryValue should do the trick for converting the shortcut from perUser to perMachine.
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MyApp" />
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ApplicationProgramsFolder" Name="My App Name" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ComponentGroup_Core">
<Component Id="Component_App" Guid="INSERT_GUID_HERE" Directory="INSTALLFOLDER">
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[AppName]"
Name="AppInstalled" Type="string" Value="yes" KeyPath="yes"/>
<File Id="MyApp" Name="My Test App.txt">
<Shortcut Id="Shortcut"
Name="Open Text File"
Description="Opens a text file"
Directory="ApplicationProgramsFolder"
WorkingDirectory="INSTALLFOLDER" />
</File>
</Component>
<Component Id="Component_MenuFolder" Guid="INSERT_GUID_HERE"
Directory="ApplicationProgramsFolder">
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[AppName]"
Name="MenuFolderInstalled" Type="string" Value="yes"
KeyPath="yes"/>
<RemoveFolder Id="RemoveFolder_App" On="uninstall" />
</Component>
</ComponentGroup>
</Fragment>

Creating start menu shortcuts, result is error LGHT0094

When adding start menu shortcuts light.exe will produce the LGHT0094 error:
<Directory Id="ProgramMenuFolder" Name="Menu">
<Directory Id="DirManufacturer" Name="Manufacturer">
<Component Id="MenuManufacturer" Guid="" KeyPath="yes">
<CreateFolder Directory="Manufacturer">
</CreateFolder>
</Component>
<Directory Id="DirProduct" Name="Product">
<Component Id="MenuProduct" Guid="" KeyPath="yes">
<CreateFolder Directory="Product">
</CreateFolder>
<Shortcut Id="SHC_Program1" Name="Program 1" Target="[ApplicationRootDirectory]Program1.exe" />
</Component>
</Directory>
</Directory>
What is wrong in my XML?
Could somebody tell me how to create subsequent menu items in the start menu?
Start Menu
Manufacturer (this and all subsequent items have to be created by the Installer)
Product
Program 1
Program 2
etc.
The article How To: Create a Shortcut on the Start Menu of WiX manual has exhaustive explanation of how to create this kind of shortcut.