WiX CopyFile/Directory Path Unavailable During Patch - wix

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]

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

How to create msi installer which can install file located near by it?

How to create msi installer which can install file located near by it or fetch this file over http?
We want to create an msi installer with wix toolkit 3.9 that should distribute our virtual machine (size is bigger than allowed in cab files), hypervisor, register(unregister) powershell scripts and something else.
We cannot create MSI with big file.
I see two approaches:
We can put virtual machine image located near by msi installed and programming this installer to install image if it exists near by it.
d:> dir
myapp.msi
vm.vdi
We can agree with client that he must put vm image located near the msi installer manually, before run it.
Download this vm image with http. What are the options for this?
How I can do this ?
I do this like this:
<!-- This is a list of directories that are used by this product as installation locations or custom -->
<!-- action file search locations. -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder" Name="AppData">
<Directory Id="AppRootDirectory" Name="Lookd"/>
</Directory>
</Directory>
<DirectoryRef Id="AppRootDirectory">
<Component Id="SupplementalScripts" Guid="31693357-578d-4dde-aefc-92f413942810" KeyPath="yes" DiskId="1">
<CreateFolder/>
<RemoveFolder Id="RemoveAppRootDirectory" On="uninstall" />
<File Id="SupplementalScripts_Register" DiskId="1" Vital="yes" Source="dst\Scripts\Register.ps1" Checksum="no"/>
<File Id="SupplementalScripts_UnRegister" DiskId="1" Vital="yes" Source="dst\Scripts\UnRegister.ps1" Checksum="no"/>
<File Id="SupplementalScripts_Throw" DiskId="1" Vital="yes" Source="dst\Scripts\Throw.ps1" Checksum="no"/>
<RegistryKey Root="HKCU" Key="Software\CVisionLab\Lookd" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Name="Version" Value="[ProductVersion]" Type="string"/>
</RegistryKey>
</Component>
<Component Id="VirtualMachineDiskImage" Guid="daa7375f-7bd8-4e97-846a-db5f6e6b025a">
<CopyFile Id="VDIFile" SourceName="lookd.vdi" SourceDirectory="SOURCEDIR" DestinationDirectory="TARGETDIR" />
</Component>
</DirectoryRef>
But I recive and error when build:
error LGHT0094 : Unresolved reference to symbol 'Directory:SOURCEDIR' in section 'Product:{7BBA165B-9A8A-40D1-97FA-233F93426F83}'.
If 1 will work for you, then a WiX CopyFile should work. The source location of the copy would be the [SourceDir] property, and the destination some directory defined in your WiX.
If it's really that big, download may be tedious, but if you use it then do it from an app you install rather than run it from the MSI install.
Clarifying in response to comment: there are just two recommendations here that are separate and not related:
Use WiX CopyFile if you choose to copy the file from next to the MSI file to the client system.
If you choose the download option, doing that from the MSI will be tedious and very error prone. It may not even work given that VS custom actions have very limited (or no) access to the network. So do a download from the app you're installing and not the MSI, if you do in fact decide to download.

WiX: Managed to not overwrite config file during upgrade, however shortcuts are removed

I have a similar problem like forki23 by bring Wix to not overwrite a configuration file during upgrade. I have a config file that should not be overwritten during upgrade, but it should be removed during uninstall. However every solution I find, breaks something else.
If I set NoOverwrite=yes and move the RemoveExistingProducts to InstallFinalize the config file is handled as I wished. However, in this case the shortcut is removed during upgrade for some reason. If I leave RemoveExistingProducts at InstallInitialize, the config file is actually removed during upgrade, however the shortcuts are present.
Why is this happening and is there are way to fix it?
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
<!-- InstallInitialize causes config-file to disappear during upgrade -->
<!-- InstallFinalize causes shortcuts to disappear during upgrade -->
...
<Property Id="DISABLEADVTSHORTCUTS" Value="1" />
...
<Directory Id="INSTALLLOCATION" Name="MyApp">
<Component Id="MYAPP.EXE" DiskId="1" Guid="...">
<File Id="MYAPP.EXE" Name="MyApp.exe" Source="..." Vital="yes" KeyPath="yes">
<Shortcut Id="startmenuShortcut"
Directory="ProgramMenuDir"
Name="!(loc.ProductName)"
WorkingDirectory='INSTALLLOCATION'
Icon="Icon.ico"
IconIndex="0"
Advertise="yes" />
</File>
<RegistryValue Root="HKLM"
Name="InstallLocation"
Key="$(var.InstallLocationRegistryKey)"
Type="string"
Value="[INSTALLLOCATION]">
</RegistryValue>
</Component>
<Component Id="MYAPP.EXE.CONFIG" DiskId="1" Guid="..." NeverOverwrite="yes">
<File Id="MYAPP.EXE.CONFIG"
Name="MyApp.exe.config"
Source="..."
KeyPath="yes" />
</Component>
...
</Directory>
...
<Directory Id="ProgramMenuFolder">
<Directory Id="ProgramMenuDir" Name="!(loc.ProductPrefix)">
<Component Id="ProgramMenuDir" Guid="...">
<RegistryValue Root="HKCU" Key="SOFTWARE\MyApp"
Type="string" Value="[INSTALLLOCATION]" KeyPath="yes" />
<RemoveFolder Id="ProgramMenuDir" On="uninstall"/>
</Component>
</Directory>
</Directory>
Note A: The config-file is a machine-wide configuration and should apply for all users.
Note B: I'm using WiX 3.7 and the target plattform is Windows 7 and 8.
Theoretically "NoOverwrite=yes and move the RemoveExistingProducts to InstallFinalize" should work, but it s clear we are losing something from the big picture. The best method to see why Windows Installer removes the shortcuts is to create a verbose log when launching the upgrade setup. You can do that in a cmd.exe with this command: msiexec /i [msi path] /L*V debug.log
The post the a download link for the log and the GUIDs of the components hosting the shortcuts so we can see if the log helps us understand what happens.
Windows installer works very exact in those things, and if anything gets removed in the After="InstallFinalize" case, this means, that a component has been removed, MSI has thought is not needed, because not contained in your new version of the msi file. Be very sure the GUID of the component containing MYAPP.exe and the shortcut has not changed in your new version. (Compare with a tool like Orce or Insted). It seems it has!
MSI removes only full components, not only shortcuts. Really! Maybe you have an update problem of shortcuts in Windows. Sometimes such things happen. Try to reboot to be sure, that this happens, what you think. Maybe there is an error in your test procedure (or it's the above mentioned GUID problem). There are not many other possibilities, if you have not custom actions which remove shortcuts or you try to add shortcuts as files or such dangerous stuff.
Putting a shortcut in the same component as the .exe is common, but not optimal in my eyes! I recommend to separate resources as much as possible, so put it in an own component. This has advantages, if you later want to rename the shortcut. Then you can just change the GUID of this component and the important .exe file is not touched.
There is a small disadvantage of that, loosing the direct connection to the file version of MYAPP.exe in overinstall scenarios, so if MYAPP.exe is a shared file between several different setups, this is not recommended. Perfect solutions for this are possible, but are not in the focus here.
Workaround: If you are still able to change the old (first) msi setup, just mark the component MYAPP.EXE.CONFIG as permanent. Then it will not be uninstalled during Major Upgrade (but not uninstalled at all, what has advantages and disadvantages, in other words, it is mostly acceptable for .config files).
If version 1 of your setup is already shipped, then you could do the same with some tricks too.

Conditionally install files based on Command Line Argument during WIX Install

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.