<WIZARD WARNING>
First a reminder: when you are in PowerShell (formerly knows as Monad), you can run anything you want out-of-process using the construct:
PowerShell {Scriptblock}
The great example of this is
PS> #RUN EVERYTHING IN PROCESS
PS> get-process |where {$_.handles -ge 900} |sort handles
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1369 45 55328 16880 469 81.67 3056 OUTLOOK
1575 48 84616 116200 450 103.52 3212 iexplore
2367 190 31192 40676 152 179.70 1768 svchost
PS> #RUN EVERYTHING OUT OF PROCESS
PS> PowerShell {get-process |where {$_.handles -ge 900} |sort handles}
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1369 45 55328 16880 469 81.73 3056 OUTLOOK
1575 48 84616 116200 450 103.56 3212 iexplore
2369 190 31192 40676 152 179.73 1768 svchost
PS> #RUN the first 2 elements of the pipeline in process and the last in-process
PS> PowerShell {get-process |where {$_.handles -ge 900}} |sort handles
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1369 45 55328 16880 469 81.75 3056 OUTLOOK
1571 48 84768 116352 450 103.59 3212 iexplore
2373 190 30716 40220 152 179.81 1768 svchost
PS> #RUN the first element of the pipeline in process and the last 2 in-process
PS> PowerShell {get-process} |where {$_.handles -ge 900} |sort handles
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1369 45 55328 16948 469 81.80 3056 OUTLOOK
1567 48 84252 115892 449 103.63 3212 iexplore
2398 190 31292 40724 153 180.02 1768 svchost
Now – have you ever tried to do that from CMD.EXE?
C:\>powershell {get-process |where {$_.handles -ge 900} | Sort Handles }
‘where’ is not recognized as an internal or external command,
operable program or batch file.
That doesn’t work so well. You try a number of things and depending upon what you are trying to do, that will work better or worse. If you want to execute script blocks with single and double quotes, this becomes incomprehensible pretty quickly.
The problem is that there are various components which try to “help” you by processing the arguments (e.g. stripping off quotes). The reason this ALWAYS works when you invoke it from Powershell is … we cheat. Well, we cheat in a Kabayashi Maru sort of way (See Kirk’s solution http://en.wikipedia.org/wiki/Kobayashi_Maru).
Here is a trick that you can use to see what is going on. The system type [ENVIRONMENT] has lots of great static properties:
PS> [Environment] |gm -static -membertype property
TypeName: System.Environment
Name MemberType Definition
—- ———- ———-
CommandLine Property static System.String CommandLine {get;}
CurrentDirectory Property static System.String CurrentDirectory {get…
ExitCode Property static System.Int32 ExitCode {get;set;}
HasShutdownStarted Property static System.Boolean HasShutdownStarted {…
MachineName Property static System.String MachineName {get;}
NewLine Property static System.String NewLine {get;}
OSVersion Property static System.OperatingSystem OSVersion {g…
ProcessorCount Property static System.Int32 ProcessorCount {get;}
StackTrace Property static System.String StackTrace {get;}
SystemDirectory Property static System.String SystemDirectory {get;}
TickCount Property static System.Int32 TickCount {get;}
UserDomainName Property static System.String UserDomainName {get;}
UserInteractive Property static System.Boolean UserInteractive {get;}
UserName Property static System.String UserName {get;}
Version Property static System.Version Version {get;}
WorkingSet Property static System.Int64 WorkingSet {get;}
Including the commandline used to execute the current process.
PS> [Environment]::commandline
“C:\Program Files\Windows PowerShell\v1.0\powershell.exe”
From there, you can do the following to see our cheat:
PS> PowerShell {[Environment]::CommandLine}
“C:\Program Files\Windows PowerShell\v1.0\powershell.exe” -encodedCommand WwBFAG4AdgBpAHIAbwBuAG0AZQBuAHQAXQA6ADoAQwBvAG0AbQBhAG4AZABMAGkAbgBlAA== -inputFormat xml -outputFormat xml
When we launch an external process which has a parameter with {}’s we say that that is a subshell and we TWEAK the command invocation by Base64 encoding the scriptblock and by telling the command to consume and produce XML.
If you ever need to invoke a complex piece of code directly from CMD.exe you can run PowerShell and do the following to get the string to pass to -EncodedCommand :
PS> $script = {gps |where {$_.handles -ge 900}|sort handles}.ToString()
PS> [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetByte
s($script))
ZwBwAHMAIAB8AHcAaABlAHIAZQAgAHsAJABfAC4AaABhAG4AZABsAGUAcwAgAC0AZwBlACAAOQA
wADAAfQB8AHMAbwByAHQAIABoAGEAbgBkAGwAZQBzAA==
You can then use that string from CMD.EXE:
C:\>PowerShell -EncodedCommand ZwBwAHMAIAB8AHcAaABlAHIAZQAgAHsAJABfAC4AaABhAG4AZ
ABsAGUAcwAgAC0AZwBlACAAOQAwADAAfQB8AHMAbwByAHQAIABoAGEAbgBkAGwAZQBzAA==
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1366 45 55328 21552 469 83.50 3056 OUTLOOK
1665 48 90164 122736 466 276.13 3212 iexplore
2396 202 31036 40664 153 192.08 1768 svchost
Enjoy!
Jeffrey Snover [MSFT]
Windows PowerShell Architect
PSMDTAG:FAQ: What is the -EncodedCommand parameter on PowerShell.Exe for?
PSMDTAG:FAQ: How can I see the command line that started the PowerShell process?
PSMDTAG:FAQ: How do I run a scriptblock in a seperate process?
PSMDTAG:INTERNAL: avoiding funky syntax across process invocations, Base64 encoding of ENCODEDCOMMAND
0 comments