WIX Installer: Updating existing value in config file - wix

I am new to Wix and up till now I was able to manage it but now I want to update existing value of a Sub node from a config file. Below is my code to update it. But I get the error: failed to find the node.
<Component Id="ServiceIPAndPortSave" Guid="*" Directory="INSTALLFOLDER">
<CreateFolder/>
<util:XmlConfig
Id="UpdateIP"
On="install"
File="[INSTALLFOLDER]ProjectName.exe.config"
Action="create"
Node="value"
ElementPath="//configuration/userSettings/ProjectName.My.MySettings/setting[\[]#name='IPAddres'[\]]/#value"
Value="[SERVICEIP]"
/>
</Component>
And below is the format for my config file:
<configuration>
<userSettings>
<ProjectName.My.Settings>
<setting name="IPAddres" serializeAs="String">
<value>127.0.0.1</value>
</setting>
</ProjectName.My.Settings>
</userSettings>
</configuration>

Your XPATH expression is incorrect, you have two problems:
Your reference to the ProjectName.My.Settings element is invalid, you are using ProjectName.My.MySettings.
Your reference to the value element is invalid, you are using attribute notation.
And while not incorrect, you are rooting the search from anywhere by using // at the start of your query.
Try:
/configuration/userSettings/ProjectName.My.Settings/setting[\[]#name='IPAddres'[\]]/value

Related

How to modify the component .xml file with utils:XmlFile using WIX?

I am trying to create an installer which also installs the xml-file depending on input values, entered in separate dialog. Here
</Component>
<Component Id="ConfigXMLDocument">
<File Id ="Config" KeyPath="yes" DiskId="1" Vital ="yes" Source="$(var.Server.ProjectDir)config.xml"/>
<CreateFolder Directory="INSTALLFOLDER">
<util:PermissionEx User="Users" ChangePermission="yes" GenericAll="yes"/>
</CreateFolder>
<util:XmlFile ElementPath ="root/Server/servername" File ="[INSTALLFORDER]config.xml" Sequence="1" Id ="SERVERNAME"
Action ="setValue" Value ="THIS VALUE IS NOT BEING SET" SelectionLanguage="XPath"/>
<util:XmlFile ElementPath ="root/Server/listenport" File ="[INSTALLFORDER]config.xml" Sequence="2" Id ="PORT"
Action ="setValue" Value ="THIS ONE EITHER"/>
</Component>
The problem is that there are no errors and all the paths are resolved correctly, but the installed file remains the same as original.
If I try to change any other XML-file, It works, but not the one installed.
I found simmilar issues online, but no answers fixed mine.
Is it possible that XmlFile is just changing file before file is installed? And what else can cause such problem?
It appeared to be not one, but two issues.
The first one was to use FIle ID instead of path, so I replaced this
File ="[INSTALLFORDER]config.xml"
with this:
File ="[#Config]"
But It still didn`t work, during the installation appeared an error that the installer cannot find the file config.xml, so i changed the InstallExecuteSequence to this:
<InstallExecuteSequence>
<Custom Action="SchedXmlFile" After="InstallFiles" />
</InstallExecuteSequence>
UPD. This still did not work fine. WIX could not open the file with error:
Failed to open XML file path/config.xml, system error: -2147024786
The error appeared to be that wix cannot recognize the BOM in the XML file for some reason:
<?xml version"1.0" encoding="UTF-8" ?>
So i just removed it.
Hope this helps.

Migrating from WiX 3.10 to WiX 4.0: unhandled extension element

I'm migrating from WiX Toolset 3.10 to 4.0-pre. Updating namespaces went ok, but I'm still getting some errors in my NAnt build log.
I have Installer.wxs file:
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<Product ...>
<DirectoryRef Id="FolderCommon">
...
<Component Id="Registration_Component_12" Guid="..." KeyPath="yes">
<?include VS2012Package.wxi.bak?>
...
</Component>
...
</DirectoryRef>
...
</Product>
Where VS2012Package.wxi.bak file is generated via RegPkg.exe:
<Include>
<Registry Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\11.0\InstalledProducts\VsPackage">
<Registry Name="Package" Value="..." Type="string" />
<Registry Name="UseInterface" Value="1" Type="integer" />
</Registry>
...
And my build fails with errors like this:
[exec] ...\Installer\VS2012Package.wxi.bak(3) : error CNDL0200 : The Component element contains an unhandled extension element 'Registry'. Please ensure that the extension for elements in the '' namespace has been provided.
I tried to add namespace 'http://wixtoolset.org/schemas/v4/wxs' to "<Include>" tag in VS2012Package.wxi.bak using external script before building, but errors just changed to error CNDL0005 : The Component element contains an unexpected child element 'Registry'
Thanks for any help!
The Registry element was deprecated in WiX v3.x and is obsoleted in WiX v4.x. Use RegistryValue instead.

Using property in File element's Source property in WiX

I am trying to use Property value in Source attribute of File element, but getting this error:
error LGHT0103 : The system cannot find the file '[MYPROPERTY]'
Here is how property defined and used:
<Property Id="MYPROPERTY" Secure="yes" Value="myfile.xml" />
...
<File Id="MyFileId" Name="myfile.xml" Source="SubFolder\[MYPROPERTY]" KeyPath="yes" />
What I am doing wrong?
The property defined via the property-Tag creates a public property in the MSI-Package which is a Windows Installer concept.
You are refering to this variable in the Source-Attribute of the File-Tag but that isn't the way you can use this property. You can only use them at runtime (e.g. to use them in Registry-Keys you create during the installation) but the Source-Attribut is resolved via compile-time of the package.
The Source-attribut of the File-Tag requires a path to variable that points to a location on the developer machine.
I assume you are looking for Wix precompiler directives:
<?define MyProperty = "C:\myfile.xml" ?>
<File Id="MyFileId" Name="myfile.xml" Source="$(var.MyProperty)" KeyPath="yes" />

Using WiX, how to skip a component when a certain registry key does not exist?

I want to copy some files into a directory in another product's installation tree, but only if that product is installed. So I figured I could set a property based on a registry search to find that product's installation root. Then I could use the property in a condition element on the component element.
Here is my code. For some reason, I am getting an error when the other product is not installed and the registry search comes up empty since the registry key will not be found.
<Property Id="PRODUCTPATH">
<RegistrySearch Id="PRODUCTPATH" Root="HKLM" Key="_MY_KEY_" Name="_MY_NAME_" Type="raw" />
</Property>
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch"/>
<Component Id="CommonDLLs" Guid="_MY_GUID_" Directory="INSTALLLOCATION">
<Condition>PRODUCTPATH</Condition>
<RegistryValue Id="_MY_ID_" Root="HKLM" Key="_MY_KEY_2" Name="Installed" Value="1" Type="integer" KeyPath="yes" />
<CopyFile Id="myfile1.dll" FileId="myfile1.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile1.dll"/>
<CopyFile Id="myfile2.dll" FileId="myfile2.dll" DestinationProperty="PRODUCTPATH" DestinationName="myfile2.dll"/>
</Component>
Try to use the util:RegistrySearch instead of RegistrySeach
This element comes with Util Extension. Check here if you don't know how to use extensions.
The util:RegistrySearch has an attribute (Result) for only checking if the key exists or not.
It would be like that:
<util:RegistrySearch
Id="PRODUCTPATH"
Variable="PRODUCTPATH"
Root="HKLM"
Key="_MY_KEY_"
Format="raw"
Result="exists">
Actually, all you have to do is add a condition to the SetProperty element like this:
<Property Id="PRODUCTPATH">
<SetProperty Id="PRODUCTBINPATH" Value="[PRODUCTPATH]\BIN" After="AppSearch">PRODUCTPATH</SetProperty>

How do i override a WixVariable from the nant light task

In my Product.wxs file I have the following element:
<WixVariable Id="MySourceDir" Overridable="yes" Value="C:\somePath\files\"/>
then in a heat generated wxs file I have something along the lines of:
<Fragment>
<ComponentGroup Id="FunctionalLibs">
<Component Id="cmp3A42AC690DA7590004EC5796B1C6BA95" Directory="dir5DCBEA4AA069AE7BD92B4A3EA9C5EC79" Guid="{8FD7F7BF-68C1-492C-8F29-8E3003A6F441}">
<File Id="fil007BA1D3A56EDEA1D669D51D8C61F518" KeyPath="yes" Source="!(wix.MySourceDir)\file1.dll" />
</Component>
</ComponentGroup>
</Fragment>
in my nant build file I have
<light exedir="${wix.dir}"
out="${output.dir}\PluginInstaller.msi"
cultures="en-us"
rebuild="true"
suppresspdb="true">
<sources basedir="${release.dir}\obj\\${configuration}">
<include name="*.wixobj" />
</sources>
</light>
How do I set the wix.MySourceDir value from the light task?
As described in the NAnt Task Reference for Light, you can add additional arguments to Light.exe using the <arg> tag. The command line reference for light.exe says we use -d to define WixVariables, so:
<light exedir="${wix.dir}"
out="${output.dir}\PluginInstaller.msi"
cultures="en-us"
rebuild="true"
suppresspdb="true">
<sources basedir="${release.dir}\obj\\${configuration}">
<include name="*.wixobj" />
</sources>
<arg line="-dMySourceDir=C:\somePath\files\" />
</light>
That should do the trick. However, perhaps the simpler, more supported, and more common way of defining a source directory like you're doing is using a preprocessor variable. The Candle Task supports them directly using the <defines> tag and the only change to your source code would be to change Source="!(wix.MySourceDir)\file1.dll" to Source="!(var.MySourceDir)\file1.dll".