1

In olden days, I remember a trick we used to use to run Perl scripts within Windows cmd.exe as a simple invocation of a cmd file rather than having to run perl.exe with the script name, something like:

@rem = '
@perl -x -S %0 %*
@goto :eof
@rem ';
<insert Perl script here>

This used the rather neat trick of exploiting differences in how cmd.exe and perl.exe would handle the input script. Windows' cmd.exe would read the first three lines as three separate commands which would:

  • have a comment with no echo;
  • run perl with the same input file and arguments, without echo; and
  • goto the end of the file (exit) with no echo.

On the other hand, perl.exe would treat the first four lines as an assignment statement, then go on to execute the Perl script proper.

Now it's often a pain to run Powershell scripts from the cmd.exe command line since you have to use something like:

powershell -file go.ps1

I'm wondering if there's a way to encode both batch and powershell commands into a single cmd file, similar to the Perl trick, in such a way that it starts running under cmd.exe but switches to Powershell quickly after that.

If that were possible, you could run your script go.cmd simply by entering:

go

at the command line, rather than some convoluted invocation of powershell.

I know that you can ship separate cmd and ps1 files but that's in fact what I'm trying to get away from. I'm looking for a single file solution if possible.

I also know that you can base-64 encode your script or execute it as a string, provided you replace all newlines with semicolons. But that means the Powershell stuff is no longer easily editable or readable in the resulting file.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • possible duplicate of [How to run a PowerShell script within a DOS batch file](http://stackoverflow.com/questions/2609985/how-to-run-a-powershell-script-within-a-dos-batch-file) – chue x Feb 24 '15 at 04:25
  • Bummer. Yes, that is a clear dupe, and the accepted answer is obviously superior to mine. Voted to close. – Jeroen Mostert Feb 24 '15 at 07:52

1 Answers1

1

Fortunately or otherwise, Powershell knows exactly what to do with .cmd files: use CMD to run them.

@set $a=%0 && powershell -encodedcommand ZwBjACAAKAAoAGQAaQByACAAZQBuAHYAOgBgACQAYQApAC4AdgBhAGwAdQBlACAALQByAGUAcABsAGEAYwBlACAAJwAiACcALAAnACcAKQAgAHwAIABzAGUAbABlAGMAdAAgAC0AcwBrAGkAcAAgADIAIAB8ACAAcABvAHcAZQByAHMAaABlAGwAbAAgAC0A
@exit /b
"Hello from Powershell! You know it's me because cmd would never know that 2 + 2 = $(2 + 2)!"

The encoded command is

gc ((dir env:`$a).value -replace '\"','') | select -skip 2 | powershell -

Which fetches the contents of the script invoking itself, skips the stuff intended for CMD and, yes, runs Powershell on the rest.

Since we're piping commands through stdin and not having them in a proper script file there may be weirdness for more complicated scripts, doubly so if you start nesting these hybrids. I wouldn't trust this in production, but hey, it's something.

Jeroen Mostert
  • 27,176
  • 2
  • 52
  • 85