There's a relatively useful suggestion floating around on Twitter on how to save results of PowerShell command to a variable and see the results at the same time.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
PS C:\> ($data=get-process)
I'll admit this is a clever technique: you get the results from Get-Process written to the pipeline AND a variable $data. The other way, and frankly I think a better way, is to use Tee-Object. Usually we use Tee-Object to save output to a file and still write the results to the pipeline.
PS C:\> get-process | tee -variable data
To me, this is much more straightforward and I don't have to remember a punctuation trick. I've also found that using Tee-Object is also better performing. I've tried a number of tests and they all seem to verify that Tee-Object is faster. Here's one test:
PS C:\Users\Jeff> measure-command {($a=dir $env:temp -rec)}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 468
Ticks : 4686037
TotalDays : 5.42365393518518E-06
TotalHours : 0.000130167694444444
TotalMinutes : 0.00781006166666667
TotalSeconds : 0.4686037
TotalMilliseconds : 468.6037
PS C:\Users\Jeff> measure-command {dir $env:temp -rec | tee -Variable a}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 158
Ticks : 1583448
TotalDays : 1.83269444444444E-06
TotalHours : 4.39846666666667E-05
TotalMinutes : 0.00263908
TotalSeconds : 0.1583448
TotalMilliseconds : 158.3448
I get the same result with both commands but you can see that Tee-Object is significantly faster.
Using the parentheses trick is handy and especially useful in the interactive console. Personally, I'll probably stick to using Tee-Object and certainly in a script using Tee-Object is easier to follow and understand.
I just ran several tests using your exact commands, and Tee-Object is consistently ~70ms slower than the parentheses trick.
Cheers,
Trevor Sullivan
Interesting. I happen to test on v3 in Windows 8 preview on my netbook. I’ll have to retest in v2.
Hi Jeff. Considered using the common parameter “-OutVariable” to get the same effect?
The trick is to feed the name of a variable without the $ prefix. If the variable doesn’t exist, -OutVariable will create it. Check it out:
Get-Process -OutVariable procs
Is equivalent to:
Get-Process | tee -Variable procs
Output still goes to the pipeline, and is simultaneously captured by the variable $procs.
The performance is QUITE a bit better with -OutVariable:
PS C:\Users\Kfreiheit> measure-command {(Get-Process -OutVariable procs)}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 2
Ticks : 27367
TotalDays : 3.16747685185185E-08
TotalHours : 7.60194444444444E-07
TotalMinutes : 4.56116666666667E-05
TotalSeconds : 0.0027367
TotalMilliseconds : 2.7367
PS C:\Users\Kfreiheit> measure-command {(Get-Process | tee -Variable procs)}
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 96
Ticks : 962522
TotalDays : 1.11403009259259E-06
TotalHours : 2.67367222222222E-05
TotalMinutes : 0.00160420333333333
TotalSeconds : 0.0962522
TotalMilliseconds : 96.2522
Looking for issues with using -OutVariable, I instead found another plus — using “+” to append to a variable when it’s used in multiple commands:
http://scriptlore.com/powershell/outvariable/
I should have thought to mention Outvariable as well. It certainly has some advantages. But keep in mind that it only works for cmdlets and advanced functions with cmdlet binding which should cover 90% of what someone might do. For everything else we would need to resort to the parens trick or Tee object.