Bind FileVersion to property in WiX - wix

As for binding the AssemblyVersion of a specific DLL to WiX File Version, is basically easy:
<Product Id="*"
Name="My Application"
Language="1033"
Version="!(bind.FileVersion.MyDll.dll)"
Manufacturer="My Company"
UpgradeCode="E7A0C56F-160B-4C67-9AAC-2FF69630EAF9">
Is there any way that the same can be achieved with Properties in WiX. Like this:
<Property Id="VERSION">
<![CDATA[!(bind.FileVersion.MyDll.dll)]]>
</Property>
I need to update an XML file during installation, with the same version number as the one in the specific DLL. Any suggestions?

You should have a look at the XmlFile Element. It allows you to set values/attributes:
<Component Id="webconfig" Guid="PUT-YOUR-GUID-HERE" NeverOverwrite="yes" Win64="yes">
<File Id="web.config" Source="$(var.bind.ProjectDir)\web.config" KeyPath="yes" />
<util:XmlFile Id="web.config.VersionInfo" File="[#web.config]" Action="setValue" PreserveModifiedDate="yes" ElementPath="//configuration/appSettings/add[\[]#key='VersionInfo'[\]]" Name="value" Value="[VERSION]" Sequence="1" />
</Component>

Related

Wix Toolkit 3.11 util namespace fails to load when building

I am trying to build an installer with Wix 3.11.2 in Visual Studio 2019. I have the extension installed and the toolkit.
I want to use the XmlFile tag in the util namespace to modify the app.config of my installed application.
I have added a reference to C:\Program Files (x86)\WiX Toolset v3.11\bin\WixUtilExtension to the installer project.
I have added the util namespace to the Product.wxs
The xmlnamespace is recognized since I get intellisense etc.
However when building I get the error error CNDL0005: The Fragment element contains an unexpected child element 'util:XmlFile'
This is my Product.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="DBDA892E-D414-44E9-9F5E-49DCD25E209B" Name="TestWixError" Language="1033" Version="1.0.0.0" Manufacturer="Test" UpgradeCode="41e16593-71c1-4516-8ec3-bc8f4911e3f1">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="TestWixErrorSetup" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="TestWixErrorSetup" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="MainExecutable" Guid="EA05AA88-F299-4EC2-A64A-4ADAB863C4AC">
<File Id="MainExecutable" Source="$(var.TestWixError.TargetPath)"/>
</Component>
<Component Id="MainPdb" Guid="8ACB76F7-BB83-4EA6-9F58-12CD015E88EC">
<File Source="$(var.TestWixError.TargetDir)$(var.TestWixError.TargetName).pdb" />
</Component>
<Component Id="MainConfig" Guid="39BAFF61-BA1A-42C3-9290-67019F6A6257">
<File Source="$(var.TestWixError.TargetPath).config" />
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<Property Id="HELLO" Value="Hello from install"/>
<util:XmlFile
Id="UpdateHello"
Action="setValue"
File="$(var.TestWixError.TargetPath).config"
SelectionLanguage="XPath"
Permanent="yes"
ElementPath="/configuration/appSettings/add[\[]#key='Hello'[\] ]/#value"
Value="[HELLO]" />
</Fragment>
</Wix>
The visual studio project is just a .net 4.7.1 console app that displays the value from Hello from the appsettings on the console.
The WixUtilExtension.dll is included in the call to candle.exe as you can see in this commandline (some parts redacted):
C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe -dDebug -d"DevEnvDir=C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\\" -d"SolutionDir=C:\Users\---\Documents\Projecten\---\TestWixError\\" -dSolutionExt=.sln -dSolutionFileName=TestWixError.sln -dSolutionName=TestWixError -d"SolutionPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError.sln" -dConfiguration=Debug -dOutDir=bin\Debug\ -dPlatform=x86 -d"ProjectDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\\" -dProjectExt=.wixproj -dProjectFileName=TestWixErrorSetup.wixproj -dProjectName=TestWixErrorSetup -d"ProjectPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\TestWixErrorSetup.wixproj" -d"TargetDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\bin\Debug\\" -dTargetExt=.msi -dTargetFileName=TestWixErrorSetup.msi -dTargetName=TestWixErrorSetup -d"TargetPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixErrorSetup\bin\Debug\TestWixErrorSetup.msi" -dTestWixError.Configuration=Debug -d"TestWixError.FullConfiguration=Debug|AnyCPU" -dTestWixError.Platform=AnyCPU -d"TestWixError.ProjectDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\\" -dTestWixError.ProjectExt=.csproj -dTestWixError.ProjectFileName=TestWixError.csproj -dTestWixError.ProjectName=TestWixError -d"TestWixError.ProjectPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\TestWixError.csproj" -d"TestWixError.TargetDir=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\bin\Debug\\" -dTestWixError.TargetExt=.exe -dTestWixError.TargetFileName=TestWixError.exe -dTestWixError.TargetName=TestWixError -d"TestWixError.TargetPath=C:\Users\---\Documents\Projecten\---\TestWixError\TestWixError\bin\Debug\TestWixError.exe" -out obj\Debug\ -arch x86 -ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUtilExtension.dll" Product.wxs
Things I have tried so far:
Removing the reference, restarting visual studio re-adding the reference
Moving the WixUtilExtension.dll to c:\temp\bin (with all other wix binaries included) and referencing from there.
Moving the WixUtilExtension.dll to the same location as the Product.wxs and referencing from there.
Looking at the WixUtilExtension.dll with ILSpy to verify that it contains a reference to the http://schemas.microsoft.com/wix/UtilExtension namespace (it does in resources it contains an xsd with this namespace)
Any suggestions to get this working are welcome.
Ok,
I am here to answer my own question, hopefully to help someone else in the future.
The util:XmlFile tag needs to be inside a Component tag.
So the fixed fragment looks like this:
<Fragment>
<Property Id="HELLO" Value="Hello from install"/>
<Component Id="TestConfigComponent" Directory="INSTALLFOLDER">
<util:XmlFile
Id="UpdateHello"
Action="setValue"
File="$(var.TestWixError.TargetPath).config"
SelectionLanguage="XPath"
Permanent="yes"
ElementPath="/configuration/appSettings/add[\[]#key='Hello'[\] ]/#value"
Value="[HELLO]" />
</Component>
</Fragment>

Remove folder in roaming using wix3.10 installer

When uninstalling my application, I'd like to delete a folder that was added by the application.It seems like the uninstaller removes only the directories and files that were originally installed from the MSI file. How do I delete application created folder?
Following the instructions on this link:
use WixUtil extensions:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
>
then read the Folder path previously stored in the registry:
<Property Id="APPLICATIONFOLDER">
<RegistrySearch Key="SOFTWARE\$(var.Manufacturer)\$(var.SkuName)" Root="HKLM" Type="raw" Id="APPLICATIONFOLDER_REGSEARCH" Name="Path" />
</Property>
Make sure the following component is included in you installer scripts:
<DirectoryRef Id="APPLICATIONFOLDER">
<Component Id="CleanupMainApplicationFolder" Guid="*">
<RegistryValue Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.SkuName)" Name="Path" Type="string" Value="[APPLICATIONFOLDER]" KeyPath="yes" />
<!-- We need to use APPLICATIONFOLDER variable here or RemoveFolderEx
will not remove on "install". -->
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
</Component>
</DirectoryRef>
Use the WiXUtil extension when you call both candle and light: -ext WixUtilExtension

How to write production version to registry

I want to write the installed version to registry using WiX. Here is the WiX code of mine:
<Product Id="B20795DC-5462-4DE6-B629-8C034D114D3C" Name="ProductName" Language="1033" Version="1.1.3" Manufacturer="Corp" UpgradeCode="8f5c57ff-71fe-4fc6-9400-9bbbb76b4262">
....
<Component Id="ProgramRegistry">
<RegistryKey Id="RegInstallDir" Root="HKLM" Key="Software\[Manufacturer]\[ProductName]" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="InstallVersion" Value="[Version]"/>
</RegistryKey>
</Component>
It creates a key named "InstallVersion" but the value is empty.
My question is how to write the product version into registry, the expected value should be the same as the version attribute in <Product> tag. (1.1.3)
The ProductVersion property contains the value you're looking for.
You can use ProductVersion property, the way #Stephen suggests. Alternatively, you can use the following approach:
define the version in a WiX variable
reference this variable in both Product element and RegistryValue element
set the product version in your build script and pass it to WiX compiler
Hence, your sample might look like this:
<Product Id="B20795DC-5462-4DE6-B629-8C034D114D3C" Name="ProductName" Language="1033" Version="$(var.Version)" Manufacturer="Corp" UpgradeCode="8f5c57ff-71fe-4fc6-9400-9bbbb76b4262">
....
<Component Id="ProgramRegistry">
<RegistryKey Id="RegInstallDir" Root="HKLM" Key="Software\[Manufacturer]\[ProductName]" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="InstallVersion" Value="$(var.Version)"/>
</RegistryKey>
</Component>
</Product>
And somewhere in the build script (let's pretend, it is NAnt):
<candle out="${build.fodler}" rebuild="true" extensions="${build.extensions}" exedir="${wxs.dir}">
<defines>
...
<define name="Version" value="1.1.3" />
...
</defines>
<sources basedir="${paths.wxs}">
<include name="**.wxs"/>
</sources>
</candle>

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" />

How to write Product Id in registry in wix

My requirement is blow.
I need to write the Product Id in registry while install the setup.
I have the below code for Product Id.
<Product Id="{CEEE7807-F6D7-43F6-A206-110B9E25AC9C}"
Name="Sample installer"
UpgradeCode="{BFBD4770-8C5D-4A53-BA07-EF52401F0CB4}"
Language="1033"
Version="$(var.ProductVersion)"
Manufacturer="My company.">
I have below code for write Registry. I want to pass the product Id value here.
<Component Id="registry_values" Guid="{11FB6C4C-3C90-4F46-B0D2-BB95150F60E6}">
<RegistryValue
KeyPath="yes"
Root="HKCU"
Key="Software\MyProduct\Myfolder\SampleFolder\Product"
Value="[Product Id]"
Type="string" />
</Component>
Please help me to solve this problem.
Somewhat confusingly, the Id attribute of the WIX Product element maps to the Windows Installer ProductCode property.
<Component Id="registry_values" Guid="{11FB6C4C-3C90-4F46-B0D2-BB95150F60E6}">
<RegistryValue
KeyPath="yes"
Root="HKCU"
Key="Software\MyProduct\Myfolder\SampleFolder\Product"
Value="[ProductCode]"
Type="string" />
</Component>