Wix create silent uninstall file - wix

my idea is make an uninstall file with .msi install file. I read some information about creating uninstaller shortcut here: http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/create_uninstall_shortcut.html , But i cant found information about make uninstall file after msi build , maybe whom know it's possible ? and if possible how i can do it ? or maybe it possible to do with cmd script? Just write script for automatically uninstall my program from mashine. My code is :
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"><?define WpfApp1_TargetDir=$(var.WpfApp1.TargetDir)?>
<Product Id="*" Name="SetupProject2" Language="1033" Version="1.0.0.0" Manufacturer="Andrejka" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Property Id="WIXUI_INSTALLDIR" Value="TESTFILEPRODUCTDIR" />
<Property Id="WixShellExecTarget" Value="[#WpfApp1.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Property Id="LAUNCH_APP_ON_EXIT" Value="1" />
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFiles'/>
</InstallExecuteSequence>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="SetupProject2" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TESTFILEPRODUCTDIR" Name="SetupProject2">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject2" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<!-- <Component Id="ProductComponent"> -->
<!-- TODO: Insert files, registry keys, and other resources here. -->
<!-- </Component> -->
<Component Id="WpfApp1.exe" Guid="*">
<File Id="WpfApp1.exe" Name="WpfApp1.exe" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe" />
</Component>
<Component Id="WpfApp1.exe.config" Guid="*">
<File Id="WpfApp1.exe.config" Name="WpfApp1.exe.config" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe.config" />
</Component>
<Component Id="aws_sdk_net_core_support.dll" Guid="*">
<File Id="aws_sdk_net_core_support.dll" Name="aws-sdk-net-core-support.dll" Source="$(var.WpfApp1_TargetDir)aws-sdk-net-core-support.dll" />
</Component>
<Component Id="AWSSDK.Core.dll" Guid="*">
<File Id="AWSSDK.Core.dll" Name="AWSSDK.Core.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.Core.dll" />
</Component>
<Component Id="AWSSDK.SimpleNotificationService.dll" Guid="*">
<File Id="AWSSDK.SimpleNotificationService.dll" Name="AWSSDK.SimpleNotificationService.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.SimpleNotificationService.dll" />
</Component>
<Component Id="MimeSharp.dll" Guid="*">
<File Id="MimeSharp.dll" Name="MimeSharp.dll" Source="$(var.WpfApp1_TargetDir)MimeSharp.dll" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>

In general you are not supposed to put uninstall shortcuts in the start menu, it is in fact a violation of Microsoft's logo requirements for Windows applications I believe. Rather you should let people uninstall your product the normal way via the add/remove programs applet.
UPDATE: I found this answer with some more information on this topic: Shortcuts with name "Uninstall <Program Name>" are not displayed in Windows 8/8.1/10
Also, just so it is clear, uninstall, is a built-in feature of MSI files - it is always automatically available unless actively blocked (such as some applications hiding themselves from display in add/remove programs). There is nothing extra you have to do in your WiX sources to support uninstall properly. Just follow Windows Installer guidelines and it comes "for free".
If what you are asking is for a way to create an uninstall batch file, then you can find a plethora of ways to uninstall your MSI file in this "uninstall reference": Uninstalling an MSI file from the command line without using msiexec.
In short, just run the command line below to uninstall your MSI if you have the MSI's product code (you can find your product code by querying your system as described here: How can I find the product GUID of an installed MSI setup? - you might need to look it up since you auto-generate your product code):
msiexec.exe /x {your-product-guid}
or just uninstall by referring to your original MSI installation file like this:
msiexec.exe /x "c:\filename.msi
See the linked answer above (the uninstall reference) for a lot more information about this.

Related

WiX Installer use RegistrySearch result for directory

I'm trying to create an installer using WiX for an add-in to a product called SolidWorks.
Looking at the docs led me to believe that I should be able to look up a location based on a registry value to find the install destination.
Here is the registry value I'm trying to target:
As seen in the picture it is located at HKEY_LOCAL_MACHINE\SOFTWARE\SolidWorks\SOLIDWORKS 2022\Setup\SolidWorks Folder.
I've tried to follow the instructions and have tried many iterations, with the following being the latest.
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SolidWorks Add-In" Language="1033" Version="1.0.0.0" Manufacturer="My Company" UpgradeCode="073e3b99-1977-4a3e-a4dc-0d61cc6ddbee">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Description="SolidWorks Add-In Installer" Manufacturer="My Company" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Feature Id="ProductFeature" Title="Installer" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<Property Id="MsiLogging" Value="v" />
<Property Id="SOLIDWORKSDIR">
<RegistrySearch Id="SolidWorksRegistry" Type="raw" Root="HKLM" Key="SOFTWARE\SolidWorks\SOLIDWORKS 2022\Setup" Name="SolidWorks Folder" />
</Property>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="SOLIDWORKSDIR" Name=".">
<Directory Id="My_Company" Name="My Company">
<Directory Id="INSTALLFOLDER" Name="SolidWorks Add-In" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="AutofacLibrary" Guid="3124c97d-079d-48fe-bc7c-e594bf49ae4a">
<File Id="AutofacDLL" Name="Autofac.dll" DiskId="1" Source="..\SolidWorksAddIn\bin\Release\Autofac.dll" KeyPath="yes" />
<File Id="AutofacPDB" Name="Autofac.pdb" DiskId="1" Source="..\SolidWorksAddIn\bin\Release\Autofac.pdb" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
This seems to completely ignore the registry value though and the install location is C:\My Company\SolidWorks Add-In
I can't figure out what needs to change. How am I targeting the registry value incorrectly or referencing the property incorrectly that isn't allowing the installer to place the installed files in the directory I want them to be in?
As per the comments above, the issue is that the registry key is in the 64-bit hive but the package was 32-bit. The fix is to either make the package 64-bit (so the searches look in 64-bit locations by default) or make the registry search 64-bit by adding the Win64='yes' attribute.

wix 3.8 silent install - ui level 2

I want to create a WIX Installer (3.8) that only installs silently.
I'm using the Wix file attached to demonstrate my issue.
At
UILevel=2
<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallExecuteSequence>
I'm setting the UI level to 2
According to:
msdn.microsoft.com/en-us/library/aa372096%28v=vs.85%29.aspx
then it's:
"
INSTALLUILEVEL_NONE 2 Completely silent installation.
"
So far so good. I can install the "product" which is nothing but an empty directory.
When I set the product's version to: Version="1.1.0.0" and want to do a major upgrade everything also works fine.
When I look at the program an feature "tool" from Microsoft
as shown here:
http://windows.microsoft.com/en-us/windows/uninstall-change-program#uninstall-change-program=windows-7
I see both versions (version 1.0.0.0 and 1.1.0.0) which is not what I expected the Wix installer should do.
When I remove
<InstallUISequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallUISequence>
<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallExecuteSequence>
from the Wix script, install Version 1.0.0.0 and later after changing the wix script to 1.1.0.0
and major upgrading again,
I only see 1 version (1.1.0.0) at the program an feature "tool" from Microsoft
( windows.microsoft.com/en-us/windows/uninstall-change-program#uninstall-change-program=windows-7 )
which is what I expect the windows installer should do.
So my question would be:
What is missing or wrong at the script
( that the program an feature "tool" from Microsoft shows 2 Versions after a major upgrade )
Wix script:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="SetupProject1" Language="1033" Version="1.1.0.0" Manufacturer="asdf" UpgradeCode="BE170BF6-0C06-4A50-B81B-CDF6609FAD5A">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" InstallPrivileges="limited" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." Schedule="afterInstallInitialize" />
<MediaTemplate />
<InstallUISequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallUISequence>
<InstallExecuteSequence>
<FindRelatedProducts Before="LaunchConditions">UILevel=2</FindRelatedProducts>
</InstallExecuteSequence>
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="test" Guid="D6527568-4C76-493B-AF1F-9E973723E773"
SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
Win64="no" Location="either">
<CreateFolder/>
<RemoveFolder Id="ProductComponents" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\MyFantasyCompany\MyApplicationName" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
First, there's no such thing as WiX script. WiX is not a imperative programming language, it's a declarative language.
Your major upgrade is failing because the condition on FindRelatedProducts is evaluating to false which means it can never detect the ProductCode of the previous MSI and remove it as part of the upgrade.
If you really want a silent install only, why not just omit a UI from the installer? Personally I have no idea why you are trying to do this and it doesn't follow established best practices.

WiX Installer InstallPrivelges="elevated" not working

When I run my installer I get the following issue.
I'm doing some custom actions which require to access the registry and I can only think that its because the WiX configuration doesn't make it request admin priveleges. I've looked at some posts on SO and tried to use.
InstallPriveleges="elevated"
within the package element however this does not make the installer have the admin shield nor request it therefore still producing the error.
Extra information about test project.
The name of my application is :WindowsFormsApplication33, the name of the custom action project is CustomAction1 and name of the Setup project is SetupProject1.
This is my current wix xml file.
<Package InstallerVersion="200" Compressed="yes" InstallPrivileges="elevated" InstallScope="perUser" />
<Binary Id="CustomAction1.CA.dll" SourceFile ="..\CustomAction1\bin\$(var.Configuration)\CustomAction1.CA.dll" />
<CustomAction Id="disableTaskManager"
Return="check"
Execute="immediate"
BinaryKey="CustomAction1.CA.dll"
DllEntry="disableTaskManager" />
<CustomAction Id="enableTaskManager"
Return="check"
Execute="immediate"
BinaryKey="CustomAction1.CA.dll"
DllEntry="enableTaskManager" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="SetupProject1" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<InstallExecuteSequence>
<Custom Action="disableTaskManager" Before="InstallFinalize" />
<Custom Action="enableTaskManager" After="InstallInitialize"><![CDATA[(NOT UPGRADINGPRODUCTCODE)]]></Custom>
</InstallExecuteSequence>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Form Test Application" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Guid="{EDA315F6-A115-4348-8607-981C252EA317}">
<File Source="$(var.WindowsFormsApplication33.TargetPath)" KeyPath ="yes" />
</Component>
<Component Guid="{E3182F61-F563-4C13-82B5-8CC39D9DB380}">
<File Source="$(var.CustomAction1.TargetPath)" KeyPath ="yes" />
</Component>
<Component Guid="{E4AF325E-B244-47F5-855A-5B40DBC425D2}">
<File Source="..\WindowsFormsApplication33\bin\Release\WindowsFormsApplication33.exe.config" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
Update : changing the InstallScope value from perUser to "perMachine" does make a UAC prompt however the DLL error still exists..
Your custom action is immediate, that means it will not run with elevation. It must be deferred to run with elevation. It's got nothing to do with WiX particularly, it's just that immediate custom actions run as the user but limited.
I struggled to get rid of the dll error however an alternative I found was to NOT use Custom Action and use the XML in the wix file to create the registry and then delete the key when uninstalling via the use of :
ForceDeleteOnUninstall="yes"
You have to use this in the
Example :
<!-- Register windows autostart registry -->
<Component Id="RegistryEntries" Guid="45C7AC46-1101-4301-83E1-D24392283A60">
<RegistryValue Type="string"
Name="FooStartup"
Value="[#FooMainApp]"
Root="HKLM"
Key="Software\Microsoft\Windows\CurrentVersion\Run"
Action="write"/>
</Component>
As found on : Registry change upon installing application C#
I really hope this helps someone new to WiX as it did to me.
Use these three attributes inside custom action tag.
<CustomAction ....
Execute="deferred"
Impersonate="no"
Return="ignore" />
These fields will make the custom action to run with admin priveleges.

Wix installer - cannot uninstall perUser package

After installation of perUser msi package I cannot uninstall it.
When selecting (Browse) package - that I installed - there is an error: 'selected package is not valid package for this product'.
Here's my code:
<?xml version='1.0'?><Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Id='a871a539-5954-44b7-810d-caed5d09e4c5' Name='x' Language='1033'
Version='1.1.0.0' Manufacturer='M' UpgradeCode='a871a539-5954-44b7-810d-caed5d09e4c5'>
<Package Description='x'
Comments='x'
Manufacturer='x' InstallerVersion='200' Compressed='yes' InstallScope='perUser' />
<Media Id='1' Cabinet='product.cab' EmbedCab='yes' />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='AppDataFolder' Name='AppData'>
<Directory Id='xFolder' Name='x' />
</Directory>
</Directory>
<Component Id='xComponent' Guid='a871a539-5954-44b7-810d-caed5d09e4c5'
Directory='xFolder'>
<RemoveFolder Id="Removex" On="uninstall" />
<!-- registry entry to be used as keypath -->
<RegistryValue Root="HKCU"
Key="Software\M\x"
Name="component.xcomponent.installed"
Type="integer"
Value="1"
KeyPath="yes"/>
<File Id='myFile' Name='myFile.txt' DiskId='1' Source='myFile.txt' />
... files here
</Component>
<Feature Id='xFeature' Title='x feature' Level='1'>
<ComponentRef Id='xComponent' />
</Feature>
Installation process is ok - no errors. Files are in correct place. Registry key is added.
What am I doing wrong?
Yes - as Wim Coenen said - that question helped me resolve problem.
However instead of executing steps in that question I cleaned registry.
The problem was that I installed this package many times changing GUID and other parameters, so there was quite a mess in registry. I searched registry by Manufacturer and Name.
After cleaning up everything was ok.

Features installed to different locations but referencing the same components

I have a product that consists of multiple features that can be installed to different locations e.g. Feature 1 is an executable installed in Program Files and Feature 2 is a website installed in wwwroot. However both Feature 1 and Feature 2 rely on many of the same dll's and hence require the components containing those dll's to be installed in 2 different locations depending on which Features are installed.
Is there a way to achieve this without defining every component twice?
To provide a further complete example of what I am trying to achieve, the following complete wxs file can be compiled using:
> candle.exe Foobar.wxs
> light.exe -ext WixUIExtension Foobar.wixobj
> msiexec /i Foobar.msi
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Name='Foobar 1.0'
Id='E578DF12-DDE7-4BC2-82CD-FF11862862D5'
UpgradeCode='90F09DD5-E01B-4652-8971-515997730195'
Language='1033'
Codepage='1252'
Version='1.0.0'
Manufacturer='Acme Ltd.'>
<Package Id='*'
Keywords='Installer'
Description="Acme 1.0 Installer"
InstallerVersion='100'
Languages='1033'
Compressed='yes'
SummaryCodepage='1252' />
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
<Property Id='DiskPrompt' Value="Acme 1.0 Installation" />
<Directory Id='TARGETDIR' Name='SourceDir'>
<!-- Directory 1 (Program Files) -->
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="PROGRAM_INSTALLDIR" Name="Acme" />
</Directory>
<!-- Directory 2 (wwwroot) -->
<Directory Id="Inetpub" Name="Inetpub">
<Directory Id="wwwroot" Name="wwwroot">
<Directory Id="WEBSITE_INSTALLDIR" Name="AcmeWebSite" />
</Directory>
</Directory>
</Directory>
<DirectoryRef Id='PROGRAM_INSTALLDIR'>
<Component Id="Component1" Guid="79EC9E0B-8325-427B-A865-E1105CB16B62">
<File Id="File1" Name="File1.txt" Source="File1.txt" />
</Component>
</DirectoryRef>
<DirectoryRef Id='WEBSITE_INSTALLDIR'>
<Component Id="Component2" Guid="702E6573-8FBC-4269-A58D-FD1157111F0F">
<File Id="File2" Name="File2.txt" Source="File2.txt" />
</Component>
</DirectoryRef>
<Feature Id="Feature.Program"
Title="My Program"
TypicalDefault="install"
Level="1"
ConfigurableDirectory="PROGRAM_INSTALLDIR" >
<ComponentRef Id="Component1"/>
<ComponentRef Id="Component2"/>
</Feature>
<Feature Id="Feature.Website"
Title="My Website"
TypicalDefault="install"
Level="1"
ConfigurableDirectory="WEBSITE_INSTALLDIR" >
<ComponentRef Id="Component1"/>
<ComponentRef Id="Component2"/>
</Feature>
<UIRef Id="WixUI_Mondo" />
<UIRef Id="WixUI_ErrorProgressText" />
</Product>
</Wix>
This will however result in ONLY File1.txt being installed in
C:\Program Files (x86)\Acme
and ONLY File2.txt being installed in
_C:\Inetpub\wwwroot\AcmeWebsite_
One solution is to define the components twice such as:
<DirectoryRef Id='PROGRAM_INSTALLDIR'>
<Component Id="Component1" Guid="79EC9E0B-8325-427B-A865-E1105CB16B62">
<File Id="File1" Name="File1.txt" Source="File1.txt" />
</Component>
<Component Id="Component2" Guid="702E6573-8FBC-4269-A58D-FD1157111F0F">
<File Id="File2" Name="File2.txt" Source="File2.txt" />
</Component>
</DirectoryRef>
<DirectoryRef Id='WEBSITE_INSTALLDIR'>
<Component Id="Component1.Web" Guid="397E93AA-32FB-425A-A783-386E0CCA2357">
<File Id="File1.Web" Name="File1.txt" Source="File1.txt" />
</Component>
<Component Id="Component2.Web" Guid="5C3AFF06-3623-4524-A90B-72B46DE5572A">
<File Id="File2.Web" Name="File2.txt" Source="File2.txt" />
</Component>
</DirectoryRef>
<Feature Id="Feature.Program"
Title="My Program"
TypicalDefault="install"
Level="1"
ConfigurableDirectory="PROGRAM_INSTALLDIR" >
<ComponentRef Id="Component1"/>
<ComponentRef Id="Component2"/>
</Feature>
<Feature Id="Feature.Website"
Title="My Website"
TypicalDefault="install"
Level="1"
ConfigurableDirectory="WEBSITE_INSTALLDIR" >
<ComponentRef Id="Component1.Web"/>
<ComponentRef Id="Component2.Web"/>
</Feature>
But then what happens if we add a third feature that is to be installed in another location? Do we then have to redefine every component again? With over 100 components, managing duplicate components will become a big job.
Any suggestions?
You are seeing a limitation in the Windows Installer. A Component can only be installed once via an MSI. Each Component can only be installed to a single Directory. To have the contents of a Component installed to two different locations, you either have to create another Component with the same content or try to use the CopyFile element to duplicate the content.
Probably not what you wanted to hear but that is the way the Windows Installer works.
Fortunately, if you chose to go with option 1, then WiX toolset will only compress the duplicated content across the Components once. Smart cabbing rocks!
I recommend creating a separate feature which contains only the common components. It shouldn't be installed by default. You can then create a custom action which marks this feature for installation only when one of your actual features is installed.
To mark the feature for installation you can use MsiSetFeatureState function:
http://msdn.microsoft.com/en-us/library/aa370387(VS.85).aspx
The custom action which does this can be conditioned with the feature action of your features:
http://msdn.microsoft.com/en-us/library/aa368561(VS.85).aspx
Features can reference a directory for Browse capability but that only means something if the components use directories that are that directory or a child of that directory. Otherwise the component will go to the directory specified. In other words, you could have INSTALLDIR for the feature and most components yet have ANOTHERDIR ( say [CommonFilesFolder]Company\Shared for another component and it will go there. That component can then belong to multiple features and you'll be ok.