How do you put PowerShell code into a batch/cmd file without having to also have a separate .ps1 file?
I got this question recently from one of our field guys and thought I would blog about the trick publicly.
This is actually very simple:
- Take the PowerShell script.
- Remove all the comments ( everything that starts with #).
- Put ; at the end of each line.
- Remove all line breaks.
- Supply the string you get as the -command parameter for powershell.exe.
The reason for all of this is that powershell.exe (the executable which allows you to run any PowerShell code allows you to either start an external .ps1 script file (which often creates additional complexity of having to maintain and ship 2 files) or execute a single line of PowerShell code as the -command parameter. Hence the requirement to flatten the script and turn something like this:
#iterate numbers 1 through 10
1..10 | foreach-object {
# just output them
"Current output:"
$_
}
into:
powershell.exe -command "1..10 | foreach-object { "Current output:"; $_; }
See also this blog post by MoW on making PowerShell pass its exit code to command files.
Tags: KB, Knowledge Base, Known Issues, PowerShell
Subscribe by email




As far as I can see, the double quotes will get the command interpreter confused, so you will have to escape them – as in
powershell.exe -command “1..10 | foreach-object { \”Current ou
tput:\”; $_; }”
If you don’t escape them you get the message:
The term ‘Current’ is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
At line:1 char:33
+ 1..10 | foreach-object { Current <<<< output:; $_; }
You also missed off the closing double quote, but that didn’t seem to make a difference.
Thanks for the post though, it could be useful for short scripts.
powershell.exe -command “1..10 | foreach-object { ‘Current output:’; $_; }”
One way to completely avoid the quoting problem is to use the -encoded parameter on powershell.exe. This takes a Base64 encoded string, decodes it and then executes it. For example, we’ll put some code in a script block (since it will be syntax checked) instead of a simple string:
PS (41) > $code = {
>> #iterate numbers 1 through 10
>> 1..10 | foreach-object {
>> # just output them
>> “Current output:”
>> $_
>> }
>>
>> }
>>
Now encode the command:
PS (42) > $encoded = [convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($code))
The result of this looks like:
PS (43) > $encoded
MQAuAC4AMQAwACAAfAAgAGYAbwByAGUAYQBjAGgALQBvAGIAagBlAGMAdAAgAHsACgAjACAAagB1AHMAdAAgAG8AdQB0AHAAdQB0ACAAdABoAGUAbQAKACI
AQwB1AHIAcgBlAG4AdAAgAG8AdQB0AHAAdQB0ADoAIgAKACQAXwAKAH0ACgA=
Then run it:
(CXT: win7) (STA-ISS) (44) > powershell -encoded MQAuAC4AMQAwACAAfAAgAGYAbwByAGUAYQBjAGgALQBvAGIAagBlAGMAdAAgAHsACgAjACA
AagB1AHMAdAAgAG8AdQB0AHAAdQB0ACAAdABoAGUAbQAKACIAQwB1AHIAcgBlAG4AdAAgAG8AdQB0AHAAdQB0ADoAIgAKACQAXwAKAH0ACgA=
BTW – PowerShell has built-in support for this so when you call powershell from powershell with a scriptblock, the script block is automatically encoded and passed to the child process:
(CXT: win7) (STA-ISS) (46) > powershell { “Hi there. Today is ” + (get-date).DayOfWeek }
Hi there. Today is Saturday
-bruce
——————–
Principal Developer, Windows PowerShell Team
Microsoft