Escaping quotes in powershell command issued by batch file - powershell

I've been trying to get a PowerShell command to create a shortcut working in a batch file but can't get it to actually put the quotes I need in the shortcut. I've used this command in other batch files just fine, but the quotes are messing it up. I've tried "", """, """", ", ", \", `", and pretty much every variation I can think of and nothing has worked. I need the shortcut to be this:
"C:\Program Files\OpenVPN\bin\openvpn-gui.exe" --connect "mullvad.ovpn"
And here's what I've been trying, of course with the numerous variations:
powershell "$s=(New-Object -COM WScript.Shell).CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\OpenVPN GUI.lnk');$s.TargetPath='"C:\Program Files\OpenVPN\bin\openvpn-gui.exe" --connect "mullvad.ovpn"';$s.Save()"
But it either just creates a shortcut to this:
"C:\Program Files\OpenVPN\bin\openvpn-gui.exe --connect mullvad_us_chi.ovpn"
or, more often, it errors because the syntax is wrong with my various attempts. So how do I get PowerShell to do what I want here?

Your main issue is that you aren't correctly creating a shortcut.
In order to do so, you should first of all use an additional property. Your TargetPath should be the executable, and the rest, its Arguments:
Then your command should look a little more like this:
"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -Command "$s = (New-Object -COM WScript.Shell).CreateShortcut(\"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\OpenVPN GUI.lnk\");$s.TargetPath=\"C:\Program Files\OpenVPN\bin\openvpn-gui.exe\";$s.Arguments=\"--connect `\"mullvad.ovpn`\"\";$s.Save()"
I rarely use single quotes, but if you prefer them then perhaps this would also work for you:
"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -Command "$s = (New-Object -COM WScript.Shell).CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\OpenVPN GUI.lnk');$s.TargetPath='C:\Program Files\OpenVPN\bin\openvpn-gui.exe';$s.Arguments='--connect \"mullvad.ovpn\"';$s.Save()"

Related

Pass whole script as argument to powershell.exe

I once found a script to easily change my Wallpaper if I use multiple ones.
set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.SendKeys("^ ")
WshShell.SendKeys("+{F10}")
WshShell.SendKeys("n")
WshShell.SendKeys("{ENTER}")
However I need a separate link that calls the script.
Now I wonder if I can pass these multiple lines of code as parameter to powershell.exe directly.
I did read that I can allign multiple lines using ; and tried building the one-liner, however it doesn't run...or rather it does run, there is no feedback, nothing changes. If I paste the command line into a running powershell instance it just exits.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden -Command "set WshShell = WScript.CreateObject('WScript.Shell'); WshShell.SendKeys('^ '); WshShell.SendKeys('+{F10}'); WshShell.SendKeys('n'); WshShell.SendKeys('{ENTER}')"
I basically just concatenated them and replaced the double quotes with single quotes to escape the special characters, so why does it not work as the separate script?
In PowerShell:
$WSH = New-Object -ComObject 'WScript.Shell'
$WSH.SendKeys('^ ')
$WSH.SendKeys('+{F10}')
$WSH.SendKeys('n')
$WSH.SendKeys('{ENTER}')
Save this as a script (Filename.ps1), and call it from a .bat or .cmd file:
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -File "path\filename.ps1"
Alternatively, as a one-liner in a command file:
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -Command "$WSH = New-Object -ComObject 'WScript.Shell';$WSH.SendKeys('\^ ');$WSH.SendKeys('+{F10}');$WSH.SendKeys('n');$WSH.SendKeys('{ENTER}')"

PowerShell keep multiple spaces

While implementing the suggestions in the topic Drag and Drop to a Powershell script we discovered that PowerShell consolidates multiple spaces into one. This is blocking us from dragging and dropping files through Windows Explorer into .bat/.ps1 constructs with multiple spaces.
This can easily be verified by the following command:
powershell -command "& echo {"a a"}"
This will result in:
a a
whereas the following result is expected:
a a
How can this be achieved?
Please note that your provided solution must fit into the Windows Explorer drag-and-drop .bat -> .ps1 flow. Currently in the .bat file we have:
powershell.exe -Command "& '%PSScript%' '%*'"
which obviously results in PowerShell stripping the duplicate spaces.
try this
powershell -command "& echo 'a a'"
Please Check if below solves your problem.
"Replace 10 with number of spaces you want."
powershell -command '& echo {"a"' ''.padleft(10, ' ') '"a"}'
output:
a a
works for me with a simple :
write-host a (" ") a

Invoke-Expression -Command Not Finding File Even Though It Exists

all,
I am trying to run a command in Power Shell and I am told the file does not exist as it stands right now for the Power Shell code. If I do the same in DOS, it finds the file and executes correctly. The only difference is that there is an additional open and closed double quote around the file name. Can this be done in Power Shell the same way? If so, how can this be done as I am not familiar with Power Shell.
DOS:
IF EXISTS F:\lvcecstos.CSV F:\LaserVault\ContentExpress\ContentExpress.exe /CID:1 /CSV:<b>"F:\lvcecstos.CSV"</b> /ClearSubscription
Power Shell:
Invoke-Expression -Command "F:\LaserVault\ContentExpress\ContentExpress.exe /CID:1 /CSV:<b>F:\lvcecstos.csv</b> /ClearSubscription"
Thanks in advance for any suggestions. I am told by the Laservault engineers that created this software package that we use that the double quotes around the file name is required. Doesn't make sense to me as to why though, but this is something I am unable to get around.
You can add double quotes around the file path as follows:
Invoke-Expression -Command 'F:\LaserVault\ContentExpress\ContentExpress.exe /CID:1 /CSV:"F:\lvcecstos.csv" /ClearSubscription';
Notice how the command is wrapped in single quotes instead of double quotes.
Ultimately, it depends on how the ContentExpress.exe program is interpreting the file path, though. For all you know, it could be appending the valued passed to "CSV" to the "current working directory."
You can also use the Start-Process cmdlet, instead of Invoke-Expression or Invoke-Command.
$Program = 'F:\LaserVault\ContentExpress\ContentExpress.exe';
$ArgumentList = '/CID:1 /CSV:"F:\lvcecstos.csv" /ClearSubscription';
Start-Process -Wait -NoNewWindow -FilePath $Program -ArgumentList $ArgumentList;
If you have PowerShell v3 (which you should) you could use the "magic parameter" --% (see here).
& F:\LaserVault\ContentExpress\ContentExpress.exe --% /CID:1 /CSV:"F:\lvcecstos.csv" /ClearSubscription
Otherwise trying to preserve double quotes around arguments could become very, very painful. See for instance this answer to a similar question.
$lvcecstos = "F:\lvcecstos.CSV"
If(Test-Path $lvcecstos)
{
Invoke-Expression -Command "& F:\LaserVault\ContentExpress\ContentExpress.exe /CID:1 /CSV:$lvcecstos /ClearSubscription"
}

How to run a command correct for CMD in remote box using PowerShell?

I need to run a remote command with help of PowerShell from CMD. This is the command I call from CMD:
powershell -command "$encpass=convertto-securestring -asplaintext mypass -force;$cred = New-Object System.Management.Automation.PSCredential -ArgumentList myuser,$encpass; invoke-command -computername "REMOTE_COMPUTER_NAME" -scriptblock {<command>} -credential $cred;"
in place of <command> (including < and > signs) can be any command which can be run in cmd.exe. For example there can be perl -e "print $^O;" or echo "Hello World!" (NOTE: There cannot be perl -e 'print $^O;', because it is incorrect command for CMD due to the single quotes). So it appears the command perl -e "print $^O;" and any other command which contains double quotes doesn't handled as expected. Here I expect it to return OS name of remote box from perl's point of view, but it prints nothing due to obscure handling of double quotes by PowerShell and/or CMD.
So the question is following, how to run command correct for CMD in remote box using PowerShell?
There are several possible problems with the command line in the OP. If the command line in the OP is being executed from Powershell itself the $encpass and $cred will get substituted before the (sub-instance) of powershell is invoked. You need to use single quotes or else escape the $ signs, for example:
powershell -command "`$encpass=2"
powershell -command '$encpass=2'
If, instead of using Powershell, the command line is executed from CMD, then ^ has to be escaped, because it is the CMD escape character.
And quoting " is a good idea as well. In a few tests that I did I had to use unbalanced quotes to get a command to work, for example, from powershell:
powershell -command "`$encpass=`"`"a`"`"`"; write-host `$encpass"
worked, but balanced quotes didn't.
To avoid all this, probably the most robust way to do this is given in powershell command line help: powershell -?:
# To use the -EncodedCommand parameter:
$command = 'dir "c:\program files" '
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)
powershell.exe -encodedCommand $encodedCommand
However there is a new feature in PS 3.0 that is also supposed to help, but I don't think it will be as robust. Described here: http://blogs.msdn.com/b/powershell/archive/2012/06/14/new-v3-language-features.aspx, near the middle of the blog.

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.