views:

737

answers:

3

For my tests I am using 'Start > Run' dialog (not the cmd.exe).

This works fine, and I get 9 in log.txt

powershell -Command 4+5 > c:\log.txt

But this does not work:

powershell -EncodedCommand IAA1ACsANwAgAA== > c:\log.txt

So how can I redirect output in this case?

Experimental code:

function Test
{
    $cmd = { 5+7 }
    $encodedCommand = EncodeCommand $cmd

    StartProcess "powershell -Command $cmd > c:\log.txt"
    StartProcess "powershell -EncodedCommand $encodedCommand > c:\log2.txt"
}

function StartProcess($commandLine)
{
    Invoke-WMIMethod -path win32_process -name create -argumentList $commandLine
}

function EncodeCommand($expression)
{
    $commandBytes = [System.Text.Encoding]::Unicode.GetBytes($expression)
    [Convert]::ToBase64String($commandBytes)
}
+2  A: 

The "Run" dialog doesn't seem like it provides redirection at all. According to this usenet post you only get redirection if you have a console. I wonder if the redirection parameter is being parsed by powershell.exe, which is choosing to redirect if it's not receiving encoded input? Sounds like a question for Raymond Chen.

Anyway, this works, at the expense of spawning an otherwise useless console:

cmd /c powershell -EncodedCommand IAA1ACsANwAgAA== > c:\ps.txt
crb
Ah.. Indeed, the > is just a PowerShell operator.
alex2k8
+1  A: 

I had to encode command together with redirection.

function Test
{
    $cmd = { 5+7 }
    $encodedCommand = EncodeCommand "$cmd > 'c:\log2.log'"

    StartProcess "powershell -Command $cmd > c:\log.txt"
    StartProcess "powershell -EncodedCommand $encodedCommand"
}

So this will write a sum 5+7 into c:\log2.log

powershell -EncodedCommand IAA1ACsANwAgACAAPgAgACcAYwA6AFwAbABvAGcAMgAuAGwAbwBnACcA

P.S.

crb suggested to use "cmd /c". But in this case the encoded script length will be constrained by the command line limitations

On computers running Microsoft Windows XP or later, the maximum length of the string that you can use at the command prompt is 8191 characters. On computers running Microsoft Windows 2000 or Windows NT 4.0, the maximum length of the string that you can use at the command prompt is 2047 characters.

alex2k8
+2  A: 

The difference between those two commands is that the -Command parameter is greedy. It takes everything on the command line after it, while -EncodedCommand is not greedy. What the first command is really doing is:

powershell -Command "4+5 > c:\log.txt"

So the new PowerShell instance is handling the redirection. However, if you use the -EncodedCommand paramter, the new PowerShell instance does not see the redirection because you did not include it in the encoded command. This can be a bad thing if the environment calling PowerShell does not have redirection (like in a scheduled task).

So, as "crb" showed, you need to either encode the redirection into your command, or call PowerShell from an environment that can handle the redirection (like cmd, or another PowerShell instance).

JasonMArcher
I have done this already.
alex2k8
I was explaining why this is happening. I believe it is important to not just fix bugs in code, but understand why they happen. Sometimes it can even show you a neat way of solving other problems.
JasonMArcher
Cool, thank you Jason!
alex2k8