2

I can execute the following command in PowerShell:

msbuild "c:\some\spaced path\project.sln" /p:MvcBuildViews=False /p:OutDir="c:\\some\\spaced path\\deploy\\Package\\"

The paths are changed, but the real ones also contain a spaced component. The double-slash is a trick from e.g. this answer.

If I run that directly, msbuild understands the path. However, it needs to run in psake like this:

exec { msbuild $SolutionFile "/p:MvcBuildViews=False;OutDir=$OutputDir" }

That works if the path has no spaces, but I want to adapt it to work with spaces (for both the sln path and OutDir). I've tried, but I couldn't figure out the escaping.

EDIT:

To clarify, it also works if I hard-code the full path in psake:

exec { msbuild "c:\some\spaced path\project.sln" /p:MvcBuildViews=False /p:OutDir="c:\\some\\spaced path\\deploy\\Package\\" }

However, it needs to use the OutputDir variable (which is not double-slash escaped). So, I add a temporary variable for that, then try to construct the command line.:

$double_slashed_dir = $OutputDir.Replace('\', '\\');
write $double_slashed_dir;
exec { msbuild $SolutionFile /p:MvcBuildViews=False "/p:OutDir=`"$double_slashed_dir`"" }

This doesn't work (I've tried a couple variations). With the above I get "MSB1008: Only one project can be specified."

Community
  • 1
  • 1
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • Just in case, the commands are not the same (the working one has two `/p:...`), do you try exactly the same command with psake? – Roman Kuzmin Oct 16 '11 at 21:59
  • Also, I created a test soultion, used all paths with spaces and exactly your command in psake. It worked. – Roman Kuzmin Oct 16 '11 at 23:05
  • @Roman, I believe I tried variations of both (and the original had them together), but you're right that I should be consistent. I'll stick to the separate version. Did the code you actually got working in psake have variables? I can get it working through exec hard-coded, but not with substitutions. – Matthew Flaschen Oct 17 '11 at 00:34
  • Yes, it worked with variables. Task body is ` $SolutionFile = "C:\TEMP\spaced path\ConsoleApplication1.sln" $OutputDir = "C:\\TEMP\\spaced path2\\" exec { msbuild $SolutionFile "/p:MvcBuildViews=False;OutDir=$OutputDir" }` – Roman Kuzmin Oct 17 '11 at 06:38
  • @Roman, wow, thanks. That works. I thought I tried that. I tried other syntax variations, including that with the original path (not double-slashed). But I guess I never tried it with `double_slashed_dir`. Post that as an answer, and I'll accept it. – Matthew Flaschen Oct 17 '11 at 06:52

5 Answers5

2

This variation worked for me (double slashes and trailing slashes in $OutputDir seem to be important):

task build {
    $SolutionFile = "C:\TEMP\spaced path\ConsoleApplication1.sln"
    $OutputDir = "C:\\TEMP\\spaced path2\\"
    exec { msbuild $SolutionFile "/p:MvcBuildViews=False;OutDir=$OutputDir" }
}
Roman Kuzmin
  • 40,627
  • 11
  • 95
  • 117
0

You want to put quotes around your OutDir, but putting single quotes will confuse the command shell parser due to the other quotes in your argument, so you need to escape those quotes by double quoting them:

exec { msbuild $SolutionFile "/p:MvcBuildViews=False;OutDir=`"`"$OutputDir`"`"" }
zdan
  • 28,667
  • 7
  • 60
  • 71
  • Unfortunately, MSBuild is still splitting on the space, giving the error "Only one project can be specified." I made sure the variable (`$OutputDir` in your answer) contained a double-slashed path. However, it doesn't work with single slashes either. – Matthew Flaschen Oct 13 '11 at 21:14
0

I tried this with the following and it worked. The only thing i added is a double quote(") after the msbuild command. This is what I have tried :

properties{
    $build_Dir="F:\projects\tweet sharp\src";
}

Task Default -depends Build


Task Build {
        Exec { msbuild "$build_Dir\TweetSharp.sln" }
}

As you can see, the build dir includes a space('tweet sharp'). Just try enclosing all the parameters of your msbuild task within double quotes and check if it works.

gprasant
  • 15,589
  • 9
  • 43
  • 57
0

I got it working with Invoke-Expression:

$double_slashed_dir = $OutputDir.Replace('\', '\\');
$msbuild_command = 'msbuild "' + $SolutionFile + '" /p:MvcBuildViews=False /p:OutDir="' + $double_slashed_dir + '"';
exec { Invoke-Expression $msbuild_command }

I consider this a little hackish. It requires string concatenation, and as far as I can tell, Invoke-Expression is basically eval (though it should be safe as there is no user input involved here).

So I'm leaving the question open for now in the hopes of a better answer. It should show the variables clearly.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • I agree; though this solves the problem, there should be more elegant ways of solving this without actually forming the entire command text. @matt – gprasant Oct 17 '11 at 03:58
  • yeah. I thought of a similar approach doing this. Before actually running the tasks, rename the appropriate dirs to neutralise the spaces(replace the spaces with _ or whatever) and then after running the tasks, convert the dirs back to their original form. Yet another hack - but not even remotely close to an elegant solution. – gprasant Oct 17 '11 at 04:21
0

I've been struggling this this too, and the answer I finally came up with is: quote the entire switch, not just the path.

So, for example:

$buildBranch = "a path/with multiple/spaces in/"

# Use an array of arguments for common build settings, note: no trailing slash after Apps
$buildSettings = (
    ('"/Property:SolutionDir=' + $buildBranch + '\My Apps"'),
    '/t:Build', 
    '/p:PlatformTarget=x86', 
    '/p:Configuration=Release')

# Combine the common build settings with the specific project
$arg = $buildSettings + @('"' + $buildBranch + '\My Apps\MyProjectPath\MyProject.vcxproj"')

exec {
    &$msbuild $arg
}

The key difference between this and all my other attempts is in the quoting of the /Property switch.

I initially did:

'/Property:SolutionDir="' + $buildBranch + '\My Apps"'

Note that the double quote I want to pass to msbuild comes after the switch name and before the value.

MsBuild would see:

/Property:SolutionDir="some path\with spaces\My Apps"

This didn't work.

I changed it to:

'"/Property:SolutionDir=' + $buildBranch + '\My Apps"'

MsBuild would see:

"/Property:SolutionDir=some path\with spaces\My Apps"

This did work!

Rob
  • 4,210
  • 3
  • 30
  • 25