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.
Related
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.
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.
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
Please read till I state my question clearly. I'm trying to implement a custom msbuild task that will accept a variable number of input parameters from a msbuild script. I am aware of arrays of input parameters in customs tasks
public ITaskItem[] ArrayofItems { get; set; }
These can be declared as follows using either propertygroup/itemgroup
<PropertyGroup>
<Item1>1</Item>
<Item2>2</Item>
<Item3>3</Item>
<Item4>4</Item>
<Item5>5</Item></PropertyGroup>
<ItemGroup>
<File Include="1"></File>
<File Include="2"></File>
<File Include="3"></File>
<File Include="4"></File>
<File Include="5"></File> </ItemGroup>
Then from VS 2010 command line I can set/override the property as following
msbuild somefile.csproj /t:MyTarget /p:Item1=Name1;Item2=Name2...etc
My question is :- Is it possible to declare variable number of propertygroup/itemgroup in the build file so that I can pass in 'n' variable parameters from msbuild command line something like this using propertygroup/itemgroup?
msbuild somefile.csproj /t:MyTarget /p:Item1=Name1;Item2=Name2;ItemN=NameN ('N' Only for illustration purposes)
Is this even possible?
Thanks in advance, Any help will be greatly appreciated.
If you call your build project like this...
> msbuild My.proj /p:ItemProperty="1;2;3;4;5"
And the project does this...
<ItemGroup>
<FromProperty Include="$(ItemProperty)" />
</ItemGroup>
<Message Text="%(FromProperty.Identity)" />
...you have essentially converted a property into an array of items. If you were to convert to dymanically created properties, there would be no easy way to reference them in the rest of your script, since you wouldn't know their names ahead of time when the script is authored.
Excerpted from MSBuild Trickery, trick #30 which has many pages of additional detail on this manipulation
I am trying to setup some properties that I use multiple times in my MSBuild script. I have the following property section:
<PropertyGroup>
<BuildDependsOn>$(BuildDependsOn); MyAfterBuild </BuildDependsOn>
<SubstitutionsFilePath>$(ProjectDir)app.config.substitutions.xml </SubstitutionsFilePath>
<AppConfig>$(TargetPath).config</AppConfig>
<HostConfig>$(TargetDir)$(TargetName).vshost.exe.config</HostConfig>
</PropertyGroup>
When I run this I get the following error:
The expression "#(TargetPath).config" cannot be used in this context. Item lists cannot be concatenated with other strings where an item list is expected. Use a semicolon to separate multiple item lists.
I don't understand this error, as the use of the $(BuildDependsOn) and $(ProjectDir) work fine. And I know the $(TargetXXX) values generate properly as when I put them directly into the Tasks section below, they work fine.
The reason for this problem is that TargetDir is defined as an item list, not a property; presumably to cater to the scenario where your outputs are distributed amongst several output directories?
I came up against this same problem and managed to work around it by using the $(OutDir) property instead of $(TargetDir).
(The OutDir property is defined in Microsoft.Common.Targets (lines 100-102) as a normalised version of the OutputPath defined in your project file.)
First try running your build with the /v:diag option, which will output a lot more information and give you a clue as to what part of the build is failing.
A clue might be in the Microsoft.Common.targets file (located in %SystemRoot%\Microsoft.NET\Framework\v2.0.50727) in the PrepareForBuild target:
<!--
These CreateProperty calls are required because TargetDir and TargetPath are defined
to contain an item list. We want that item list to be expanded so that it can be used
as a regular property value and not as an item-list-with-transform.
-->
<CreateProperty Value="$(TargetDir)">
<Output TaskParameter="Value" PropertyName="TargetDir" />
</CreateProperty>
<CreateProperty Value="$(TargetPath)">
<Output TaskParameter="Value" PropertyName="TargetPath" />
</CreateProperty>
To me this looks like a bug, you can report it at https://connect.microsoft.com/feedback/Search.aspx?SiteID=210.