Fix MSBuild invocation to quote property option values.

This commit ensures that any `/property` option's value is surrounded by quotes
to allow MSBuild to properly interpret special characters like semicolons.

Users familiar with MSBuild expect `/property:Name="Value"` to handle
semicolons. However, since `dotnet` parses the command line first, the
quotes get processed by its command line parser.  This results in
`/property:Name=Value` being passed to MSBuild, which will not parse a "Value"
containing a semicolon correctly.

Since it is safe to always quote the property value for this option, this fix
simply ensures that the value is surrounded by quotes.

This fixes the issue for all commands that forward arguments to MSBuild.

Fixes #7791.
This commit is contained in:
Peter Huene 2018-04-26 10:53:54 -07:00
parent 9e877425c4
commit f9b939fe89
No known key found for this signature in database
GPG key ID: E1D265D820213D6A
11 changed files with 128 additions and 99 deletions

View file

@ -13,21 +13,21 @@ namespace Microsoft.DotNet.Cli.MSBuild.Tests
[Theory]
[InlineData(new string[] { }, "-target:Build")]
[InlineData(new string[] { "-o", "foo" }, "-target:Build -property:OutputPath=foo")]
[InlineData(new string[] { "-property:Verbosity=diag" }, "-target:Build -property:Verbosity=diag")]
[InlineData(new string[] { "--output", "foo" }, "-target:Build -property:OutputPath=foo")]
[InlineData(new string[] { "-o", "foo1 foo2" }, "-target:Build \"-property:OutputPath=foo1 foo2\"")]
[InlineData(new string[] { "-o", "foo" }, @"-target:Build -property:OutputPath=\""foo\""")]
[InlineData(new string[] { "-property:Verbosity=diag" }, @"-target:Build -property:Verbosity=\""diag\""")]
[InlineData(new string[] { "--output", "foo" }, @"-target:Build -property:OutputPath=\""foo\""")]
[InlineData(new string[] { "-o", "foo1 foo2" }, @"-target:Build ""-property:OutputPath=\""foo1 foo2\""""")]
[InlineData(new string[] { "--no-incremental" }, "-target:Rebuild")]
[InlineData(new string[] { "-r", "rid" }, "-target:Build -property:RuntimeIdentifier=rid")]
[InlineData(new string[] { "--runtime", "rid" }, "-target:Build -property:RuntimeIdentifier=rid")]
[InlineData(new string[] { "-c", "config" }, "-target:Build -property:Configuration=config")]
[InlineData(new string[] { "--configuration", "config" }, "-target:Build -property:Configuration=config")]
[InlineData(new string[] { "--version-suffix", "mysuffix" }, "-target:Build -property:VersionSuffix=mysuffix")]
[InlineData(new string[] { "--no-dependencies" }, "-target:Build -property:BuildProjectReferences=false")]
[InlineData(new string[] { "-r", "rid" }, @"-target:Build -property:RuntimeIdentifier=\""rid\""")]
[InlineData(new string[] { "--runtime", "rid" }, @"-target:Build -property:RuntimeIdentifier=\""rid\""")]
[InlineData(new string[] { "-c", "config" }, @"-target:Build -property:Configuration=\""config\""")]
[InlineData(new string[] { "--configuration", "config" }, @"-target:Build -property:Configuration=\""config\""")]
[InlineData(new string[] { "--version-suffix", "mysuffix" }, @"-target:Build -property:VersionSuffix=\""mysuffix\""")]
[InlineData(new string[] { "--no-dependencies" }, @"-target:Build -property:BuildProjectReferences=\""false\""")]
[InlineData(new string[] { "-v", "diag" }, "-target:Build -verbosity:diag")]
[InlineData(new string[] { "--verbosity", "diag" }, "-target:Build -verbosity:diag")]
[InlineData(new string[] { "--no-incremental", "-o", "myoutput", "-r", "myruntime", "-v", "diag", "/ArbitrarySwitchForMSBuild" },
"-target:Rebuild -property:OutputPath=myoutput -property:RuntimeIdentifier=myruntime -verbosity:diag /ArbitrarySwitchForMSBuild")]
@"-target:Rebuild -property:OutputPath=\""myoutput\"" -property:RuntimeIdentifier=\""myruntime\"" -verbosity:diag /ArbitrarySwitchForMSBuild")]
public void MsbuildInvocationIsCorrect(string[] args, string expectedAdditionalArgs)
{
expectedAdditionalArgs = (string.IsNullOrEmpty(expectedAdditionalArgs) ? "" : $" {expectedAdditionalArgs}");
@ -43,10 +43,10 @@ namespace Microsoft.DotNet.Cli.MSBuild.Tests
}
[Theory]
[InlineData(new string[] { "-f", "tfm" }, "-target:Restore", "-target:Build -property:TargetFramework=tfm")]
[InlineData(new string[] { "-f", "tfm" }, "-target:Restore", @"-target:Build -property:TargetFramework=\""tfm\""")]
[InlineData(new string[] { "-o", "myoutput", "-f", "tfm", "-v", "diag", "/ArbitrarySwitchForMSBuild" },
"-target:Restore -property:OutputPath=myoutput -verbosity:diag /ArbitrarySwitchForMSBuild",
"-target:Build -property:OutputPath=myoutput -property:TargetFramework=tfm -verbosity:diag /ArbitrarySwitchForMSBuild")]
@"-target:Restore -property:OutputPath=\""myoutput\"" -verbosity:diag /ArbitrarySwitchForMSBuild",
@"-target:Build -property:OutputPath=\""myoutput\"" -property:TargetFramework=\""tfm\"" -verbosity:diag /ArbitrarySwitchForMSBuild")]
public void MsbuildInvocationIsCorrectForSeparateRestore(
string[] args,
string expectedAdditionalArgsForRestore,