Pass path of shortcut file to CustomAction - wix

I have a shortcut definition like this:
<Component Id="PowershellShortcut" Guid="{12345678-1234-1234-1234-1234567890AB}">
<Condition>POWERSHELL_INSTALL_LOCATION</Condition>
<Shortcut Id="PowershellStartMenuShortcut"
Name="Powershell Environment"
Description="Powershell Environment"
Target="[POWERSHELL_INSTALL_LOCATION]"
Arguments="-PSConsoleFile "[#Powershell.Environment]"" />
</Component>
I want to pass the path to the resultant .lnk file into a CustomAction. I've tried various things, e.g.:
<CustomAction Id="SetCustomActionData_ElevatePowershellShortcut" Return="check"
Property="ElevatePowershellShortcut"
Value="<WHAT-GOES-HERE?>" />
Where I've tried the following in place of <WHAT-GOES-HERE?>:
[$PowershellShortcut] -- This almost gets me there. I get the folder the .lnk file is in, but not the file itself
[$PowershellStartMenuShortcut] -- Empty string
[#PowershellStartMenuShortcut] -- Empty string. This works on <File> elements...
An alternative would be to keep using the [$PowershellShortcut] value and also pass in the name of the .lnk file. Which would be the <Shortcut>'s Name attribute. I'm not sure how to get at it, either...
The reason I want to do this is that we've already had a case where the Name of the shortcut was changed, and everything stopped working, so we don't want to have to update the name/path of the shortcut in more than one place.

Just after I wrote this question, I came up with a solution. It's not quite what I asked for, but it solved my problem, so I'm posting it. If somebody can figure out how to do what I actually asked for, I will mark their answer as the correct one, although my solution is fairly clean and straight forward.
I ended up defining the following variable in my WiX define file:
<?define PowershellShortcutName="Powershell Environment" ?>
and then I set the <Shortcut Name="$(var.PowershellShortcutName)"> and the CustomAction to:
<CustomAction Id="SetCustomActionData_ElevatePowershellShortcut" Return="check"
Property="ElevatePowershellShortcut"
Value="[$PowershellShortcut]$(var.PowershellShortcutName).lnk" />
Everything works like it should now.

Related

MSBuild GetPathOfFileAbove() returning empty

I am trying to refactor the code below to use GetPathOfFileAbove() instead.
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory),global.json))\eng\Configurations.props" />
when i tried the below code, an error was thrown, file not found
<Import Project="$([MSBuild]::GetPathOfFileAbove('global.json','$(MSBuildThisFileDirectory)'))\eng\Configurations.props" />
The path of the above code result in,where "global.json" shouldn't have been here:
"C:\dotnetruntime\runtime\global.json\eng\Configurations.props"
Expected path:
"C:\dotnetruntime\runtime\eng\Configurations.props"
I having a hard time finding documentation to figured out the configuration am missing here. Can you guys give me some pointers
The correct path to use was
"<Import Project="$([MSBuild]::GetPathOfFileAbove(Configurations.props,$(MSBuildThisFileDirectory)))../../../../../eng/Configurations.props" />"
The use of "../" allows the file be searched one directory above.

Error The localization variable !(loc.EMRDataServiceDescription) is unknown. Please ensure the variable is defined

When i am building my WIX project from visual studio (Votive) I am getting the below error:
Severity Code Description Project Path File Line Column Source Suppression State
Error The localization variable !(loc.EMRDataServiceDescription) is unknown. Please ensure the variable is defined. EMR4.0.1 E:\Code\EMR\EMR4\EMR4.0.1\EMR4.0.1 E:\Code\EMR\EMR4\EMR4.0.1\EMR4.0.1\EMR_WiX_Installer_EN.wxs 76 1 Build
I am using "EMRDataServiceDescription" in the below code snippet at the "ServiceInstall" element.
EMR_WiX_Installer_EN.wxs file
<Component Id="DataServiceExeComponent" Guid="{6F0AFA7E-77EA-11E0-A3DF-5DD64824019B}" >
<Condition><![CDATA[REINSTALLMODE<>"ecmus"]]></Condition>
<File Id="EXECUTABLE2" Name="dataserv.exe" Source="$(var.DataServiceFile)" DiskId="1" KeyPath="yes" DefaultSize="7121522" DefaultVersion="4.3.0.0.1170.S" />
**<ServiceInstall Id="InstallEMRDataService" Name="EMR Data Service" DisplayName="EMR Data Service" Type="ownProcess" Start="auto" ErrorControl="normal" Description="!(loc.EMRataServiceDescription)">**
<ServiceDependency Id="EMR UPS Service"/>
</ServiceInstall>
And this is declared in WixUI_en-us.wxl file like as shown below:
<String Id="EMRDataServiceDescription" Overridable="yes">Service for managing data operations.</String>
And the namespace is like as shown below:
<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl" Codepage="1252">
Before this error i got the below error that i fixed by using the setting in "Build Action".
Error The localization identifier 'EMRDataServiceDescription' has been duplicated in multiple locations. Please resolve the conflict. EMR4.0.1 light.exe 0 1 Build
Below are the settings i made:
Right click on the .wxl file
Click on properties.
Under “Build Action”:
Changed “EmbeddedResource” to “None”
Did I miss anything or the error is due to the the settings i made?
Problem Scenario: A bit unclear what exactly is happening, but I think you must:
1) either have a localization file for another language than English which is lacking the identifier you refer to: "APCDataServiceDescription" and you haven't excluded it from the build, or
2) you have set the English localization file to "None" for "Build Action".
Possible Resolution: First set the English location file to "EmbeddedResource" for the "Build Action" if this is not already the current setting. Next you can select what cultures to build by right clicking your WiX project in the Solution Explorer Pane in Visual Studio, then you go Properties and to the "Build" tab. Now set the "Cultures to build" field to "en-US" in order to build only English (or set it to the culture value of your main WiX project file - could be any culture):
Now try to build and see if the English version compiles correctly.

Wix preprocessor variable value includes quotes

using Wix 3.11, project built using msbuild 14.0.25420.1
I've come across a situation where a string I define in a proprocessor variable is having the enclosing quotes included within the variable value.
I would appreciate if someone could tell me:
why this behaviour occurs ( am I doing something wrong ? )
how I would quote a string value with spaces
The project has a main .wxs file, plus a number of .wxi Include files.
In the main Product.wxs within the Wix element:
<?define registry_key_path="SOFTWARE\MySoftwareGroup\MySoftware" ?>
Then in an include file Component.wxi within a Component element:
<RegistryValue
Root="HKLM"
Key="$(var.registry_key_path)"
Name="InstallFolder"
Value="[INSTALLDIR]"
Type="string" />
The install fails with error:
Error 1406. Could not write value InstallFolder to key
\"SOFTWARE\MySoftwareGroup\MySoftware"
You can see that the key contains the quotes. It should read:
\SOFTWARE\MySoftwareGroup\MySoftware
If I remove the quotes from the define:
<?define registry_key_path=SOFTWARE\MySoftwareGroup\MySoftware ?>
the installer correctly parses the variable and finds the right registry key and writes to it.
Why are the quotes being included?
How would I quote the string value if it contained a space?
Works for me with WiX v3.11.1.2318. Open your .msi in Orca to inspect the Registry table and see if the quotes exist there. If you can reproduce it in a small example .wixproj, please open a bug.

Passing multiString values to installer through command-line

I have an WiX installer configured like this:
<Property Id="MY_PROPERTY">
...
<Registry Name="MyValue" Type="multiString" Value="[MY_PROPERTY]" />
Now I want to pass this property value at the command line as a list:
MsiExec.exe /i MyInstaller.msi /qb MY_PROPERTY="One[~]Two[~]Three"
However, the installer does not split the values into a list and the literal value is written instead.
If I hard code the element it works properly:
<Registry Name="MyValue" Type="multiString" Value="One[~]Two[~]Three" />
Does anyone know how to specify a list of values at the command-line for a multiString registry value? Thanks in advance
Better late than never!
This can be achieved using a Custom Action.
Follow this MS document carefully: https://learn.microsoft.com/en-us/windows/win32/msi/registry-table
In your custom action, insert the registry value into MSI table from your property as follows,
Set db = Session.Database
set oView = db.OpenView("INSERT INTO `Registry` (`Registry`,`Root`,`Key`,`Name`,`Value`,`Component_`) VALUES ('reg_MY_PROPERTY', -1,'Software\Company\Product','MyValue','" & _
Session.Property("MY_PROPERTY") & "','CM_CP_BlahBlah') TEMPORARY")
oView.Execute
oView.Close
CM_CP_BlahBlah is your WIX component Registry values are attached to.
Please note "custom action must come before the RemoveRegistryValues and WriteRegistryValues actions in the action sequence"
<InstallExecuteSequence>
<Custom Action="SetMyPropertyCustomAction" Before="RemoveRegistryValues">NOT REMOVE</Custom>
</InstallExecuteSequence>
REG_MULTI_SZ
A sequence of null-terminated strings, terminated by an empty string (\0).
The following is an example:
String1\0String2\0String3\0LastString\0\0
The first \0 terminates the first string, the second to the last \0 terminates the last string, and the final \0 terminates the sequence. Note that the final terminator must be factored into the length of the string.
So as per this LINK you should be doing this:
MY_PROPERTY="One\0Two\0Three\0"
For MULTISTRINGValues check this element: MULTISTRINGVALUE

How to redirect input for customaction execommand

I'm trying to setup a custom action to initialize my SQLite database using the sqlite3.exe command line tool. In a command prompt I type the following: c:\sqlite3.exe database.db < sqlscript.sql
My Wix custom action falls apart in the ExeCommand attribute because I cannot seem to escape out the <.
<CustomAction Id="InitializeDatabase" FileKey="SQLiteEXE" ExeCommand="database.db < sqlscript.sql" Execute.../>
I've tried "&lt" as well.
I know I could just install an empty initiailzed database but I'm curious how to redirect inputs.
Thanks.
So, what exactly is happening when you say it falls apart? Does it compile?
Just so that we're on the same page, are you ending you XML entity with the semi-colon. You probably are, but it didn't come through in your code sample. Are you using:
<
If that doesn't work, you could try putting the command into a property and using CDATA tags, such as:
<Property Id="MyCommand">
<![CDATA[
database.db < sqlscript.sql
]]>
</Property>
and using that in the ExeCommand attribute:
ExeCommand="[MyCommand]"
That might work.
If you really have to call an EXE, I reccomend using the WiX QuietExec Custom Action pattern. Worse case you could install a .BAT file then use the cmd /c foo.bat command to call it. Then you wouldn't have to escape the <.
Otherwise I would search for an alternative to the EXE. I try to stick with data driven custom actions that run in process ( say C++ or C#/DTF ).
Quiet Execution Custom Action