Run MSBuild from PowerShell can't find project file [duplicate] - powershell

I've just tested this on PowerShell v1.0. Setup is as follows:
Id CommandLine
-- -----------
1 $msbuild = "C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe"
4 $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"
.
This line fails with an unintuitive error message:
Id CommandLine
-- -----------
5 & $msbuild $a
.
This line fails because & expects the first argument to be the command itself.
Id CommandLine
-- -----------
10 & "$msbuild $a"
.
This line works:
Id CommandLine
-- -----------
16 cmd /c "$msbuild $a"
.
Please explain. I'm more interested in why the & syntax isn't working, than an MSBuild-specific workaround.

Ugh.
$collectionOfArgs = #("C:\some\project\or\other\src\Solution.sln",
"/target:Clean", "/target:Build")
& $msbuild $collectionOfArgs
This works. & takes a collection of arguments, so you must split up strings containing multiple arguments into a collection of string arguments.

The issues you are seeing results from PowerShell parsing arguments. In the first example, when PowerShell sees $a it passes it as a single parameter msbuild. We can see this using the echoargs utility from PSCX:.
PS> $a = "C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build"
PS> & echoargs $a
Arg 0 is <C:\some\project\or\other\src\Solution.sln /target:Clean /target:Build>
The second example is even worse because you are telling powershell to invoke "$echoargs $a" as the command name and it isn't a valid command name.
The third line works because CMD.exe gets the expanded form of "$echoargs $a" as a single argument which is parses and executes:
You have a couple of options here. First I do it this way:
PS> & $msbuild C:\some\project\or\other\src\Solution.sln `
/target:Clean /target:Build
The other option is to use Invoke-Expression like so:
PS> Invoke-Expression "$msbuild $a"
In general I try to be very careful with Invoke-Expression particularly if any part of the string that gets invoked is provided by the user.

You can also try using the free Invoke-MsBuild powershell script/module. This essentially gives you an Invoke-MsBuild PowerShell cmdlet that you can call instead of trying to invoke the msbuild.exe manually yourself.

That works well for me:
PS> cmd.exe /c 'C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe' /target:Clean /target:Build 'C:\some\project\or\other\src\Solution.sln'

Related

PowerShell script does not receive arguments no matter what

Trying to pass a single command line argument to a powershell script on Windows 7, but the script does not seem to recognize any arguments. It blasts through the first lines below
foreach($arg in $args)
{
Write-Host "Arg: $arg";
}
without outputting anything that I use on the command line and fails due to $args[0] being empty. However the rest of my script works if I instead hardcode the value of the variable I am trying to assign from the command line (it simply opens that file and does something).
I was inspired by this answer Passing a variable to a powershell script via command line specifically by the link in the accepted answer, and tried using param block but that did not print out anything as well
param(
[string]$fileName
)
Write-Host "Filename: [ $fileName ]";
when invoked like script.ps1 -filename SampleFile.txt
When I simply copy/paste the first script from the link into a new script:
Write-Host "Num Args:" $args.Length;
foreach ($arg in $args)
{
Write-Host "Arg: $arg";
}
and call it as 1.ps1 1 2 3 its output is only Num Args: 0.
What am I doing wrong?
PS: If it matters, here is version information
PS Z:\> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
I don't think it has anything to do with file linking, or registry hacking! :)
When running the example code, I also get no return when using your code. But when you make the parameter MANDATORY, it starts to display the arguments. Just need to format the PARAM Correctly, as in:
Param( [Parameter(Mandatory=$True)]
[string]$argument_one
)
Write-Host "Hello World $argument_one"
There you have it. Now you can call it from CMD as in:
powershell.exe -command "& 'thePSFile.ps1' -$argument_one 'it works now'"
I hope this Helps. I know, resurrected from the dead, but I thought some other people searching could see how they were almost there.
//ark
I have this problem as well. It took a while to recover what I have done previously.
First approach: make sure assoc, ftype and %PATHEXT% are set for powershell:
C:\>assoc .ps1
.ps1=Microsoft.PowerShellScript.1
C:\>ftype Microsoft.PowerShellScript.1
Microsoft.PowerShellScript.1="C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe" -noexit -file %1 %~2
C:\>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.py;.pyw;.ps1
But this likely will not work in windows 7 or higher.
Then edit the registry (all cautions apply here)
Edit the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Microsoft.PowerShellScript.1\Shell\0\Command
Set it from
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1"
To
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" %~2
Good luck!

Pass parameter from a batch file to a PowerShell script

In my batch file, I call the PowerShell script like this:
powershell.exe "& "G:\Karan\PowerShell_Scripts\START_DEV.ps1"
Now, I want to pass a string parameter to START_DEV.ps1. Let's say the parameter is w=Dev.
How can I do this?
Let's say you would like to pass the string Dev as a parameter, from your batch file:
powershell -command "G:\Karan\PowerShell_Scripts\START_DEV.ps1 Dev"
put inside your powershell script head:
$w = $args[0] # $w would be set to "Dev"
This if you want to use the built-in variable $args. Otherwise:
powershell -command "G:\Karan\PowerShell_Scripts\START_DEV.ps1 -Environment \"Dev\""
and inside your powershell script head:
param([string]$Environment)
This if you want a named parameter.
You might also be interested in returning the error level:
powershell -command "G:\Karan\PowerShell_Scripts\START_DEV.ps1 Dev; exit $LASTEXITCODE"
The error level will be available inside the batch file as %errorlevel%.
Assuming your script is something like the below snippet and named testargs.ps1
param ([string]$w)
Write-Output $w
You can call this at the commandline as:
PowerShell.Exe -File C:\scripts\testargs.ps1 "Test String"
This will print "Test String" (w/o quotes) at the console. "Test String" becomes the value of $w in the script.
When a script is loaded, any parameters that are passed are automatically loaded into a special variables $args. You can reference that in your script without first declaring it.
As an example, create a file called test.ps1 and simply have the variable $args on a line by itself. Invoking the script like this, generates the following output:
PowerShell.exe -File test.ps1 a b c "Easy as one, two, three"
a
b
c
Easy as one, two, three
As a general recommendation, when invoking a script by calling PowerShell directly I would suggest using the -File option rather than implicitly invoking it with the & - it can make the command line a bit cleaner, particularly if you need to deal with nested quotes.
Add the parameter declaration at the top of ps1 file
test.ps1
param(
# Our preferred encoding
[parameter(Mandatory=$false)]
[ValidateSet("UTF8","Unicode","UTF7","ASCII","UTF32","BigEndianUnicode")]
[string]$Encoding = "UTF8"
)
write ("Encoding : {0}" -f $Encoding)
Result
C:\temp> .\test.ps1 -Encoding ASCII
Encoding : ASCII
The answer from #Emiliano is excellent. You can also pass named parameters like so:
powershell.exe -Command 'G:\Karan\PowerShell_Scripts\START_DEV.ps1' -NamedParam1 "SomeDataA" -NamedParam2 "SomeData2"
Note the parameters are outside the command call, and you'll use:
[parameter(Mandatory=$false)]
[string]$NamedParam1,
[parameter(Mandatory=$false)]
[string]$NamedParam2

How do I pass a string parameter to Powershell for ConvertFrom-StringData from command line?

I'm having trouble running powershell with a script that should use a variable number of parameters.
The script file looks like this:
param( [string]$paramString )
$params = ConvertFrom-StringData $paramString
$params
Running the script directly in powershell yields the expected result:
[PS] C:\some\path>.\test.ps1 "a=foo `n b=bar `n c=moo"
Name Value
---- -----
c moo
a foo
b bar
Calling powershell from the command line with the same script and parameters shows this:
C:\some\path>powershell -nologo -file ./test.ps1 "a=foo `n b=bar `n c=moo"
Name Value
---- -----
a foo `n b=bar `n c=moo
It seems like the passed string is in some format so the ConvertFrom-StringData function is unable to parse it anymore.
Approach with -File is problematic because the parameter is not evaluated by cmd (at it is in PowerShell) and new lines equivalents are not expanded, they are passed in literally.
The problem can be solved if we still let PowerShell to do that by using -Command instead:
powershell -nologo -command "./test.ps1 ""a=foo `n b=bar `n c=moo"""
It is ugly: we have to double every inner " in the command. But it works. (The command can be defined by several parameters; I just prefer to use a single parameter: this way looks simpler to me).
Use single quote to pass parameters to powershell with script like this:
C:\some\path>powershell .\test.ps1 'a=foo' 'b=bar' 'c=moo'

How to run an EXE file in PowerShell with parameters with spaces and quotes

How do you run the following command in PowerShell?
C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass"
When PowerShell sees a command starting with a string it just evaluates the string, that is, it typically echos it to the screen, for example:
PS> "Hello World"
Hello World
If you want PowerShell to interpret the string as a command name then use the call operator (&) like so:
PS> & 'C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe'
After that you probably only need to quote parameter/argument pairs that contain spaces and/or quotation chars. When you invoke an EXE file like this with complex command line arguments it is usually very helpful to have a tool that will show you how PowerShell sends the arguments to the EXE file. The PowerShell Community Extensions has such a tool. It is called echoargs. You just replace the EXE file with echoargs - leaving all the arguments in place, and it will show you how the EXE file will receive the arguments, for example:
PS> echoargs -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass
Arg 0 is <-verb:sync>
Arg 1 is <-source:dbfullsql=Data>
Arg 2 is <Source=mysource;Integrated>
Arg 3 is <Security=false;User>
Arg 4 is <ID=sa;Pwd=sapass!;Database=mydb;>
Arg 5 is <-dest:dbfullsql=Data>
Arg 6 is <Source=.\mydestsource;Integrated>
Arg 7 is <Security=false;User>
Arg 8 is <ID=sa;Pwd=sapass!;Database=mydb; computername=10.10.10.10 username=administrator password=adminpass>
Using echoargs you can experiment until you get it right, for example:
PS> echoargs -verb:sync "-source:dbfullsql=Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;"
Arg 0 is <-verb:sync>
Arg 1 is <-source:dbfullsql=Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;>
It turns out I was trying too hard before to maintain the double quotes around the connection string. Apparently that isn't necessary because even cmd.exe will strip those out.
BTW, hats off to the PowerShell team. They were quite helpful in showing me the specific incantation of single & double quotes to get the desired result - if you needed to keep the internal double quotes in place. :-) They also realize this is an area of pain, but they are driven by the number of folks are affected by a particular issue. If this is an area of pain for you, then please vote up this PowerShell bug submission.
For more information on how PowerShell parses, check out my Effective PowerShell blog series - specifically item 10 - "Understanding PowerShell Parsing Modes"
UPDATE 4/4/2012: This situation gets much easier to handle in PowerShell V3. See this blog post for details.
I had spaces in both command and parameters, and this is what worked for me:
$Command = "E:\X64\Xendesktop Setup\XenDesktopServerSetup.exe"
$Parms = "/COMPONENTS CONTROLLER,DESKTOPSTUDIO,DESKTOPDIRECTOR,LICENSESERVER,STOREFRONT /PASSIVE /NOREBOOT /CONFIGURE_FIREWALL /NOSQL"
$Parms = $Parms.Split(" ")
& "$Command" $Parms
It's basically the same as Akira's answer, but this works if you dynamically build your command parameters and put them in a variable.
Just add the & operator before the .exe name.
Here is a command to install SQL Server Express in silence mode:
$fileExe = "T:\SQLEXPRADV_x64_ENU.exe"
$CONFIGURATIONFILE = "T:\ConfSetupSql2008Express.ini"
& $fileExe /CONFIGURATIONFILE=$CONFIGURATIONFILE
There are quite a few methods you can use to do it.
There are other methods like using the Call Operator (&), Invoke-Expression cmdlet etc. But they are considered unsafe. Microsoft recommends using Start-Process.
Method 1
A simple example
Start-Process -NoNewWindow -FilePath "C:\wamp64\bin\mysql\mysql5.7.19\bin\mysql" -ArgumentList "-u root","-proot","-h localhost"
In your case
Start-Process -NoNewWindow -FilePath "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -ArgumentList "-verb:sync","-source:dbfullsql=`"Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`"","-dest:dbfullsql=`"Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`"","computername=10.10.10.10","username=administrator","password=adminpass"
In this method you separate each and every parameter in the ArgumentList using commas.
Method 2
Simple Example
Start-Process -NoNewWindow -FilePath "C:\wamp64\bin\mysql\mysql5.7.19\bin\mysql" -ArgumentList "-u root -proot -h localhost"
In your case
Start-Process -NoNewWindow -FilePath "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -ArgumentList "-verb:sync -source:dbfullsql=`"Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`" -dest:dbfullsql=`"Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`",computername=10.10.10.10,username=administrator,password=adminpass"
This method is easier as it allows to type your parameters in one go.
Note that in powershell to represent the quotation mark ( " ) in a string you should insert the grave accent ( ` ) (This is the key above the Tab key in the US keyboard).
-NoNewWindow
parameter is used to display the new process in the current console window. By default Windows PowerShell opens a new window.
References : Powershell/Scripting/Start-Process
This worked for me:
& 'D:\Server\PSTools\PsExec.exe' #('\\1.1.1.1', '-accepteula', '-d', '-i', $id, '-h', '-u', 'domain\user', '-p', 'password', '-w', 'C:\path\to\the\app', 'java', '-jar', 'app.jar')
Just put paths or connection strings in one array item and split the other things in one array item each.
There are a lot of other options here: https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx
Microsoft should make this way simpler and compatible with command prompt syntax.
In case somebody is wondering how to just run an executable file:
..... > .\file.exe
or
......> full\path\to\file.exe
See this page:
https://slai.github.io/posts/powershell-and-external-commands-done-right/
Summary using vshadow as the external executable:
$exe = "H:\backup\scripts\vshadow.exe"
&$exe -p -script=H:\backup\scripts\vss.cmd E: M: P:
You can use:
Start-Process -FilePath "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe" -ArgumentList "-verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass"
The key thing to note here is that FilePath must be in position 0, according to the Help Guide. To invoke the Help guide for a commandlet, just type in Get-Help <Commandlet-name> -Detailed . In this case, it is Get-Help Start-Process -Detailed.
I was able to get my similar command working using the following approach:
msdeploy.exe -verb=sync "-source=dbFullSql=Server=THESERVER;Database=myDB;UID=sa;Pwd=saPwd" -dest=dbFullSql=c:\temp\test.sql
For your command (not that it helps much now), things would look something like this:
msdeploy.exe -verb=sync "-source=dbfullsql=Server=mysource;Trusted_Connection=false;UID=sa;Pwd=sapass!;Database=mydb;" "-dest=dbfullsql=Server=mydestsource;Trusted_Connection=false;UID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass
The key points are:
Use quotes around the source argument, and remove the embedded quotes around the connection string
Use the alternative key names in building the SQL connection string that don't have spaces in them. For example, use "UID" instead of "User Id", "Server" instead of "Data Source", "Trusted_Connection" instead of "Integrated Security", and so forth. I was only able to get it to work once I removed all spaces from the connection string.
I didn't try adding the "computername" part at the end of the command line, but hopefully this info will help others reading this now get closer to their desired result.
New escape string in PowerShell V3, quoted from New V3 Language Features:
Easier Reuse of Command Lines From Cmd.exe
The web is full of command lines written for Cmd.exe. These commands lines work often enough in PowerShell, but when they include certain characters, for example, a semicolon (;), a dollar sign ($), or curly braces, you have to make some changes, probably adding some quotes. This seemed to be the source of many minor headaches.
To help address this scenario, we added a new way to “escape” the parsing of command lines. If you use a magic parameter --%, we stop our normal parsing of your command line and switch to something much simpler. We don’t match quotes. We don’t stop at semicolon. We don’t expand PowerShell variables. We do expand environment variables if you use Cmd.exe syntax (e.g. %TEMP%). Other than that, the arguments up to the end of the line (or pipe, if you are piping) are passed as is. Here is an example:
PS> echoargs.exe --% %USERNAME%,this=$something{weird}
Arg 0 is <jason,this=$something{weird}>
I use this simple, clean and effective method.
I place arguments in an array, 1 per line. This way it is very easy to read and edit.
Then I use a simple trick of passing all arguments inside double quotes to a function with 1 single parameter. That flattens them, including arrays, to a single string, which I then execute using PS's 'Invoke-Expression'. This directive is specifically designed to convert a string to runnable command.
Works well:
# function with one argument will flatten
# all passed-in entries into 1 single string line
Function Execute($command) {
# execute:
Invoke-Expression $command;
# if you have trouble try:
# Invoke-Expression "& $command";
# or if you need also output to a variable
# Invoke-Expression $command | Tee-Object -Variable cmdOutput;
}
# ... your main code here ...
# The name of your executable app
$app = 'my_app.exe';
# List of arguments:
# Notice the type of quotes - important !
# Those in single quotes are normal strings, like 'Peter'
$args = 'arg1',
'arg2',
$some_variable,
'arg4',
"arg5='with quotes'",
'arg6',
"arg7 \ with \ $other_variable",
'etc...';
# pass all arguments inside double quotes
Execute "$app $args";
I tried all of the suggestions but was still unable to run msiexec.exe with parameters that contained spaces. So my solution ended up using System.Diagnostics.ProcessStartInfo:
# can have spaces here, no problems
$settings = #{
CONNECTION_STRING = "... ..."
ENTITY_CONTEXT = "... ..."
URL = "..."
}
$settingsJoined = ($settings.Keys | % { "$_=""$($settings[$_])""" }) -join " "
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.WorkingDirectory = $ScriptDirectory
$pinfo.FileName = "msiexec.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "/l* install.log /i installer.msi $settingsJoined"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$stdout = $p.StandardOutput.ReadToEnd()
$p.WaitForExit()
You can run exe files in powershell different ways. For instance if you want to run unrar.exe and extract a .rar file you can simply write in powershell this:
$extract_path = "C:\Program Files\Containing folder";
$rar_to_extract = "C:\Path_to_arch\file.rar"; #(or.exe if its a big file)
C:\Path_here\Unrar.exe x -o+ -c- $rar_to_extract $extract_path;
But sometimes, this doesn't work so you must use the & parameter as shown above:
For instance, with vboxmanage.exe (a tool to manage virtualbox virtual machines) you must call the paramterers outside of the string like this, without quotes:
> $vmname = "misae_unrtes_1234123"; #(name too long, we want to change this)
> & 'C:\Program Files\Oracle\VirtualBox\VBoxManage.exe' modifyvm $vmname --name UBUNTU;
If you want to call simply a winrar archived file as .exe files, you can also unzip it with the invoke-command cmdlet and a Silent parameter /S (Its going to extract itself in the same folder than where it has been compressed).
> Invoke-Command -ScriptBlock { C:\Your-path\archivefile.exe /S };
So there are several ways to run .exe files with arguments in powershell.
Sometimes, one must find a workaround to make it work properly, which can require some further effort and pain :) depending on the way the .exe has been compiled or made by its creators.
Cmd can handle running a quoted exe, but Powershell can't. I'm just going to deal with running the exe itself, since I don't have it. If you literally need to send doublequotes to an argument of an external command, that's another issue that's been covered elsewhere.
1) add the exe folder to your path, maybe in your $profile
$env:path += ';C:\Program Files\IIS\Microsoft Web Deploy\'
msdeploy
2) backquote the spaces:
C:\Program` Files\IIS\Microsoft` Web` Deploy\msdeploy.exe
This worked for me:
PowerShell.exe -Command "& ""C:\Some Script\Path With Spaces.ps1"""
The key seems to be that the whole command is enclosed in outer quotes, the "&" ampersand is used to specify another child command file is being executed, then finally escaped (doubled-double-) quotes around the path/file name with spaces in you wanted to execute in the first place.
This is also completion of the only workaround to the MS connect issue that -File does not pass-back non-zero return codes and -Command is the only alternative. But until now it was thought a limitation of -Command was that it didn't support spaces. I've updated that feedback item too.
http://connect.microsoft.com/PowerShell/feedback/details/750653/powershell-exe-doesn-t-return-correct-exit-codes-when-using-the-file-option
An alternative answer is to use a Base64 encoded command switch:
powershell -EncodedCommand "QwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAEkASQBTAFwATQBpAGMAcgBvAHMAbwBmAHQAIABXAGUAYgAgAEQAZQBwAGwAbwB5AFwAbQBzAGQAZQBwAGwAbwB5AC4AZQB4AGUAIAAtAHYAZQByAGIAOgBzAHkAbgBjACAALQBzAG8AdQByAGMAZQA6AGQAYgBmAHUAbABsAHMAcQBsAD0AIgBEAGEAdABhACAAUwBvAHUAcgBjAGUAPQBtAHkAcwBvAHUAcgBjAGUAOwBJAG4AdABlAGcAcgBhAHQAZQBkACAAUwBlAGMAdQByAGkAdAB5AD0AZgBhAGwAcwBlADsAVQBzAGUAcgAgAEkARAA9AHMAYQA7AFAAdwBkAD0AcwBhAHAAYQBzAHMAIQA7AEQAYQB0AGEAYgBhAHMAZQA9AG0AeQBkAGIAOwAiACAALQBkAGUAcwB0ADoAZABiAGYAdQBsAGwAcwBxAGwAPQAiAEQAYQB0AGEAIABTAG8AdQByAGMAZQA9AC4AXABtAHkAZABlAHMAdABzAG8AdQByAGMAZQA7AEkAbgB0AGUAZwByAGEAdABlAGQAIABTAGUAYwB1AHIAaQB0AHkAPQBmAGEAbABzAGUAOwBVAHMAZQByACAASQBEAD0AcwBhADsAUAB3AGQAPQBzAGEAcABhAHMAcwAhADsARABhAHQAYQBiAGEAcwBlAD0AbQB5AGQAYgA7ACIALABjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQA9ADEAMAAuADEAMAAuADEAMAAuADEAMAAsAHUAcwBlAHIAbgBhAG0AZQA9AGEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIALABwAGEAcwBzAHcAbwByAGQAPQBhAGQAbQBpAG4AcABhAHMAcwAiAA=="
When decoded, you'll see it's the OP's original snippet with all arguments and double quotes preserved.
powershell.exe -EncodedCommand
Accepts a base-64-encoded string version of a command. Use this parameter
to submit commands to Windows PowerShell that require complex quotation
marks or curly braces.
The original command:
C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass"
It turns into this when encoded as Base64:
QwA6AFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAEkASQBTAFwATQBpAGMAcgBvAHMAbwBmAHQAIABXAGUAYgAgAEQAZQBwAGwAbwB5AFwAbQBzAGQAZQBwAGwAbwB5AC4AZQB4AGUAIAAtAHYAZQByAGIAOgBzAHkAbgBjACAALQBzAG8AdQByAGMAZQA6AGQAYgBmAHUAbABsAHMAcQBsAD0AIgBEAGEAdABhACAAUwBvAHUAcgBjAGUAPQBtAHkAcwBvAHUAcgBjAGUAOwBJAG4AdABlAGcAcgBhAHQAZQBkACAAUwBlAGMAdQByAGkAdAB5AD0AZgBhAGwAcwBlADsAVQBzAGUAcgAgAEkARAA9AHMAYQA7AFAAdwBkAD0AcwBhAHAAYQBzAHMAIQA7AEQAYQB0AGEAYgBhAHMAZQA9AG0AeQBkAGIAOwAiACAALQBkAGUAcwB0ADoAZABiAGYAdQBsAGwAcwBxAGwAPQAiAEQAYQB0AGEAIABTAG8AdQByAGMAZQA9AC4AXABtAHkAZABlAHMAdABzAG8AdQByAGMAZQA7AEkAbgB0AGUAZwByAGEAdABlAGQAIABTAGUAYwB1AHIAaQB0AHkAPQBmAGEAbABzAGUAOwBVAHMAZQByACAASQBEAD0AcwBhADsAUAB3AGQAPQBzAGEAcABhAHMAcwAhADsARABhAHQAYQBiAGEAcwBlAD0AbQB5AGQAYgA7ACIALABjAG8AbQBwAHUAdABlAHIAbgBhAG0AZQA9ADEAMAAuADEAMAAuADEAMAAuADEAMAAsAHUAcwBlAHIAbgBhAG0AZQA9AGEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIALABwAGEAcwBzAHcAbwByAGQAPQBhAGQAbQBpAG4AcABhAHMAcwAiAA==
and here is how to replicate at home:
$command = 'C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql="Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;" -dest:dbfullsql="Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;",computername=10.10.10.10,username=administrator,password=adminpass"'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)
$encodedCommand
# The clip below copies the base64 string to your clipboard for right click and paste.
$encodedCommand | Clip
For the executable name, the new-alias cmdlet can be employed to avoid dealing with spaces or needing to add the executable to the $PATH environment.
PS> new-alias msdeploy "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe"
PS> msdeploy ...
To list or modify PS aliases also see
PS> get-alias
PS> set-alias
From Jeffery Hicks Aarticle
Other answers address the arguments.
If you just need to run a file in the current directory and don't feel like spelling out the entire path use Get-Location:
& "$(Get-Location)\example.exe" arg1 arg2 arg3
Note the & at the start. Spaced arguments are to be placed after the quotes.
I had the following code working perfect on my laptop:
& $msdeploy `
-source:package="$publishFile" `
-dest:auto,computerName="$server",includeAcls="False",UserName="$username",Password="$password",AuthType="$auth" `
-allowUntrusted `
-verb:sync `
-enableRule:DoNotDeleteRule `
-disableLink:AppPoolExtension `
-disableLink:ContentExtension `
-disableLink:CertificateExtension `
-skip:objectName=filePath,absolutePath="^(.*Web\.config|.*Environment\.config)$" `
-setParam:name=`"IIS Web Application Name`",value="$appName"
Then when I tried to run that directly on one server I started getting those errors "Unrecognized argument ...etc.... All arguments must begin with "-". "
After trying all possible workarounds (no success), I found out that Powershell on the server (Windows 2008 R2) was version 3.0, while my laptop has 5.0. (you can use "$PSVersionTable" to see version).
After upgrading Powershell to latest version it started working again.
So, I ran into a similar problem and chose to solve it this way instead:
Escape your quote (") characters with a backtick (`)
Surround your new expression with quotes (")
Using the call operator (&), issue the command invoke-expression on the new string
Example solution:
& { invoke-expression "C:\Program Files\IIS\Microsoft Web Deploy\msdeploy.exe -verb:sync -source:dbfullsql=`"Data Source=mysource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`" -dest:dbfullsql=`"Data Source=.\mydestsource;Integrated Security=false;User ID=sa;Pwd=sapass!;Database=mydb;`",computername=10.10.10.10,username=administrator,password=adminpass`"" }
To transfer a batch script using exiftool.exe to a powershell script I had the challange to give '-s, "-s and even ${Filename} to the command and on the other hand fill out variables in these parameters.
For a start: The replacement in using 'echochars' is brilliant. It clearly shows what is grouped as a single parameter and what ends up as the next parameter.
In powershell it is similar to perl (and unix scripting): the used quotes have their meaning.
strings between "-s. The string will be interpreted (variables filled)
Strings between '-s. The string will not be interpreted (or verry limited)
the escape character is ` (the back-quote). The next character looses its special meaning. Comparable with the \ (back stroke) on unix/linux/perl.
Some examples:
${ExifArgs} += "-if `"`${FileName} !~ /desktop.ini/i`""
${ExifArgs} += '-dateFormat "%Y\%Y%m\%Y%m%d_%H%M%S"'
${ExifArgs} += ('"' + "-FileName<${NewFotos}\${SourceName}\" + '${DateTimeOriginal}_${ImageWidth}x${ImageHeight}_${Model;s/ //g}_${FileName;s/^.*([0-9]{4})[^0-9].*$/\1/}.%e' + '"')
A call to echoargs with the above, produces the next output (numbers are hacked for privacy):
Arg 11 is <-if>
Arg 12 is <${FileName} !~ /desktop.ini/i>
Arg 13 is <-dateFormat>
Arg 14 is <%Y\%Y%m\%Y%m%d_%H%M%S>
Arg 15 is <-FileName<D:\Pictures\NewFotos\${DateTimeOriginal}_${ImageWidth}x${ImageHeight}_${Model;s/ //g}_${FileName;s/^.*([0-9]{4})[^0-9].*$/\1/}.%e>
See how the first line produces arg 11 and 12: the outher "-s are removed to store the entire line in the array. The inner "-s, quoted by the `-s are there to keep the argument together (while the -if is the previous argument)
The second shows arg 13 and 14: the use of "-s between '-s. No need to escape using `-s.
In the last line (producing arg 15): the single string is constructed by using powershell ()-s and +-s to concatenate a couple of strings to a single string. It uses both " and ' delimited strings to have som ${}-s filled out by powershell and some for exiftool.
And yes, some powershell special characters are transvered into the archuments.

powershell sending multiple parameter to a external command

I am trying to run a external exe from a powershell script.
This exe wants 4 parameters.
I have been trying every combo of invoke-item, invoke-command, & 'C:\program files\mycmd.exe myparam', made a shortcut in C:\ to get rid of the spaces in the path.
I can make it work with one parameter, but not with more. I get various errors.
To sum up, how do you send 4 parameters to an exe?
It's best if shown in longhand. Once you see what's going on, you can shorten it down by just using commas between each argument.
$arg1 = "filename1"
$arg2 = "-someswitch"
$arg3 = "C:\documents and settings\user\desktop\some other file.txt"
$arg4 = "-yetanotherswitch"
$allArgs = #($arg1, $arg2, $arg3, $arg4)
& "C:\Program Files\someapp\somecmd.exe" $allArgs
... shorthand:
& "C:\Program Files\someapp\somecmd.exe" "filename1", "-someswitch", "C:\documents and settings\user\desktop\some other file.txt", "-yetanotherswitch"
In the easy case, passing arguments to a native exe is as simple as using a built-in command:
PS> ipconfig /allcompartments /all
You can run into problems when you specify a full path to an EXE and that path contains spaces. For example if PowerShell sees this:
PS> C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\sn.exe -k .\pubpriv.snk
It interprets the command to be "C:\Program" and "Files\Microsoft" as the first parameter, "SDKs\Windows\v7.0\Bin\sn.exe" as the second parameter, etc. The simple solution is to put the path in a string use the invocation operator & to invoke the command named by the path e.g.:
PS> & 'C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\sn.exe' -k .\pubpriv.snk
The next area we run into problems with is when the arguments are complex and/or use characters that PowerShell interprets specially e.g.:
PS> sqlcmd -v user="John Doe" -Q "select '$(user)' as UserName"
This doesn't work and we can debug this by using a tool from the PowerShell Community Extensions called echoargs.exe which shows you exactly how the native EXE receives the arguments from PowerShell.
PS> echoargs -v user="John Doe" -Q "select '$(user)' as UserName"
The term 'user' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, ...
<snip>
Arg 0 is <-v>
Arg 1 is <user=John Doe>
Arg 2 is <-Q>
Arg 3 is <select '' as UserName>
Note that with Arg3 $(user) is interpreted & evaluated by PowerShell and results in an empty string. You can fix this problem and a good number of similar issues by using single quotes instead of double qoutes unless you really need PowerShell to evaluate a variable e.g.:
PS> echoargs -v user="John Doe" -Q 'select "$(user)" as UserName'
Arg 0 is <-v>
Arg 1 is <user=John Doe>
Arg 2 is <-Q>
Arg 3 is <select $(user) as UserName>
If all else fails, use a here string and Start-Process like so:
PS> Start-Process echoargs -Arg #'
>> -v user="John Doe" -Q "select '$(user)' as UserName"
>> '# -Wait -NoNewWindow
>>
Arg 0 is <-v>
Arg 1 is <user=John Doe>
Arg 2 is <-Q>
Arg 3 is <select '$(user)' as UserName>
Note if you are using PSCX 1.2 you will need to prefix Start-Process like so - Microsoft.PowerShell.Management\Start-Process to use PowerShell's built-in Start-Process cmdlet.