In Wix, how can I avoid hardcoding a file source for a file that already exists in the installation directory? - wix

In my .wxs file, I have the following file declaration. This file already exists in the installation directory. It is not being copied from the source directory. I need to update it using util:XmlConfig during the install. The XmlConfig part is working.
<File Id="AppConfig" Name="Dynamics.exe.config" Source="C:\Program Files (x86)\Microsoft Dynamics\GP2010\Dynamics.exe.config" />
The problem is I can't assume the file is always going to exist in that same location. I'd really like to simply reference it like so:
<File Id="AppConfig" Name="[#INSTALLDIR]\Dynamics.exe.config" />
However, that fails with the following message:
> light.exe ....
The system cannot find the file 'SourceDir\....\[#INSTALLDIR]\Dynamics.exe.config'
How can I say "the file already exists in the installation directory, use that file during the installation, and do not validate for it now"?

Directories are available with bracket notation as though they were regular properties. If you don't need to install the Dynamics.exe.config but just access it with XmlConfig elements, you can simply reference that directory and don't need to bother with the File element:
<Component Id="Dynamics.exe.config" KeyPath="yes" Guid="*">
<util:XmlConfig Id="Dynamics.exe.config.XmlConfig1"
On="install"
Action="..."
File="[INSTALLDIR]\Dynamics.exe.config"
...
/>
<util:XmlConfig Id="Dynamics.exe.config.XmlConfig2"
On="install"
Action="..."
File="[INSTALLDIR]\Dynamics.exe.config"
...
/>
</Component>

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.

How to update INI file that is marked as read-only (WiX toolset)

I have a small installer project in Wix Toolset. One of the INI files I need to modify might be marked as read-only and the installer refuses to modify it.
Is there any way to force installer to do the INI modification? All I found was permission setting during file installation, however this file is not part of the installation.
My component looks like this:
<Component Id="FooBar.ini" Guid="GUID" KeyPath="yes" Permanent="yes">
<IniFile Id="FooBar.ini" Directory="FOOBARDIR" Name="FooBar.ini"
Action="addLine" Section="Foo" Key="Bar" Value="1" />
</Component>

How to declare virtual path in .wxs file?

I am quite new in creating setup project using .wxs file.I am using WIX 3.9. I want to change the physical path to virtual path in .wxs file.
Currently .wsx file is using physical path like this -
<Component Id="cmp2CB74B07C01493F593A258BAE09C0B1C" Guid="08CD4620-DE67-4C7A-A97A-212AB5BA5E52">
<File Id="filCF6108D60D7B1865907043E2ABFE30DF" KeyPath="yes" Source="C:\ProjectName\Client\Bin\AjaxControlToolkit.dll" />
</Component>
I want to use virtual path something like this -
<Component Id="cmp2CB74B07C01493F593A258BAE09C0B1C" Guid="08CD4620-DE67-4C7A-A97A-212AB5BA5E52">
<File Id="filCF6108D60D7B1865907043E2ABFE30DF" KeyPath="yes" Source="~\ProjectName\Client\Bin\AjaxControlToolkit.dll" />
</Component>
How could I do this in .wxs file? Please suggest.
Assuming you are already using heat to generate your components, you can specify a variable by using -var <VariableName>. According to the docs this will:
Substitute File/#Source="SourceDir" with a preprocessor or a wix variable (e.g. -var var.MySource will become File/#Source="$(var.MySource)\myfile.txt" and -var wix.MySource will become File/#Source="!(wix.MySource)\myfile.txt".
I use this by running the heat command in the post-build event of the original project, and passing in -var var.$(ProjectName).TargetDir. The resulting File will have Source="$(var.ProjectName.TargetDir)\whatever.dll". As long as ProjectName is added as a reference to the wix setup project then the variable will be resolved properly.

LGHT1076 / LGHT1076: Install a data file to localappdata

Using WiX, a file can be installed to ProgramFiles using the following:
<DirectoryRef Id="ApplicationBinDirectory">
<Component ...>
<File Id="..." KeyPath="yes" Source="..." />
</Component>
</DirectoryRef>
Now I want to do the same, but the target is a folder in local application data. The file really belongs there according to http://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
<!-- this is the folder in %LOCALAPPDATA% -->
<Directory Id="LocalAppDataFolder">
<Directory Id="ApplicationLocalAppDataDirectory" Name="my folder name"/>
</Directory>
<DirectoryRef Id="ApplicationLocalAppDataDirectory">
<File Id="fil" KeyPath="yes" Source="..." />
</DirectoryRef>
But I get the following error and warning now:
installer.wxs(63) : error LGHT0204 : ICE38: Component ApplicationConfiguration installs to user profile. It must use a registry key under HKCU as its KeyPath, not a file.
installer.wxs(64) : warning LGHT1076 : ICE91: The file 'fil' will be installed to the per user directory 'ApplicationLocalAppDataDirectory' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per
machine installation is desired.
Adding RegistryValue and RemoveFolder as I have to do it for start menu shortcuts doesn't change the message.
I'm kind of lost here. How do I install a file to local appdata? Please note that I want to install only 1 file there, in addition to the usual setup in program files.
This should help. It shows adding a registry key item to be the keypath:
http://nofoe.blogspot.com/2008/12/wix-it-must-use-registry-key-under-hkcu.html

WIX: copy file to custom dir in another partition

I need to install my app's files to usual location like C:\Program Files\MyApp
and also need to copy several of them into custom folder in another partition
(let's say D:\CustomFolder, it's allowed to hardcode it).
Install should be silent - no gui or wizard. And alose everything should be in one *.msi file.
I can do that via CustomActions, but elegant-declarative way is preferable.
Has anyone tried this before?
Thanks.
UPDATE:
Forgot to mention, that it's allowed for files that should be on separate partition to be in C:\Program Files\MyApp
Solved. The approach is:
Specify custom folder where file should be put:
<Property Id="MY_CUSTOM_DESTINATION" Value="D:\MyCustomFolder" />
Put <Copy ..> directive into <File ...> which should be copied
<DirectoryRef Id="MyAppFolderThatIsInProgramFiles">
<Component Id="MyComponent" Guid="some_guid">
<File Id="MyFileXml" Source="MyFile.xml" KeyPath="yes" >
<CopyFile Id="Copy_MyFileXml" DestinationProperty="MY_CUSTOM_DESTINATION"/>
</File>
</Component>
</DirectoryRef>
p.s. as a side-effect, file specified in <File Id="MyFileXml" ... /> will be put into both location: C:\Program Files\MyApp and D:\MyCustomFolder, but that's correct for my task.
It's against Windows Installer Best Practices to hard code directories. You can never assume there will always be a D: or even a C:. Still, customers have asked (demanded) that I install something to D:\FOO.
So, how to make the customer happy and have the install still "work" on that VM that doesn't have a D:? By redirecting the directory at install time with a custom action that only redirects it if D: is a fixed hard disk.
Also, while the CopyFile element is useful, it's not really needed because you can just author the files into components twice and smart cabing will make sure your MSI doesn't bloat up by having the File records point to the same entry in media \ cab storage.
You can simply describe your disk structure under the Directory Tag:
<Property Id="DRIVE_1" Value="c:\" />
<Property Id="DRIVE_2" Value="d:\" />
<Property Id="DRIVE_3" Value="e:\" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="DRIVE_1" />
<Directory Id="DRIVE_2" />
<Directory Id="DRIVE_3" />
</Directory>
I wouldn't advocate hardcoding, but you get the idea.