Archive for June 27th, 2008

PowerShell script in a .bat file

How do you put PowerShell code into a batch/cmd file without having to also have a separate .ps1 file? (If you can have an external .ps1 file – you just invoke powershell.exe and supply the path to the script file as parameter.)

I got this question recently from one of our field guys and thought I would blog about the trick publicly.

The problem is that PowerShell syntax can obviously have elements that .bat files cannot stand, and that you cannot pass multiline script as powershell.exe parameter.

There are actually a couple of ways to do so:

1. Encode the script:

As Bruce points here PowerShell has the -EncodedCommand parameter, which lets you pass any PowerShell code as base-64-encoded string.

So if you have some sort of script, like this:

#iterate numbers 1 through 10
1..10 | foreach-object {
# just output them
"Current output:"
$_
}

You simply (in PowerShell command-line or script) put it in curcly brackets and assign (as scriptblock) to a variable:

$code = {
    #iterate numbers 1 through 10
    1..10 | foreach-object {
    # just output them
    "Current output:"
    $_
    }
}

Then use this PowerShell command to get the encoded version:

[convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($code))

Then copy/paste the output of the command to your batch file:

powershell.exe -EncodedCommand DQAKAAkAIwBpAHQAZQByAGEAdABlACAAbgB1AG0AYgBlAHIAcwAgADEAIAB0AGgAcgBvAHUAZwBoACAAMQAwAA0ACgAJADEALgAuADEAMAAgAHwAIABmAG8AcgBlAGEAYwBoAC0AbwBiAGoAZQBjAHQAIAB7AA0ACgAJACMAIABqAHUAcwB0ACAAbwB1AHQAcAB1AHQAIAB0AG
gAZQBtAA0ACgAJACIAQwB1AHIAcgBlAG4AdAAgAG8AdQB0AHAAdQB0ADoAIgANAAoACQAkAF8ADQAKAAkAfQANAAoA

2. Keep the code as PowerShell but turn it to a string:

If the first approach for whatever reason does not work for you (e.g. you care about readability), you can try to flatten the script and pass it as a string:

  1. Take the PowerShell script.
  2. Remove all the comments ( everything that starts with #).
  3. Put ; at the end of each line.
  4. Remove all line breaks.
  5. 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: , , ,


My Recent Tweets

Legal

The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

June 2008
M T W T F S S
« May   Jul »
 1
2345678
9101112131415
16171819202122
23242526272829
30  

%d bloggers like this: