Passing parameters to -EncodedCommand

When invoking PowerShell from cmd/bat files -EncodedCommand is a great way to pass the actual PowerShell code to powershell.exe without worrying about escaping various special characters. This allows you to have just a single batch file (with no external PowerShell scripts whatsoever) which has PowerShell code right inside the file which looks something like:

powershell.exe -EncodedCommand DQAKAA0ACgAJACQAcABhAHIAYQBtAHMAIAA9ACAARwBlAHQALQBDAG8AbgB0AGUAbgB0ACAAJABlAG4AdgA6AFQARQBNAFAAXABwAGEAcgBhAG0AcwAuAHQAeAB0AA0ACgAJACIAUwBlAGUAIAB3AGgAaQBjAGgAIABwAGEAcgBhAG0AZQB0AGUAcgBzACAAUABvAHcAZQByAFMAaABlAGwAbAAgAGcAbwB0ADoAIAAkAHAAYQByAGEAbQBzACIADQAKAAkADQAKAA==

What I was recently pointed to, is that this approach has one limitation: how do you pass parameters to this PowerShell code? For example, say, cmd file gets parameters from command-line and wants to pass them to PowerShell – you obviously don’t know the values in advance so you cannot pre-encode them.

The easiest way that I found is: simply put the value from cmd file to a temporary file, and then read the file from PowerShell code.

So, for illustration purpose, my super-advanced PowerShell script will simply output the parameters:

    $params = Get-Content $env:TEMP\params.txt
    "See which parameters PowerShell got: $params"

As you can see, I am getting the parameters by reading the content of pre-defined file in %TEMP% location.

Now, let’s encode this by running:

$code = {

    $params = Get-Content $env:TEMP\params.txt
    "See which parameters PowerShell got: $params"
    
}

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

In my case I got:

DQAKAA0ACgAJACQAcABhAHIAYQBtAHMAIAA9ACAARwBlAHQALQBDAG8AbgB0AGUAbgB0ACAAJABlAG4AdgA6AFQARQBNAFAAXABwAGEAcgBhAG0AcwAuAHQAeAB0AA0ACgAJACIAUwBlAGUAIAB3AGgAaQBjAGgAIABwAGEAcgBhAG0AZQB0AGUAcgBzACAAUABvAHcAZQByAFMAaABlAGwAbAAgAGcAbwB0ADoAIAAkAHAAYQByAGEAbQBzACIADQAKAAkADQAKAA==

Now we are ready to put this into cmd:

echo %* > %TEMP%\params.txt

powershell.exe -EncodedCommand DQAKAA0ACgAJACQAcABhAHIAYQBtAHMAIAA9ACAARwBlAHQALQBDAG8AbgB0AGUAbgB0ACAAJABlAG4AdgA6AFQARQBNAFAAXABwAGEAcgBhAG0AcwAuAHQAeAB0AA0ACgAJACIAUwBlAGUAIAB3AGgAaQBjAGgAIABwAGEAcgBhAG0AZQB0AGUAcgBzACAAUABvAHcAZQByAFMAaABlAGwAbAAgAGcAbwB0ADoAIAAkAHAAYQByAGEAbQBzACIADQAKAAkADQAKAA==

Basically, all I do is write the command-line arguments which the batch file got to a temporary file, and then invoke our PowerShell script.

And here’s the proof that this actually works:


c:\Scripts>pass-params.cmd Here are my parameters!

c:\Scripts>echo Here are my parameters! 1>C:\Users\dsotniko\AppData\Local\Temp\
params.txt

c:\Scripts>powershell.exe -EncodedCommand DQAKAA0ACgAJACQAcABhAHIAYQBtAHMAIAA9A
CAARwBlAHQALQBDAG8AbgB0AGUAbgB0ACAAJABlAG4AdgA6AFQARQBNAFAAXABwAGEAcgBhAG0AcwAuA
HQAeAB0AA0ACgAJACIAUwBlAGUAIAB3AGgAaQBjAGgAIABwAGEAcgBhAG0AZQB0AGUAcgBzACAAUABvA
HcAZQByAFMAaABlAGwAbAAgAGcAbwB0ADoAIAAkAHAAYQByAGEAbQBzACIADQAKAAkADQAKAA==

See which parameters PowerShell got: Here are my parameters!

Now you can have a single batch file, encapsulating PowerShell code and capable of passing parameters to it!

5 Responses to “Passing parameters to -EncodedCommand”


  1. 1 Rich Beckett July 7, 2011 at 9:38 pm

    That was very interesting, helpful and instructive. I believe I saw a post recently regarding active Roles server where someone wanted to do exactly this, pass arguments which included curly braces. I now have amuch better understanding of some of the finer aspects of PowerShell

    Thanks.

  2. 2 Anonymous July 2, 2013 at 12:36 am

    Or you could look at it the other way and facepalm. Why is it so hard to escape characters in Powershell? And why is Windows *so* bad at validating input and guarding against attacks?

  3. 3 John Hofmann November 10, 2017 at 1:21 pm

    I know this isn’t exactly timely, but while researching this problem, I found your blog, and thought I’d share the method I came up with to do this without the need to create any extra files.

    You can simply set the variables in your batch script:

    SET “VARIABLE1=TEXT”

    You can then account for the variables ahead of time in your PowerShell script before encoding it:

    If ($env:VARIABLE1) {Write-Output $env:VARIABLE1}

    • 4 Lee Fitzsimmons November 13, 2017 at 6:43 am

      Here’s another variation I just finished so thought I share as well – pipe the parameters via echo eg:

      echo -p1 this -p2 is -p3 a -p4 test | powershell.exe -encodedcommand “thebase64encodedscript”

      Then at the top of your encoded powershell script, something like the following to read in your parameters.

      $params = @{}
      $curparam = “”

      $pr = [Console]::In.ReadLine()
      $pr = $pr -replace ‘\s+$’, ”
      $a = $pr | Select-String -Pattern ‘(?:^| )(\”(?:[^\”]+|\”\”)*\”|[^ ]*)’ -AllMatches

      foreach($x in $a.Matches) {

      $n = $($x -replace ‘^\s+’, ”) -replace ‘\s+$’, ”
      if($n -match (‘\-[0-9A-z]+’)) {
      $curparam = $n
      } else {
      if(-not [string]::IsNullOrEmpty($curparam)) {
      $params.add($curparam , $n)
      }
      }
      }

      write-host $params.’-p1′

      Your parameters are then accessible via the arraylist $params.
      Credit for the regex goes to jimplode: https://stackoverflow.com/questions/3776458/split-a-comma-separated-string-with-both-quoted-and-unquoted-strings

      in answer to anon , the specific use case for this is that in SCCM, powershell scripts in task sequences must be taken from a package. SCCM does however provide a way to execute a regular command, so being able to wrap the powershell script this way circumvents the need to create a package for simple one off scripts.

      • 5 Lee Fitzsimmons November 13, 2017 at 6:49 am

        Note that the above only works when executed from cmd, not a powershell prompt. In powershell, in.readline will take each space-separated item echoed as a separate line. the code can be easily modified for this scenario


Leave a comment




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

July 2011
M T W T F S S
 123
45678910
11121314151617
18192021222324
25262728293031