WiX Installer use RegistrySearch result for directory - wix

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.

Related

Wix create silent uninstall file

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.

How to set permissions to IniFile in WiX?

I have a component with an IniFile element in my WiX script. I need to set the read and write permissions for the Local Service to the resulting ini-file as the application runs under this account and must be able to read and write from/into the ini-file. The Permission(Ex) elements can't have IniFile as a parent so I don't see the native way in WiX to set permissions to an IniFile element, could anyone suggest a solution? The file is installed into a subfolder of CommonAppData.
The option to include a ready ini-file in the distribution and install it simply as a File is bad for me as the contents of the file depends on the individual installation (paths, computer name etc).
What version of Wix are you using? I am using Wix v3.9 and could get it to work. Well, I don't understand why the PermissionEx element would be concerned about the "Name" attribute of the File tab, especially when PermissionEx is itself nested/a child of the File tag.
Here is my sample project.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="INIFile" Language="1033" Version="1.0.0.0" Manufacturer="Test" UpgradeCode="4549f852-c012-4180-ab66-5d972f3faf53">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="INIFile" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="INIFile" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent">
<File Id="TestFile" KeyPath="yes" Source="E:\Learning\Test Projects\Files\test.txt" Name="test.txt">
<PermissionEx Id="Blah" Sddl="O-AB-C" />
</File>
<IniFile Id="TestIni" Action="addLine" Directory="INSTALLFOLDER" Key="Test" Name="Test" Section="Test" Value="Test"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>

Wix how to hide feature options (no subfeatures)

There is a similar question
Edit context menu (selectiontree) in customize dialog?
but the link in the accepted answer states:
"You cannot remove Entire feature will be installed on local hard drive from the options. It is displayed only when there are subfeatures and enables installation of the subfeatures as well as the feature itself as opposed from Will be installed on local hard drive which installs only the selected features and does not affect subfeatures."
However, I have no subfeatures. How to remove the Entire feature... option?
Here's the code below:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WixTestFeatureTree" Language="1033" Version="1.0.0.0" Manufacturer="TestManufacturer" UpgradeCode="bb04a635-6251-4fd5-8d2f-182d3441dc0a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<UIRef Id="WixUI_FeatureTree" />
<UIRef Id="WixUI_ErrorProgressText" />
<Feature Id="ExeFeature" Title="The EXE file" Level="1">
<Component Id="TheApp" Guid="*" Directory="INSTALLFOLDER">
<File Id="TestExe" Source="Test.exe" Vital="yes"></File>
</Component>
</Feature>
<Feature Id="PdfFeature" Title="The PDF file" Level="1">
<Component Id="ThePDF" Guid="*" Directory="INSTALLFOLDER">
<File Id="TestPDF" Source="Test.pdf" Vital="yes"></File>
</Component>
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WixTestFeatureTree" />
</Directory>
</Directory>
</Fragment>
</Wix>
It looks Windows Installer always displays Entire feature will be installed on local hard drive item even if there are no subfeatures. At least this item was present in all the cases that I tested where there were no visible subfeatures. It could also depend on the version of Windows Installer, I tested in Windows 7 with all the latest updates.
I've always thought Windows Installer doesn't display Entire feature will be installed on local hard drive item for a feature which has no subfeatures. Latest tests proved I was wrong.
You need to add the UI type in order to have a different UI in the installer.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WixTestFeatureTree" Language="1033" Version="1.0.0.0" Manufacturer="TestManufacturer" UpgradeCode="bb04a635-6251-4fd5-8d2f-182d3441dc0a">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<UI Id="MyWixUI_FeatureTree">
<UIRef Id="WixUI_FeatureTree" />
</UI>
<UIRef Id="WixUI_ErrorProgressText" />
<Feature Id="ExeFeature" Title="The EXE file" Level="1">
<Component Id="TheApp" Guid="*" Directory="INSTALLFOLDER">
<File Id="TestExe" Source="Test.exe" Vital="yes"></File>
</Component>
</Feature>
<Feature Id="PdfFeature" Title="The PDF file" Level="1">
<Component Id="ThePDF" Guid="*" Directory="INSTALLFOLDER">
<File Id="TestPDF" Source="Test.pdf" Vital="yes"></File>
</Component>
</Feature>
<UIRef Id="WixUI_Mondo"></UIRef>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WixTestFeatureTree" />
</Directory>
</Directory>
</Fragment>
</Wix>
add <UIRef Id="WixUI_Mondo"></UIRef> , also add reference to WixUIExtension.dll
each feature has **Level**attribute, level=1 meaning the feature will be installed, if you change the level for 1000 for example the user can pick in the custom dialog weather he wants to install this feature or not

Wix Install assemblies to GAC

i'm trying to install dlls to GAC, I get this error:
The assembly is not strongly named or is not signed with the minimal key length.
Code below. How do I get around this?
<Product Id="4C76EAE3-148A-4597-A994-0178693C5B25" Name="MySolutionInstaller" Language="1033" Version="1.0.0.0" Manufacturer="Me" UpgradeCode="a5e6cbeb-18be-4f7e-9ab5-f1adb1d947eb">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="MySolutionInstaller" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<!--<Directory Id="INSTALLFOLDER" Name="MyDLLCoreLibrary">-->
<Directory Id="ProductDirectory" Name="MySolutionInstaller">
<Directory Id="GAC" Name="GAC"/>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents">
<Component Id='DataLibraryGAC' Directory="GAC" Guid='a3b57886-4d27-4e4c-a28f-60a061cdd12d'>
<File Id='DataDLLGAC' Name='MyProject.Data.dll' Source='C:\projects\MyProject.Data\bin\Debug\MyProject.Data.dll'
KeyPath="yes" Assembly=".net" />
<!--<RemoveFile Id="RemoveDataDLLGAC" Name="My.Data.dll" On="uninstall" />-->
</Component>
</ComponentGroup>
</Fragment>
This error shows your assembly is not signing with strong name key. We need to sign the assembly using .snk file to install it in GAC. Check this to sign the assembly.
Another way around the error is to not put it in the GAC. Instead put your assembly where your EXE(s) can find it. The simpliest layout is all in one folder. But there are other options, such as automatically probing subfolders, as explained by How the Runtime Locates Assemblies.
An advantange of not installing into the GAC is that you can still design the installer to work without an administrator.

Install to GAC and register in registry

Okay, I'm obviously missing something. I'm trying to follow this in order to install to GAC and also make available for development. However, the only thing that's happening is that the DLL is being dropped into the ProductDirectory. It's not appearing in the GAC, nor is the registry key being added. How can I get this to work?
Relevant parts of Product.wxs below.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="Me.Common" Language="1033" Version="1.0.0.0" Manufacturer="Me" UpgradeCode="ea52947a-0980-435d-a8f5-280d3526cb90">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<!-- The feature to install. -->
<Feature Id="ProductFeature" Title="Me.Common" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="ProductDirectory" Name="Me.Common">
<Directory Id="GAC" Name="GAC" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents">
<Component Id="RunTime_Me.Common" Directory="GAC" Guid="E2B19C22-DC01-432D-85B0-0E4948F95A43">
<!-- Add to GAC. -->
<File Id="RunTime_Me.Common"
Source="$(var.Me.Common.TargetDir)$(var.Me.Common.TargetFileName)"
Assembly=".net"
KeyPath="yes" />
</Component>
<Component Id="DesignTime_Me.Common" Directory="ProductDirectory" Guid="C1BD8CD1-E834-49D5-B499-D9E313E70669">
<!-- Add locally. -->
<File Id="DesignTime_Me.Common"
Source="$(var.Me.Common.TargetDir)$(var.Me.Common.TargetFileName)"
KeyPath="yes" />
<!-- Add to registry so that Visual Studio can find it via Add Reference. -->
<Registry Id="Registry_DesignTime_Me.Common_AssemblyFolders"
Root="HKLM"
Key="SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\[ProductName]"
Value="[$DesignTime_Me.Common]"
Type="string" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
Turns out it was already installing in the GAC. I was looking in the wrong place; .NET now has a second GAC for 4.0 items (C:\Windows\Microsoft.NET\assembly). That leaves the registry key. I was getting a warning that Registry is deprecated, so I replaced that component with the below, but still not working:
<Component Id="DesignTime_Me.Common" Directory="ProductDirectory" Guid="C1BD8CD1-E834-49D5-B499-D9E313E70669">
<!-- Add locally. -->
<File Id="DesignTime_Me.Common"
Source="$(var.Me.Common.TargetDir)$(var.Me.Common.TargetFileName)"
KeyPath="yes" />
<!-- Add to registry so that Visual Studio can find it via Add Reference.
These require .NET v4.0 minimum. -->
<RegistryKey Root="HKLM"
Key="SOFTWARE\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx\[ProductName]">
<RegistryValue Type="string" Value="[$DesignTime_Me.Common]" />
</RegistryKey>
</Component>
</ComponentGroup>
It's all working; I was just looking in the wrong places.
The 4.0 GAC is at C:\Windows\Microsoft.NET\assembly.
The registry key is being placed in SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319\AssemblyFoldersEx\[ProductName] because the installer is 32-bit.
Since at least one of your files is apeparing, I would guess that you are not running elevated. Try adding InstallPrivileges="elevated" to your package element.
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated" />