How can I log a the value of a property in Wix? - wix

I want to know if in the same directory of my setup (CURRENTDIR) there is a file named "pippo.txt". So I made the following property.
<Property Id="TROVAPIPPO">
<DirectorySearch Id="trovadir" Depth="0" Path="CURRENTDIR">
<FileSearch Id="trovafile" Name="pippo.txt" />
</DirectorySearch>
</Property>
Now I want to display the value of this property in the log file (in temp folder). But I don't know how.

Run your installer from the command line with msiexec /i yourInstaller.msi /L*v yourLogFile.txt
Changes to MSI properties will be logged. The log files are pretty big, but it'll be in there somewhere.

Related

WiX Toolset: ICE03 Invalid identifier with RemoveFolderEx

I'm trying to create a .msi installer for a Node.js project using the WiX Toolset. I want to remove the node_modules folder during uninstall. This is the relevant excerpt from my .wxs file:
<Property Id='APPLICATIONFOLDER'>
<RegistrySearch Id='ApplicationFolder' Root='HKLM' Key='Software\[ProductName]' Name='InstallDir' Type='raw'/>
</Property>
<DirectoryRef Id='TARGETDIR'>
<Component Id='RemoveFolder' Guid='3e2231d9-61b3-41a2-b407-8df015be537e'>
<util:RemoveFolderEx Property='[APPLICATIONFOLDER]\node_modules' On='uninstall'/>
<RegistryValue Root='HKLM' Key='Software\[ProductName]' Name='InstallDir' Type='string' Value='INSTALLDIR' KeyPath='yes'/>
</Component>
</DirectoryRef>
I thought this would read the value from the registry, assign it to the property APPLICATIONFOLDER, and then in the RemoveFolderEx tag append the string \node_modules to that property's value.
But when I try to run this through light.exe, I get ICE03: Invalid identifier; Table: WixRemoveFolderEx, Column: Property, Key(s): wrf1A1445CB13E8BF98989EA24E3514470A.
Clearly, it is unhappy with my Property attribute, but what do I need to fix it? I've seen plenty of guides using this general pattern, but they always read the install dir value from the registry and then nuke that entire folder. That seems a little crass - if the user has added files to the directory I don't want to delete them. How can I specify a subfolder to delete?
I've solved the problem. Because I personally had a hard time figuring it out - the guides I've seen on RemoveFolderEx only all cover the same use case of nuking a folder saved to the registry, not a subfolder; and I find the WiX documentation to be less than beginner-friendly in most cases -, I am recording the solution here in case someone else should ever stumble upon the same problem.
As was pointed out already, Property does not work in the way I presumed in my question - it really does just accept the id of a property holding the path to the directory to delete. So you will definitely need to set a property in some way. (Some guides on the internet do not make this very clear.)
The next obvious path to investigate would be to assign the property a modified result of the registry search. However, this is impossible with WiX (to the best of my knowledge).
The answer lies in SetProperty. This, finally, allows to set a new property based on the one read from the registry.
It is worth noting that doing this still prevents the installation folder from being deleted, even if it empty. This, however, can easily be remedied by adding a RemoveFolder (without the Ex). This will delete the folder, but only if it is empty.
The relevant code that got it working for me is below.
<!-- Read the InstallDir from the registry and assign it to property APPLICATIONFOLDER -->
<Property Id='APPLICATIONFOLDER'>
<RegistrySearch
Id='ApplicationFolder'
Root='HKLM'
Key='Software\[ProductName]'
Name='InstallDir'
Type='directory'
Win64='yes'/>
</Property>
<!-- Set new property NODE_MODULES_FOLDER by appending node_modules\ to APPLICATIONFOLDER -->
<SetProperty
Id='NODE_MODULES_FOLDER'
Value='[APPLICATIONFOLDER]node_modules\'
Before='CostInitialize'/>
<Component Id='RemoveFolders' Guid='...'>
<!-- Remove the node_modules subfolder, using the property we created above -->
<util:RemoveFolderEx Property='NODE_MODULES_FOLDER' On='uninstall'/>
<!-- Remove main installation directory now, but only if it is empty. -->
<!-- That's why we're using RemoveFolder instead of RemoveFolderEx here. -->
<RemoveFolder Id='RemoveMainFolder' Property='APPLICATIONFOLDER' On='uninstall'/>
<RegistryValue
Root='HKLM'
Key='Software\[ProductName]'
Name='InstallDir'
Type='string'
Value='[INSTALLDIR]'
KeyPath='yes'/>
</Component>
I thought this would read the value from the registry, assign it to the property APPLICATIONFOLDER, and then in the RemoveFolderEx tag append the string \node_modules to that property's value.
It won't. As the doc says, Property is:
The id of a property that resolves to the full path of the source directory.
The easiest way to make that happen is to write the exact path you want to nuke to the registry.

How to use WixToolset DirectorySearch

I've been struggling with the DirectorySearch command.
I want to find the Templates folder that is located under the Microsoft Office folder.
It can be in either of the following two locations:
Microsoft Office\Templates
Microsoft Office\Root\Templates
I've tried the following
....
<Directory Id="MICROSOFTOFFICE" Name="Microsoft Office">
<Directory Id="TEMPLATES"/>
</Directory>
<Property Id="TEMPLATES">
<DirectorySearch Id='MSDir' Path='[MICROSOFTOFFICE]' >
<DirectorySearch Id='TDir' Depth='3' Path='Templates'/>
</DirectorySearch>
</Property>
What am I doing wrong?
When I try to view the contents of Templates it says "1: 0 2:"
Does this mean null?
<Condition Message="[TEMPLATES]">TEMPLATES</Condition>
Directories are not properties. If you want to set a directory to the value of a property you should use SetDirectory
<SetDirectory Action="SetTemplateDir" Id="TEMPLATES" Value="[TEMPLATES]">TEMPLATES</SetDirectory>
If this doesn't work you might need to look at the msi logs for more information on what is happening during the directory searches and trying to set the directory. Just run your msi from the cmd line with "msiexec /i installer.msi /l*v msilog.txt"

Not able to update XML value in Change mode (without admin rights)

I have written following code in my wix installer for updating the language in an XML file and this works fine in following conditions:
1) fresh install
2) upgrade by using admin rights (I am using msiexec /I "Tools.msi" /l*v D:\InstallLog.txt).
However, when I run/execute the msi without admin rights (This is where "Change" mode is being used....what am I missing) the values are not updating always set to the default value :
<Property Id="LANGUAGE" Value="en-US" />
The code:
<util:XmlFile Id="LanguageConfig"
Value="[LANGUAGE]"
ElementPath="/configuration/appSettings/add[\[]#key='Language'[\]]"
Action="setValue"
File="$(var.ConfigFile)"
Name="value" Sequence="1" />
<util:XmlFile Id="MappingLanguageXML"
Value="[LANGUAGE]"
ElementPath="/MappedUsers/UsersList/UserID/LanguageCode"
Action="setValue"
File="$(var.UserMappingFile)" Sequence="1" />
Any help is much appreciated.
The fact that it's being changed implies it may not be a privilege issue. I suspect that the scenario is that a different language was entered at install time, but you did not preserve its value anywhere so Change just uses the default value. Properties aren't remembered automatically, that's what the WiX "remember property" pattern is for. That's likely to be the solution - preserve the install time value of LANGUAGE. It's no different from running any program - the fact that the user may have entered something that went into a variable doesn't mean that the variable will have that same value next time you run the program unless you save it.
Based on PhilDw pointer I solved the issue by modifying my property
<Property Id="LANGUAGE" Value="en-US" />
as follows:
<Property Id="LANGUAGE" Secure="yes" Value="en-US">
<RegistrySearch Id="RememberLanguage" Root="HKLM"
Key="$(var.RegistryLoc)"
Name="Language" Type="raw" />
</Property>
By preserving the value in the registry I was able to modify the value during "Change" operation.

How to find a file inside installer's folder in Wix?

Is there any way to find (and execute) a file that lies near installer ? My example of file structure:
MyInstaller.msi
Tools
Tool.exe
I want to be able to find Tools\Tool.exe from MyInstaller.msi and launch it (if it exists) when user will click a button. I'm trying this
<Property Id="TOOL_EXE">
<DirectorySearch Id="TOOL_PATH" Path="\Tool\">
<FileSearch Id="TOOL_EXE_SEARCH" Name="tool.exe" />
</DirectorySearch>
</Property>
but TOOL_EXE variable is empty.
Important note: I don't have this file in moment of creating installer, so I can't include it.
I think the only problem here is the Path-attribute, where you specified \Tool\ as value. The leading backslash tries to search on the root, therefore it can't find the directory. Also leave away the final backslash: adding it the installer expects something to follow there. So try .\Tool instead.
You could also use the following (SourceDir is referencing the folder of the installation file, see also here). It is possible though that the property is not already available, didn't test this.
<Property Id="TOOL_EXE">
<DirectorySearch Id="TOOL_PATH" Path="[SourceDir]Tool" Depth="0">
<FileSearch Id="TOOL_EXE_SEARCH" Name="tool.exe" />
</DirectorySearch>
</Property>

Wix directory reference a registry value

I am writing an installer which needs to lookup the installation directory from a registry value.
I am using the property to lookup the registry and the component group refers that property. But the component group doesn't seem to be picking up directory from the property. Is there a better way to do it?
Cheers..
I guess you are doing something like that :
<Property Id="MY_PATHNAME" Secure="yes">
<RegistrySearch Id="My_Path_Signature" Root="HKLM"
Key="$(var.My_Key)" Name="PathName" Type="directory">
</RegistrySearch>
</Property>
then you're trying to retrieve the value of "MY_PATHNAME"...
In case the installer decides not to set the property correctly , you can generate a log from the command line :
msiexec /i MyInstaller.msi /l*v MyLog.txt