1

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&amp;#174%3B Product" />
      <OtherProperty Include="foo" />
    </ItemGroup>

   <Exec Command="msbuild.exe subBuildScript.proj /p:DefineConstants=&quot;MyProductName=@(MyProductName);OtherVar=@(foo);AnotherVar=asdf;&quot; " />
    </Target>
  </Project>

When executed, the above produces the command line:

msbuild.exe subBuildScript.proj /p:DefineConstants="MyProductName=Trademarked&#174; Product;OtherVar=foo;AnotherVar=asdf;"

Which ends up defining the constants with the product name split at the semicolon:

MyProductName=Trademarked&#174
Product
OtherVar=foo
AnotherVar=asdf

Note: I've also tried using %25 for the percent sign:

<MyProductName Include="Trademarked&amp;#174%253B Product" />

But that gives me:

MyProductName=Trademarked&#174B 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.

Community
  • 1
  • 1
John M. Wright
  • 4,477
  • 1
  • 43
  • 61

1 Answers1

1

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. %3B for semi-colons).

Because you're using &amp; 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 your MyProductName item group's value to be:

<MyProductName Include="Trademarked&#174; Product" />

Since MyProductName appears to be a scalar value, and not a list, I would use a property instead:

<PropertyGroup>
  <MyProductName>Trademarked® Product</MyProductName>
</PropertyGroup>

In your Exec task you can then use it like this:

<Exec Command="msbuild.exe subBuildScript.proj /p:DefineConstants=&quot;MyProductName=$(MyProductName);OtherVar=@(foo);AnotherVar=asdf;&quot; " />
Aaron Jensen
  • 25,861
  • 15
  • 82
  • 91
  • Turns out it was an issue with the way WiX is parsing the properties, but since I didn't mention WiX involvement in my original post, you couldn't have known that. Your answer appears to correctly address the question as it was posted, so marking it as accepted. – John M. Wright Sep 11 '12 at 17:40