Conditionally install files based on Command Line Argument during WIX Install - properties

I am wanting to install files during a wix install conditionally whether a command line parameter has been set
e.g. I have the following file, which only installs if a DEBUG flag has been set
<Component Id="file.pdb" Guid="SOME-GUID">
<Condition>DEBUG</Condition>
<File Id="file.pdb" Source="file.pdb" KeyPath="yes" Vital="no" />
</Component>
I have added the DEBUG property and read it in from the command line. The File never installs though, I am perplexed as to why?

Solved the issue. Below is an explanation of what I was doing wrong and what I did to solve it
I had created an installer (.msi) and was using the following cmd line args to start it up
msiexec -i prog.msi DEBUGPROPERTY=True
I had several merge modules with components which would install depending on whether this property was set which were getting the property injected into them like so...
<Merge
Id="SomeID"
Language="1033"
SourceFile="Module.msm"
DiskId="1">
<ConfigurationData
Name="debugProperty"
Value="[DEBUGPROPERTY]" />
What I was missing was in the merge modules (.msm) i needed the following code
<Configuration Name='debugProperty' Format='Text' DefaultValue='[DEBUGPROPERTY]'/>
<Substitution Table='CustomAction' Row='setDebugProperty' Column='Target' Value='[=debugProperty]'/>
<CustomAction Id='setDebugProperty' Property='DEBUGPROPERTY' Value='[DEBUGPROPERTY]'/>
<InstallExecuteSequence>
<Custom Action='setDebugProperty' Before="LaunchConditions">1</Custom>
</InstallExecuteSequence>
This allowed me to access the property DEBUGPROPERTY inside this module so i could restrict whether a file was installed at install time or not, like so
<Component Id="File.pdb" Guid="SOME-GUID">
<Condition>DEBUGPROPERTY</Condition>
<File Id="File.pdb" Source="File.pdb" KeyPath="yes" Vital="no" />
</Component>
This now works, and allows me to install .pdb files during an install if i include this argument.

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 use selfextract files in a wix install

I am really new using WIX, my only experience to build a complete install was with INNO, and WIX has been decided the way to go for an MSI
The installation includes a bunch of examples and templates, 427 files, which seems crazy to enumerate even with an utility like HEAT.EXE
So we went for a self-extracting utility. WIX install includes this custom utility and the compressed cabinet file, and then that extracts files and folders via custom action.
Problem is when we try to delete the compressed file and the extractor utility. I haven't found the way to delete them after the extraction takes place. RemoveFile seems to not work, and deleting the file within the extraction utility fires the self-healing mechanism in every run of the application.
Leaving the files in the install is dangerous, it is 200MB and it would reset all the installed examples if user runs the self-extraction utility by accident.
If it is of use, the WIX snippet in charge of this is like that:
<Fragment>
<ComponentGroup Id="App_Files">
<Component Id="cmp_Files_Dat" Directory="INSTALLCOMMONFOLDER" Guid="{8BFED6C2-4D4F-48BB-xxxx-C171F624C90B}">
<File Id="fil_Files_Dat" Source="appfiles\files.dat" />
<RemoveFile Id="rem_Files_Dat" Name="files.dat" On="install" />
</Component>
<Component Id="cmp_UnpackFiles_exe" Directory="INSTALLCOMMONFOLDER" Guid="{5722B5E0-C6E8-4C71-yyyy-61EC0ACA0D72}">
<File Id="fil_UnpackFiles_exe" Source="appfiles\UnPackFiles.exe" Checksum="yes" />
<RemoveFile Id="rem_UnpackFiles_exe" Name="UnPackFiles.exe" On="install" />
</Component>
</ComponentGroup>
<CustomAction Id="action_UnPackFiles" FileKey="fil_UnpackFiles_exe" ExeCommand="[INSTALLCOMMONFOLDER]" Execute="commit" Return="check" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="action_UnPackFiles" After="InstallFiles" > NOT (REMOVE="ALL") </Custom>
</InstallExecuteSequence>
</Fragment>
The net result of the code above leaves the files, does not remove them.
Thanks in advance
Josep

Wix IniFile error on Uninstall

I'm using wix IniFile element to edit ini file on install. When I try to uninstall i get error 2343:
Начало действия 12:37:47: RemoveIniValues.
MSI (s) (7C:BC) [12:37:47:264]: Note: 1: 2343
DEBUG: Error 2343: Specified path is empty.
My wxs with ini editing is as follows:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="miktex_config_path" Hidden="yes"/>
<SetProperty Id="miktex_config_path" Value="[INSTALLLOCATION]miktex\miktex\config" After="InstallFiles" Sequence="execute">Not Installed</SetProperty>
<DirectoryRef Id="dirC060208F28327102C690BFF33C18B6C4">
<Component Id="miktex_config_file" Guid="4B9400C2-7EEF-4233-881D-5DFE6F80BB5B">
<CreateFolder />
<IniFile Directory="miktex_config_path" Id="common_install_path" Name="miktexstartup.ini" Action="addLine" Key="CommonInstall" Value="[INSTALLLOCATION]miktex" Section="Paths"/>
<IniFile Directory="miktex_config_path" Id="common_data_path" Name="miktexstartup.ini" Action="addLine" Key="CommonData" Value="[CommonAppDataFolder]miktex_data" Section="Paths"/>
<Condition><![CDATA[Not Installed]]></Condition>
</Component>
</DirectoryRef>
</Fragment>
</Wix>
Why doesn't uninstaller take into account my condition element?
How can I force installer to ignore ini file editing during uninstall?
The condition is against the component, however the action that is running is RemoveIniValue. You can surpress this action by overriding InstallExecuteSequence as follows:
<InstallExecuteSequence>
<RemoveIniValues Suppress="yes" />
</InstallExecuteSequence>
It depends on the task you pursue. If you need to prevent INI value removal at all then suppressing the RemoveIniValues in the InstallExecuteSequence is the way to go as suggested by David Martin. However, that suppression (NO MATTER what you put as a condition for that), prevents the INI entry removals and for install and for uninstall (again, condition doesn't work, don't even try to put condition to suppress on uninstall only). But if you need to allow INI entry/tag removals during the install (IniFile declaration with remove action) but at the same time you need to prevent the rest of your INI settings from removal during the uninstall, then simply mark the Component where you keep your IniFile declarations as Permanent="yes". In that case your INI settings will not be removed on uninstall and your declarations to remove particular INI settings on install will work, And forget about the RemoveIniValues suppression at all.

WiX CopyFile/Directory Path Unavailable During Patch

I have a WiX installer (say at 10.0) that copies some files. Everything with the file copy works fine. I am trying to create a patch from that version. Whenever the patch (10.1) is run, and the previous 10.0 install had to copy some of these files, I receive the following area while running the repair:
"The specified path [Path] is unavailable."
I have checked, and the specified path IS available. The files that were copied into are there. Further, the source data directory from which the files were copied from in the 10.0 install are also there.
There are other directories into which other files are copied. I am not sure if they would also have the error, and I simply have not seen it yet.
What could be going wrong?
Here is my .wxs code, which is the same in both the original install and the patch:
<DirectoryRef Id="SAVEDDBFOLDER">
<Component Id="SavedDBVDirectory" Guid="xxx">
<CreateFolder>
<Permission User ="[WIX_ACCOUNT_ADMINISTRATORS]" GenericAll="yes"/>
<Permission User ="[WIX_ACCOUNT_USERS]" GenericAll="yes"/>
</CreateFolder>
</Component>
</DirectoryRef>
<CustomAction Id="SetOldDBVWFiles"
Property="OLDDBVWFILES"
Value="[PATHTOOLDVER]Saved DB Files"/>
<DirectoryRef Id="SAVEDDBFOLDER">
<Component Id="CopyOldDataBVFiles" Guid="yyy">
<CopyFile Id="CopyOldDBVWFiles"
Delete="yes"
SourceProperty="OLDDBVWFILES" DestinationProperty="SAVEDDBFOLDER" SourceName="*"/>
<Condition>
<![CDATA[(NOT Installed) AND (NOT REMOVE) AND (PREVIOUSVERSION << "8." OR PREVIOUSVERSION << "7.")]]>
</Condition>
</Component>
</DirectoryRef>
<!--This custom action runs in 10.0 install-->
<!--PREVIOUSHYVERSION is set for 10.0; it is not for 10.1-->
<CustomAction Id="SetOldDBVWFilesHy"
Property="OLDHYDBVWFILES"
Value="[PATHTOOLDAD]Saved DB Files"/>
<DirectoryRef Id="SAVEDDBFOLDER">
<Component Id="CopyOldHyDatabusViewerFiles" Guid="zzz">
<CopyFile Id="CopyOldHyDBVWFiles"
Delete="yes"
SourceProperty="OLDHYDBVWFILES" DestinationProperty="SAVEDDBFOLDER" SourceName="*"/>
<Condition>
<![CDATA[(NOT Installed) AND (NOT REMOVE) AND (PREVIOUSHYVERSION << "4.")]]>
</Condition>
</Component>
</DirectoryRef>
Ok, I figured this one out. From the log files (msiexec /L*V "[log file]"), I discovered that one of the path variables -- "PATHTOOLDAD," and no, it's not a path to Dad's tools -- was not set in the patch. It shouldn't have mattered, as this property is only used in the initial install and not at all in the patch, but it had to be set to something. I added the option "PATHTOOLDAD=[whatever]" to the call to msiexec to set the property, and voila, it worked.
msiexec /i [MSP Patch File] PATHTOOLDAD=[path of old program that was removed]

Files not installed when executing custom action in WIX

I am writing a WXS file for a package I want to install. For the sake of simplicity, let's say I want to install 1 file and then I want to execute a command against it (in my case, it is a public GPG key and I want to import it after the installation is done). Here are the relevant parts of my WXS file:
<CustomAction Id="ImportKey" Directory="INSTALLDIR"
ExeCommand="[SystemFolder]cmd.exe /C gpg --import keyfile.key"
Return="check" />
<!-- Install file keyfile.key into C:\GnuPG -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLDIR" Name="GnuPG">
<Component Id="GnuPGConfiguration" Guid="E9469F1C-A875-1014-A3B3-DEF3264B13C4">
<File Name="keyfile.key" Id="KeyfileKey" />
</Component>
</Directory>
</Directory>
<Feature Id="GnuPGConfiguration" Level="1" Title="GnuPG Configuration">
<ComponentRef Id="GnuPGConfiguration" />
</Feature>
<!-- Run custom action after files are installed -->
<InstallExecuteSequence>
<Custom Action="ImportKey" After="InstallFiles">NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>
I can successfully build the MSI. When installing, I use msiexec and turn on logging. There it says that installation fails on the custom action and the correct command is found in the log. Running it manually works. If I comment out execution of the command, the file is installed in the correct location (C:\GnuPG\keyfile.key exists after installation).
Instead of running my GPG command, I tried running dir ant redirected its output to a file. Viewing it, I can see that keyfile.key is not among the files in C:\GnuPG. It seems that the command is run before the file is installed.
Any ideas on what I am doing wrong?
You need to read and understand:
Installation Phases and In-Script Execution Options for Custom Actions in Windows Installer
You will find yourself considering needing
<CustomAction ... Execute="deferred" and Impersonate="no" ... />
Also you are likely to need to qualify the location of the .key file as your current directory isn't going to be what you think it is.