WiX minor upgrade remove Windows 7 taskbar pinned shortcut - wix

Every update to new version WiX for some reason removed pinned start menu shortcut from taskbar. How can I fix this?
Shortcut was created using this command:
<DirectoryRef Id="ProgramMenuFolder">
<Component Id="GitExtensions.newstartmenu" Guid="*">
<Shortcut
Id="GitExtensions.newstartmenu"
Name="$(var.ProductName)"
Description="$(var.ProductName)"
Icon="gitextensions.ico"
Target="[INSTALLDIR]GitExtensions.exe"
WorkingDirectory="INSTALLDIR"/>
<RegistryValue
Root="HKCU" Key="$(var.InstalledRegKey)"
Name="GitExtensions.newstartmenu" Value="" Type="string"
KeyPath="yes"/>
</Component>
</DirectoryRef>
WiX code: https://github.com/gitextensions/gitextensions/blob/f9490e3e6e34cc2f6770fd9e1d6132cf5cfd0b0b/Setup/Product.wxs#L385-L399
Setup had been built in VS2010 + WiX 3.5.

It's actually doing a major upgrade and by scheduling RemoveExistingProducts early, the upgrade is removing the older version before installing the newer version. The shell removes the pin when the older shortcut is removed. You can try experimenting with a later scheduling of RemoveExistingProducts but note that there are costs associated with that.

Related

How to keep taskbar shortcut during update?

I have the following situation.
My product installs the binaries inside c:\Program Files (x86)\MyCompany\MyApp\ and a shortcut under C:\ProgramData\Microsoft\Windows\Start Menu\Programs\MyCompany.
I build the msi using this great example: https://helgeklein.com/blog/2014/09/real-world-example-wix-msi-application-installer/
I just added the following piece of code
<!-- ApplicationShortcut-->
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="!(loc.ManufacturerName)">
<Component Id="ApplicationShortcut" Guid="F4B7EAFA-FF19-41B4-8267-3AEFC12235A7">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="!(loc.ApplicationName)"
Description="!(loc.ProductDescription)"
Target="[INSTALLDIR]MyApp.exe"
WorkingDirectory="INSTALLDIR"
/>
<RemoveFolder Id="RemoveApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\!(loc.ManufacturerName)\!(loc.ApplicationName)" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
The problem is the following
I install the application the fist time, it will install the shortcut just fine
Now I start the app and choose Pin to taskbar, this will create a shortcut inC:\Users\\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar`
If I rebuild the msi and execute the setup again, the taskbar shortcut is not clickable anymore, because the shortcut in C:\Users\<user>\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar is missing
Is it possible to maintain the taskbar shortcut during an update?
I found the answer here: https://stackoverflow.com/a/33402698/98491
<InstallExecuteSequence>
<RemoveShortcuts>Installed AND NOT UPGRADINGPRODUCTCODE</RemoveShortcuts>
</InstallExecuteSequence>
This prevents shortcuts from being uninstalled during an update.
As described in the comments, the disadvantage is that, after uninstall, the TaskBarShortCut remains, but that is something that a user might expect. Having to recreate a pinned taskbar shortcut everytime he updates a software is not.

Old Property with RegSearch is affecting Product upgrade (new version without this prop)

I've inherited project with MSI created in WiX and now I'm trying to solve some of the issues that unfortunately exist.
There's a remember property pattern which is used to found specific directory saved in registry entry:
<Property Id="AUTO_FOUND_DIR" Secure="yes" Admin="yes">
<RegistrySearch Id="regsrch_AUTO_FOUND_DIR"
Root="HKCU"
Key="$(var.RegPath)"
Name="$(var.SpecificKey)"
Type="raw"
/>
</Property>
The SpecificKey value is then saved in AUTO_FOUND_DIR property.
Then the black magic appears. A separate component is holding (among other stuff) a shortcut located in ProgramMenuFolder (non-advertised) to the main executable.
I've been told that usage of util:RemoveFolderEx is a workaround for an old issue where this shortcut was orphaned and hasn't been removed during uninstall:
<Feature>
<DirectoryRef Id="ProgramMenuDir">
<Component Id="cmp_ProgramMenuDir" Guid="{0E8BD13A-GUID-IS-HERE-6E5092ECA9EF}">
<CreateFolder />
<RemoveFolder Id='ProgramMenuDir' On='uninstall' />
<RegistryKey Id='reg_SpecificKeyID' Root='HKCU' Key='$(var.RegPath)' ForceCreateOnInstall="yes">
<RegistryValue Type='string' Name='$(var.SpecificKey)' Value='[ProgramMenuDir]'/>
</RegistryKey>
<!-- other content: shortcut to ProgramMenuFolder and other stuff -->
<util:RemoveFolderEx Id="rm_dirID" On="install" Property="AUTO_FOUND_DIR"/>
</Component>
</DirectoryRef>
</Feature>
The problem is: I don't need this workaround (and usage of AUTO_FOUND_DIR property as well. I've removed that code but during upgrade (major, Product and Package GUIDs set to "*", UpgradeCode has the same value as previous version) I can see in verbose log from MSI that this AUTO_FOUND_DIR exists, the RegistrySearch reads the key value with specific directory and as a result the util:RemoveFolderEx removes that directory and all components that are there located.
My question is: how can I detect why this old property is being used during upgrade and how to get rid of it?
Additional information: the install scope is PerMachine, ALLUSERS is set to 1. The MSI with upgraded version has this property removed.
Without a close look at your complete verbose log to see what's going on, remember that an upgrade does an uninstall of the older installed product. This means that a lot of the logic in the older installed product will happen during your upgrade. So you will definitely see the RegistrySearch running as the older product uninstalls, setting AUTO_FOUND_DIR, and you will see the RemoveFolder that runs during the uninstall.
So it's not clear if you actually have an issue if all you're seeing is the uninstall activity of that older product being uninstalled. That activity is embedded in the installed product.

WiX: Managed to not overwrite config file during upgrade, however shortcuts are removed

I have a similar problem like forki23 by bring Wix to not overwrite a configuration file during upgrade. I have a config file that should not be overwritten during upgrade, but it should be removed during uninstall. However every solution I find, breaks something else.
If I set NoOverwrite=yes and move the RemoveExistingProducts to InstallFinalize the config file is handled as I wished. However, in this case the shortcut is removed during upgrade for some reason. If I leave RemoveExistingProducts at InstallInitialize, the config file is actually removed during upgrade, however the shortcuts are present.
Why is this happening and is there are way to fix it?
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
<!-- InstallInitialize causes config-file to disappear during upgrade -->
<!-- InstallFinalize causes shortcuts to disappear during upgrade -->
...
<Property Id="DISABLEADVTSHORTCUTS" Value="1" />
...
<Directory Id="INSTALLLOCATION" Name="MyApp">
<Component Id="MYAPP.EXE" DiskId="1" Guid="...">
<File Id="MYAPP.EXE" Name="MyApp.exe" Source="..." Vital="yes" KeyPath="yes">
<Shortcut Id="startmenuShortcut"
Directory="ProgramMenuDir"
Name="!(loc.ProductName)"
WorkingDirectory='INSTALLLOCATION'
Icon="Icon.ico"
IconIndex="0"
Advertise="yes" />
</File>
<RegistryValue Root="HKLM"
Name="InstallLocation"
Key="$(var.InstallLocationRegistryKey)"
Type="string"
Value="[INSTALLLOCATION]">
</RegistryValue>
</Component>
<Component Id="MYAPP.EXE.CONFIG" DiskId="1" Guid="..." NeverOverwrite="yes">
<File Id="MYAPP.EXE.CONFIG"
Name="MyApp.exe.config"
Source="..."
KeyPath="yes" />
</Component>
...
</Directory>
...
<Directory Id="ProgramMenuFolder">
<Directory Id="ProgramMenuDir" Name="!(loc.ProductPrefix)">
<Component Id="ProgramMenuDir" Guid="...">
<RegistryValue Root="HKCU" Key="SOFTWARE\MyApp"
Type="string" Value="[INSTALLLOCATION]" KeyPath="yes" />
<RemoveFolder Id="ProgramMenuDir" On="uninstall"/>
</Component>
</Directory>
</Directory>
Note A: The config-file is a machine-wide configuration and should apply for all users.
Note B: I'm using WiX 3.7 and the target plattform is Windows 7 and 8.
Theoretically "NoOverwrite=yes and move the RemoveExistingProducts to InstallFinalize" should work, but it s clear we are losing something from the big picture. The best method to see why Windows Installer removes the shortcuts is to create a verbose log when launching the upgrade setup. You can do that in a cmd.exe with this command: msiexec /i [msi path] /L*V debug.log
The post the a download link for the log and the GUIDs of the components hosting the shortcuts so we can see if the log helps us understand what happens.
Windows installer works very exact in those things, and if anything gets removed in the After="InstallFinalize" case, this means, that a component has been removed, MSI has thought is not needed, because not contained in your new version of the msi file. Be very sure the GUID of the component containing MYAPP.exe and the shortcut has not changed in your new version. (Compare with a tool like Orce or Insted). It seems it has!
MSI removes only full components, not only shortcuts. Really! Maybe you have an update problem of shortcuts in Windows. Sometimes such things happen. Try to reboot to be sure, that this happens, what you think. Maybe there is an error in your test procedure (or it's the above mentioned GUID problem). There are not many other possibilities, if you have not custom actions which remove shortcuts or you try to add shortcuts as files or such dangerous stuff.
Putting a shortcut in the same component as the .exe is common, but not optimal in my eyes! I recommend to separate resources as much as possible, so put it in an own component. This has advantages, if you later want to rename the shortcut. Then you can just change the GUID of this component and the important .exe file is not touched.
There is a small disadvantage of that, loosing the direct connection to the file version of MYAPP.exe in overinstall scenarios, so if MYAPP.exe is a shared file between several different setups, this is not recommended. Perfect solutions for this are possible, but are not in the focus here.
Workaround: If you are still able to change the old (first) msi setup, just mark the component MYAPP.EXE.CONFIG as permanent. Then it will not be uninstalled during Major Upgrade (but not uninstalled at all, what has advantages and disadvantages, in other words, it is mostly acceptable for .config files).
If version 1 of your setup is already shipped, then you could do the same with some tricks too.

WiX minor upgrade doesn't remove old Shortcut

The following steps had been performed:
Setup1.msi had been built in VS2005 + WiX 3.0 (.NET Framework 2.0).
Version 1.0.0.0 had been installed by Setup1.msi.
For the purpose of minor upgrade a Setup2.msi had been built
(Setup2.msi differs from Setup1.msi ONLY in ProductVersion="1.0.1.0")
The following Patch.wxs had been prepared:
<Patch
AllowRemoval="no"
Classification="Update"
Comments="..."
Description="..."
DisplayName="..."
Manufacturer="..."
TargetProductName="...">
<Media Id="1000" Cabinet="MyPatch.cab">
<PatchBaseline Id="MyPatch" />
</Media>
<PatchFamily
Id="MyPatchFamily"
Version="1.0.1.0"
ProductCode="...THE SAME AS IN Setup1.msi..."
Supersede="yes">
<ComponentRef Id="CMP_Program_EXE" />
<ComponentRef Id="CMP_Desktop_Shortcut" />
<ComponentRef Id="CMP_ProgramMenu_Shortcut" />
</PatchFamily>
</Patch>
Patch.msp had been created with help of candle, light, torch and pyro.exe.
The following command had been invoked:
msiexec /p Patch.msp REINSTALL=ALL REINSTALLMODE=vomus
As a result, Program.exe was updated and new shortcuts "v. 1.0.1"
were created.
However, old Shortcut "v. 1.0.0" remained both on "DesktopFolder" and on
"ProgramMenuFolder".
How can I make the Patch remove old Shortcut?
Thanks in advance.
The simplest way is not to add version to shortcut name. See Windows UX Guidelines:
Avoid putting a version number in a program name unless that is how users normally refer to your program.
Otherwise your minor upgrade has to remove the shortcut to the old version and create a new shortcut that points to the new version.
During minor upgrade, the old version does not get uninstalled, that's why the shortcut is not updated.
You can use the RemoveFile element within the Component one owning the Shortcut:
<DirectoryRef Id="DesktopFolder">
<Component Id="..." Guid="...">
<Shortcut Id="..." Name="foobar_1.0.1" ... />
<RemoveFile Id="..." Name="foobar_1.0.0.lnk" On="install" />
...
</Component>
</DirectoryRef>
But. There's one problem remained -- when you uninstall you MSP patch, new shortcut (foobar_1.0.1.lnk) is not removed (because the Shortcut table is transformed back, I believe). Therefore, user ends up with two shortcuts. I do not know how to fix that, therefore I asked here.

WiX Conditional Feature/Component Orphaned on Uninstall

Edit: Quoting myself because I summarized the issue much better in one of the comments below…
I have a condition that is true when the package is installed, but
not true when it is removed. I expected MSI to remember that it had
installed the conditional component and remove it with the uninstall,
but this is not the case. I am trying to find out A) the proper way to
clean up this orphaned component, and B) the best way to protect
against this problem in the future.
I guess my question boils down to, is it safe to just delete an orphaned feature/component after a product is uninstalled? And is there any way to check what, if anything, is still referencing a component that I believe to be an orphan? And how do I fix my installer to keep this from happening in the future?
We have a wix project to install a library, Foo. This installer puts copies of Foo.dll into the GAC, and a folder, Program Files\Reference Assemblies\Foo\<version> by default. The installer also adds two registry keys, one is a custom key which stores the path of the Foo folder for reuse in future installs, the other tells Visual Studio to include the full <version> folder path in its search for installed libraries so that Foo shows up in the “Add References” dialog. Multiple versions of the Foo library can be installed on the machine at a time, each will be located in the appropriate <version> folder under Foo.
Foo 2.0.0 had a bug that slipped through testing, Foo 2.0.1 contained the bug fix, no other changes. It was decided that since the bug fix was the only change, we would add a policy file to the GAC which would redirected references for Foo 2.0.0 to Foo 2.0.1. This policy file was added to the installer as a new component inside of a new feature. An upgrade tag was added to detect and remove Foo 2.0.0 when Foo 2.0.1 was installed. The installation of the policy feature was made conditional on Foo 2.0.0 being detected. Everything seemed to be working and Foo 2.0.1 was pushed out.
Now, a year later, we discover that we again missed noticing a bug, this time in the installer setup rather than the library code. It turns out that when Foo 2.0.1 replaces 2.0.0, and is then uninstalled, the policy file is orphaned and remains in the GAC while all other files and keys are removed. I have tested this on a clean install of windows (virtual machines can be so useful) and confirmed that the problem can be replicated, i.e. no additional references to the component have snuck in to cause it to stay behind.
All of this was originally done in WiX 3.0 but we have recently moved up to using WiX 3.5. Our WiX code looks like this:
<Product Id="Guid 1" Name="Foo v2.0.1" Language="1033" Version="2.0.1" Manufacturer="My Team" UpgradeCode="Guid 2">
<Package InstallerVersion="300" Compressed="yes" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Upgrade Id="Guid 2">
<UpgradeVersion Minimum="2.0.0" Maximum="2.0.0" IncludeMaximum="yes" IncludeMinimum="yes" OnlyDetect="no" Property="UPGRADE2X0X0"></UpgradeVersion>
</Upgrade>
<Property Id="FOODIR">
<RegistrySearch Id="FooPath" Type="directory" Root="HKLM" Key="Software\Foo" Name="InstallPath"></RegistrySearch>
</Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="RefAssemb" Name="Reference Assemblies">
<Directory Id="FOODIR" Name="Foo">
<Component Id="FooLibPath" Guid="Guid 3">
<RegistryKey Root="HKLM" Key="Software\Foo" Action="createAndRemoveOnUninstall">
<RegistryValue Name="InstallPath" Type="string" Value="[FOODIR]" KeyPath="yes"></RegistryValue>
</RegistryKey>
</Component>
<Directory Id="FOOVERSION" Name="v2.0.1">
<Component Id="Foo_VSFile" Guid="Guid 4">
<File Id="Foo_DLL" Source="$(sys.CURRENTDIR)2.0.1\Foo.dll" KeyPath="yes"></File>
</Component>
<Component Id="Foo_VSRegKey" Guid="Guid 5">
<RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\.NETFramework\v3.5\AssemblyFoldersEx\Foo v2.0.1" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Value="[FOOVERSION]" KeyPath="yes"></RegistryValue>
</RegistryKey>
</Component>
<Directory Id="FOOGAC" Name="GAC">
<Component Id="Foo_GAC" Guid="Guid 6">
<File Id="Foo" Source="$(sys.CURRENTDIR)2.0.1\Foo.dll" KeyPath="yes" Assembly=".net"></File>
</Component>
<Component Id="Foo_Policy_2x0x1" Guid="Guid 7">
<File Id="Foo_PolicyDLL" Source="$(sys.CURRENTDIR)2.0.1\policy.2.0.Foo.dll" KeyPath="yes" Assembly=".net"></File>
<File Id="Foo_PolicyConfig" Source="$(sys.CURRENTDIR)2.0.1\policy.2.0.Foo.config" CompanionFile="Foo_PolicyDLL"></File>
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFoo" Level="1">
<ComponentRef Id="Foo_GAC"/>
<Feature Id="Foo_VSSupport" Level="1">
<ComponentRef Id="FooLibPath"/>
<ComponentRef Id="Foo_VSFile"/>
<ComponentRef Id="Foo_VSRegKey"/>
</Feature>
<Feature Id="Foo_Policy_v2x0x1" Level="0">
<ComponentRef Id="Foo_Policy_2x0x1"/>
<Condition Level="1">UPGRADE2X0X0</Condition>
</Feature>
</Feature>
</Product>
is it safe to just delete an orphaned feature/component after a
product is uninstalled?
No, it's not. If you just delete it, its component registration information is still left on the machine.
And is there any way to check what, if anything, is still referencing
a component that I believe to be an orphan?
Not really. But if there is something referencing one of your components, it's most likely another product developed by you or an older version of your current product which wasn't uninstalled correctly.
It's very unlikely that a random product would reference your component or assembly.
And how do I fix my installer to keep this from happening in the
future?
Use major upgrades which uninstall the old component and install the new one. No special policy files, no conditional installations or removals.
Multiple versions of the Foo library can be installed on the machine
at a time, each will be located in the appropriate folder
under Foo.
Why? If you have a single product, you can use major upgrades. This way the user will have only one version installed with only one version of your assembly.
Versioned assemblies installed side by side make sense only for different products.
It was decided that since the bug fix was the only change, we would
add a policy file to the GAC which would redirected references for Foo
2.0.0 to Foo 2.0.1. This policy file was added to the installer as a
new component inside of a new feature.
This is a hack and most likely this is what is causing the problem. Your new installed should have uninstalled the old version along with Foo 2.0.0.
Major upgrades should always be standalone.