Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell fails to run multi-line commands from stdin?

I'm wanting to pass arbitrary scripts to Powershell via stdin. (In practice, I'd like to avoid having to put the script into a temporary file, but for the purposes of this question I will pipe the contents of a file to powershell.)

So I'm doing something like so (in this example, from a Windows cmd shell):

type myfile.txt | powershell -

It works if myfile.txt contains something like this:

1..3 | % { $_ *2 } 
echo done  

(It outputs 2\n4\n6\ndone.) However, if I split this first statement across multiple lines like so, then Powershell simply exists without generating any output at all:

1..3 | 
  % { $_ *2 } 
echo done  

This seems to fail for any multiline statement. For example, this also fails to produce output:

1..3 | % {
  $_ *2 } 
echo done  

I'm surprised by this since each are legal Powershell scripts that would work normally if placed into a .ps1 file and run as normal.

I've tried various things including escaping the EOL using line continuation chars, to no avail. The same effect occurs if the parent shell is Powershell, or even Python (using subprocess.Popen with stdin=PIPE). In each case, Powershell exits without any error, and the exit code is 0.

Interestingly, if I run the following, only "before.txt" gets created.

"before" | out-file before.txt
1..3 | 
   % { $_ *2 } 
"after" | out-file after.txt
echo done   

Any ideas why Powershell would have trouble reading a multi-line command, if read from stdin?

like image 575
Michael Lewis Avatar asked May 24 '16 15:05

Michael Lewis


2 Answers

I'm going to consider this answered by this: How to end a multi-line command in PowerShell since it shows that an extra newline is required. However, I'm going to raise this to MS as a bug since this should not be required when reading from a non-tty, or when -NonInteractive switch is specified.

Please vote on my bug report to the Powershell team.

like image 106
Michael Lewis Avatar answered Oct 11 '22 22:10

Michael Lewis


This is not a complete answer, but from what I can tell, the problem has to do with the input being sent in line by line.

To demonstrate the line-by-line issue, I invoke powershell this way:

powershell.exe -command "gc myfile.txt" | powershell.exe -

vs

powershell.exe -command "gc myfile.txt -raw" | powershell.exe -

The first example replicates what you see with type, the second reads the entire contents of the file, and it works as expected.

It also works from within PowerShell if you put the script contents in a string and pipe it into powershell.exe -.

I had a theory that it had to do with line-by-line input lacking line breaks, but it's not so clear cut. If that were the case, why would the first option work but not the second (removing the line break splitting the single pipeline should have no effect, while removing the line break between the pipeline and the echo should make it fail). Maybe there's something unclear about the way powershell is handling the input with or without line breaks.

like image 32
briantist Avatar answered Oct 12 '22 00:10

briantist