Msbuild: Unable to pass in Property values containing a semicolon or comma in .Net Core MSBuild

Created on 8 Feb 2016  路  17Comments  路  Source: dotnet/msbuild

In corefx repo, we pass in a special property in our outerloop jenkins runs that contains a colon ';' on the property name. With Full MSBuild, the behavior is that given the colon is found inside a quoted string, then it just assumes that the colon is part of the string. However, in .Net Core the behavior is different, since what it tries to do is to use the colon as the end of the string, and assumes that everything after the colon is a different switch. For example, if you have the following target:

<Target Name="TestTarget">
    <ItemGroup>
      <IParam Include="$(Param)" />
    </ItemGroup>
    <Message Text="The param passed was: @(IParam)" />
  </Target>

You get the following when using full msbuild:

msbuild build.proj /p:Param="Hello;World" /t:TestTarget
Project "C:\Users\joperezr\Desktop\repo\corefx\build.proj" on node 1 (TestTarget target(s)).
TestTarget:
  The param passed was: Hello;World

This is the result when running the same target in .Net Core MSBuild:

Corerun.exe MSBuild.exe build.proj /p:Param="Hello;World" /t:TestTarget
MSBUILD : error MSB1006: Property is not valid.
Switch: World
.NET Core

Most helpful comment

@danmosemsft found a very nice workaround in https://github.com/Microsoft/msbuild/issues/2999#issuecomment-366101535

Note I discovered a workaround; MSBuild escaping works here. Comma is %2c so

dan@danmose2:~/dotnetU$ dotnet msbuild  /p:"aaa=bbb,ccc" /v:diag | grep "ccc"
Switch: ccc
dan@danmose2:~/dotnetU$ dotnet msbuild  /p:"aaa=bbb%2cccc" /v:diag | grep "ccc"
/usr/share/dotnet/sdk/2.1.3/MSBuild.dll /Logger:Microsoft.DotNet.Tools.MSBuild.MSBuildLogger,/usr/share/dotnet/sdk/2.1.3/dotnet.dll /m /p:aaa=bbb%2cccc /v:m /v:diag ./dotnetU.csproj
                   aaa = bbb,ccc

Semicolon ; is %3B.

All 17 comments

Hey @rainersigwald could you please take a look at this to see if it's a known issue? Currently this is the reason why our new outerloop runs in corefx are failing, we could obviously work around it by modifying the properties we pass in, but I believe that this is a bug and hopefully not a very hard one to fix

Looks like it's a bug in our command-line quote handling to me, and I think we should fix it. This is the error we throw when you attempt to define a property at the command line but don't give an =value part:

o:\msbuild>msbuild /p:blah build.proj /nologo
MSBUILD : error MSB1006: Property is not valid.
Switch: blah

So I think what's happening here is we're disregarding the quotes and splitting at the semicolon as though it was outside the quotes (and interpreting World as a new property, with no given value).

Side note: that error message is confusing! #472

Just to give an update, we're not sure exactly how to fix this quite yet. An easy workaround is to escape the quotes:
msbuild build.proj /p:Param=\"Hello;World\" /t:TestTarget

The issue is here. We previously used Environment.CommandLine which kept the quotes, the string array does not. Since Environment.CommandLine is not supported in .NET Core right now, we will have to modify our logic to handle this case.

@AndyGerlicher I can try escaping the quotes for now, and will change that once we have an actual fix.

We've discussed this at length in team meeting and triage. It seems the core issue here is we have custom parsing logic that differs from the command line parameter parsing logic, and they're somewhat incompatible and mutually exclusive between .NET Core and full .NET.

In Windows, we get the command line as passed in and parse it. Since this is not available in .NET Core we do something slightly different. Some options:

  1. Modify our parsing logic to be smarter about arg splitting. Since we don't have to do anything to split them this would likely be easier, but probably not 100% compatible and diverge us more from the full Framework version. Not ideal. I imagine there was also a reason why this was done in this way in the first place, but that might be over optimistic.
  2. Implement platform specific logic to try to get the proper string and use that. This is easy in Windows/cmd.exe, but not so with every platform and command processor out there. I don't want builds to fail like this in only certain scenarios for something like quotes in the command line.
  3. Try to fix this scenario, recognizing that with the loss of fidelity from the users string -> parsed args there will likely be further issues found in the future.
  4. Do nothing and escape quotes when using the .NET Core version and you need them to appear.

None of these are very good, for now we're going to stick with option 4. If someone has a better idea please speak up.

Note that Environment.CommandLine isn't available by design, the issue is here https://github.com/dotnet/coreclr/issues/3103 for the discussion.

I'm having this same issue. However escaping the string doesn't help. I am using Powershell if that matters.

[string]$frameworks_to_test = "netcoreapp1.0,net451"

$testFrameworks = $frameworks_to_test.Replace(',', ';')

            &dotnet msbuild $solutionFile /t:Build `
                /p:Configuration=$configuration `
                /p:AssemblyVersion=$assemblyVersion `
                /p:InformationalVersion=$pv `
                /p:Product=$product_name `
                /p:Company=$company_name `
                /p:Copyright=$copyright `
                /p:TestFrameworks=\"$testFrameworks\"

I still get the "property is not valid" error.

I am using the .NET Core SDK 2.0 to build and have verified that is what it is using with the dotnet --version command.

This is still a problem with on-premise TFS update 2, when using msbuild it does not quote properly during the Xamarin.iOS build task using the Codesignkey property. The issue is not specific to just commas or semicolons, I attempted to just specify /p:Codesignkey=iPhone Distribution and I still receive the same error:
MSBUILD : error MSB1008: Only one project can be specified. Switch: Distribution

Alternative workaround would be to keep whole thing in single quote
'/p:Param="Hello;World'.

We get same problem with latest Xamarin on Mono:
msbuild with parameter /p:CodesignKey="iPhone Distribution: Some Company, LLC" fails with exactly same error. But works with '/p:CodesignKey="iPhone Distribution: Some Company, LLC"'

Not sure which of the issues (this or 472) is the root one, I posted detailed info into #472.

@danmosemsft found a very nice workaround in https://github.com/Microsoft/msbuild/issues/2999#issuecomment-366101535

Note I discovered a workaround; MSBuild escaping works here. Comma is %2c so

dan@danmose2:~/dotnetU$ dotnet msbuild  /p:"aaa=bbb,ccc" /v:diag | grep "ccc"
Switch: ccc
dan@danmose2:~/dotnetU$ dotnet msbuild  /p:"aaa=bbb%2cccc" /v:diag | grep "ccc"
/usr/share/dotnet/sdk/2.1.3/MSBuild.dll /Logger:Microsoft.DotNet.Tools.MSBuild.MSBuildLogger,/usr/share/dotnet/sdk/2.1.3/dotnet.dll /m /p:aaa=bbb%2cccc /v:m /v:diag ./dotnetU.csproj
                   aaa = bbb,ccc

Semicolon ; is %3B.

How do I escape this?:
.$msbuild /t:Build /t:Publish /p:TargetDatabaseName=$Database /p:TargetConnectionString=$connectionString /p:SqlPublishProfilePath=$SettingsFileName /p:Variables:ProjectDir=$ProjectDir $ProjectFileName
The last /p gives:
MSBUILD : error MSB4177: Invalid property. The name "Variables:ProjectDir" contains an invalid character ":".

The property name is for building db projects using MS tools.

NOTE: The property name -- Variables:ProjectDir (with a COLON in it)

Have you tried something like this '/p:CodesignKey="iPhone Distribution: Some Company, LLC"'

Helped me.

@jeffmounce Colons are not valid in MSBuild property names. How did you identify that property? What kind of project uses it?

SQL DB Project.
https://msdn.microsoft.com/en-us/library/hh550080(v=vs.103).aspx
(search for "/Variables:")

To pass through parameters to sqlpackage, you simply append /p: to them and they pass through.

@jeffmounce

To pass through parameters to sqlpackage, you simply append /p: to them and they pass through.

MSBuild doesn't have a mechanism to do that: MSBuild logic cannot enumerate defined properties, so it can't detect arbitrary properties. Where did you get that information?

There are many such posts around the net about this. Such as:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/e8975bc0-e1a3-4d53-a286-4832b8491301/working-with-msbuild-in-order-to-build-and-deploy-a-database-project?forum=ssdt

But it sounds like the answer is "you can't do that."
So, I ask, "How do I build an SSDT project using msbuild and pass SQLCMD variables?"

How do I build an SSDT project using msbuild and pass SQLCMD variables?

That's a great question for the SSDT folks. I don't know offhand the best way to contact them; I'd try their forum or asking for documentation at their docs site.

Was this page helpful?
0 / 5 - 0 ratings