I have an msbuild script which uses the Exec tag to kick off another MSBuild command including a DefineConstants property with multiple values. Since I have multiple values for that property, I’m using the technique described in this question to call MSBuild.exe directly (not use the MSBuild tag) and enclose the values in quotes.
However, I now need to embed a special symbol into one of those values, which I’m attempting to do using the code ¯ (registered trademark ®)
The problem is that the special character code must end in a semicolon, but when I embedded the semicolon, msbuild reads that as a value seperator. I can seem to find a valid way to escape the semicolon and have it still show up in the end parameter value.
My question is this:
How can I embed the special char into my build parameter?
To improve readability, I’ve moved the value to a variable in my example, but that’s not a requirement.
File: TopLevelBuildScript.proj
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BuildWithSpecialChar">
<ItemGroup>
<!-- Note: %3B is the escape code for semicolon -->
<MyProductName Include="Trademarked&#174%3B Product" />
<OtherProperty Include="foo" />
</ItemGroup>
<Exec Command="msbuild.exe subBuildScript.proj /p:DefineConstants="MyProductName=@(MyProductName);OtherVar=@(foo);AnotherVar=asdf;" " />
</Target>
</Project>
When executed, the above produces the command line:
msbuild.exe subBuildScript.proj /p:DefineConstants="MyProductName=Trademarked® Product;OtherVar=foo;AnotherVar=asdf;"
Which ends up defining the constants with the product name split at the semicolon:
MyProductName=Trademarked®
Product
OtherVar=foo
AnotherVar=asdf
Note: I’ve also tried using %25 for the percent sign:
<MyProductName Include="Trademarked&#174%253B Product" />
But that gives me:
MyProductName=Trademarked®B Product
OtherVar=foo
AnotherVar=asdf
Update
It turns out the issue wasn’t with MSBuild, rather with the way WiX parses parameters (my subBuildScript utilizes WiX). I didn’t consider that, so didn’t mention it in my original posting.
Ultimately, I went with a solution based on this answer to another question:
<PropertyGroup>
<WixValues>
<MyProductName>Trademarked® Product<MyProductName>
<OtherProperty>foo"</OtherProperty>
</WixValues>
</PropertyGroup>
<MSBuild
Projects="subProjectScript.proj"
Properties="Configuration=Release;WixValues=$([MSBuild]::Escape($(WixValues)))"
Targets="Clean;Rebuild"
ContinueOnError="false"
StopOnFirstFailure="true">
</MSBuild>
and unescaping the values in subProjectScript.proj as described in the other answer.
First, MSBuild files are XML, which you can encode as UTF-8, so you should be able to copy/paste the trademark character directly in the MSBuild script, without escaping.
If you can’t take that approach, don’t escape the ampersand. There are two levels of escaping things in an MSBuild script. The first is XML-encoding, so that XML-sensitive characters (
<and&) can be used and you’ll still have safe XML. When MSBuild reads in the file, XML-escape sequences get unescaped. After that process, MSBuild then does its own un-escaping (i.e.%3Bfor semi-colons).Because you’re using
&at the beginning of your XMl escape sequence, the XML processor is interpreting that as a literal ampersand, not the special XML ampersand, which denotes an escape sequence. Change yourMyProductNameitem group’s value to be:Since
MyProductNameappears to be a scalar value, and not a list, I would use a property instead:In your
Exectask you can then use it like this: