15

I want to execute a cmd on PowerShell and this command uses semicolons. Then PowerShell interprets it as multiple commands. How do I make PowerShell ignore the semicolons and execute my command how a unique command?

Example:

Invoke-Expression "msbuild /t:Build;PipelinePreDeployCopyAllFilesToOneFolder /p:Configuration=Debug;_PackageTempDir=$TargetFolder $WebProject"

Another example:

Invoke-Expression "test`;test2"

And the second example response:

The term 'test' is not recognized as the name of a cmdlet, function, script file, or operable program. Check
the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:6
+ teste <<<< ;teste2
    + CategoryInfo          : ObjectNotFound: (teste:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

The term 'test2' is not recognized as the name of a cmdlet, function, script file, or operable program. Chec
k the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:13
+ teste;teste2 <<<<
    + CategoryInfo          : ObjectNotFound: (teste2:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wallybh
  • 934
  • 1
  • 11
  • 28

6 Answers6

31

Just escape the semicolon on the command line:

msbuild /t:Build`;PipelinePreDeployCopyAllFilesToOneFolder /p:Configuration=Debug`;_PackageTempDir=$TargetFolder $WebProject

I do this all the time with the tf.exe utility:

tf.exe status . /r /workspace:WORK`;johndoe

FYI, this issue has been heavily voted up on Connect. PowerShell v3 addresses this issue with the new --% operator:

$env:TargetFolder = $TargetFolder
msbuild $WebProject --% /t:Build;PipelinePreDeployCopyAllFilesToOneFolder /p:Configuration=Debug;_PackageTempDir=%TargetFolder%
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
5

The easiest way to ignore a semicolon? Simply use a single quote versus double quote!

In PowerShell, the type of quote you use matters. A double quote will let PowerShell do string expansion (so if you have a variable $something = someprogram.exe, and run "$something", PowerShell substitutes in "someprogram.exe").

If you don't need string substitution/variable expansion then just use single-quotes. PowerShell will execute single-quoted strings exactly as listed.

Another option if you want to use string expansion is to use a here-string instead. A here string is just like a regular string, however it begins and ends with an @ sign on its own separate line, like so:

$herestring = @"
Do some stuff here, even use a semicolon ;
"@

This is a best-of-both-worlds scenario, as you can use your fancy characters and have them work, but still get Variable expansion, which you do not get with single-quotes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
FoxDeploy
  • 12,569
  • 2
  • 33
  • 48
1

Try using Start-Process to run MSbuild then pass the rest as a value with -Argument.

Jeffery Hicks
  • 947
  • 5
  • 8
  • Yes it works. But I could not retrieve the MSbuild exit code. – wallybh Apr 13 '12 at 12:35
  • @wallybh To get the exit code with Start-Process you have to do 2 things, use the -PassThru param and assign the output to a variable and check its ExitCode property and use the -Wait param. – Andy Arismendi Apr 13 '12 at 15:44
1

Here is an example of the way I use to call native EXE files with commented usage and parameters:

# Gen-CACert.ps1
clear-host

$scriptBlock = {.\Makecert -n `"CN=PowerShell Authorite de certification`"  <# Sujet du certificat (conforme à la norme X50 #>`
                           -a sha1                                          <# Algorithme utilisé #>`
                           -eku 1.3.6.1.5.5.7.3.3                           <# Option du certificat (signature de code) #>`
                           -r                                               <# Certificat auto signé #>`
                           <# -ss `"$($args[0])`"                              Dossier de stockage du certificat #>`
                           -ss `"root`"                                     <# Dossier de stockage du certificat #>`
                           -sr localMachine                                 <# Magasin de stockage localmachine ou currentuser (defaut) #>`
                           -sv `"$($args[0]).pvk`"                          <# Nom du fichier contenant la clef privée #>`
                           `"$($args[0]).cer`"}                             <# Nom du fichier certificat #>

$PoshCARoot = "PoshCARoot"
Invoke-Command -ScriptBlock $scriptBlock  -ArgumentList $PoshCARoot
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JPBlanc
  • 70,406
  • 17
  • 130
  • 175
0

As an alternative to Start-Process, you can just call the command as you would similarly call it using cmd.exe using the call operator &:

& msbuild /t:Build;PipelinePreDeployCopyAllFilesToOneFolder /p:Configuration=Debug;_PackageTempDir=$TargetFolder $WebProject
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andy Arismendi
  • 50,577
  • 16
  • 107
  • 124
  • Great! With this and the escape char I solved my problem. Thanks! – wallybh Apr 13 '12 at 12:37
  • 4
    @wallybh Cool, you should also be able to quote the arguments too like this `"/t:Build;PipelinePreDeployCopyAllFilesToOneFolder"` to not have to escape the semi colon. – Andy Arismendi Apr 13 '12 at 15:48
  • 1
    Just escape it will ya? – Aliostad Feb 12 '15 at 09:36
  • This does not work for me when running in PowerShell window, what am I doing wrong? Neither does escaping using ` – nietras Dec 08 '21 at 12:17
  • That is the following `& dotnet build /m /verbosity:minimal /nologo -c Release /p:DefineConstants=PRE1`;PRE2` fails with MSBUILD : error MSB1006: Property is not valid. Switch: PRE2 – nietras Dec 08 '21 at 12:18
  • 1
    Not using escape just means "PRE2" is called after as it's seen as separate command – nietras Dec 08 '21 at 12:20
  • 1
    Which means `msbuild /p:Configuration=TEST`;TEST2` fails too with MSBUILD : error MSB1006: Property is not valid. Switch: TEST2 – nietras Dec 08 '21 at 12:25
  • Okay, not sure why none of the tricks mentioned here work but writing `dotnet build /p:DefineConstants="TEST TEST2"` works, this is parsed as two different preprocessor definitions – nietras Dec 08 '21 at 12:30
0

You can use comma as the separator:

msbuild /t:Build,PipelinePreDeployCopyAllFilesToOneFolder /p:Configuration=Debug,_PackageTempDir=$TargetFolder $WebProject
bvamos
  • 773
  • 7
  • 10