So in my previous post I wrote about how I got around a problem with some standard error from Perforce. I want to take my work around function and pipe it into Tee-object so I can simultaneously display and log what’s going on with the execution of my consistency check. A consistency check could take a while, so being able to see it’s running output is important.
In my function, I use Invoke-Expression. Well, turns out it’s not so easy to just pipe that into Tee-Object. At least in PSH V1.
Here is my test PowerShell script:
write-host Running in PowerShell Version $host.version.major write-host 'Executing: Invoke-Expression "print.exe /?" | tee-object -filepath test.log' Invoke-Expression "print.exe /?" | tee-object -filepath test.log write-host Now lets get the content of test.log get-content test.log write-host write-host 'Executing: Invoke-Expression "print.exe /?" > test.log' Invoke-Expression "print.exe /?" > test.log write-host Now lets get the content of test.log get-content test.log |
Run it inside PowerShell v1:
PS C:\temp> .\test.ps1 Running in PowerShell Version 1 Executing: Invoke-Expression "print.exe /?" | tee-object -filepath test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. Now lets get the content of test.log Get-Content : Cannot find path 'C:\temp\test.log' because it does not exist. At C:\temp\test.ps1:5 char:12 + get-content <<<< test.log Executing: Invoke-Expression "print.exe /?" > test.log Now lets get the content of test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. |
The pipe doesn’t work, but standard redirection does. I also tried piping it to out-file. Oddly, the output goes straight to the screen and nothing to the file.
Now let’s try it in v2 CTP3:
PS C:\temp> .\test.ps1 Running in PowerShell Version 2 Executing: Invoke-Expression "print.exe /?" | tee-object -filepath test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. Now lets get the content of test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. Executing: Invoke-Expression "print.exe /?" > test.log Now lets get the content of test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. PS C:\temp> |
In v2, we get the expected result.
I was about to give up on this, but I found this post that describes basically the same issue. The suggested fix is to wrap the Invoke-Expression (or iex) in parenthesis.
PS C:\temp> (Invoke-Expression "print.exe /?") | tee-object -filepath test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. PS C:\temp> get-content test.log Prints a text file. PRINT [/D:device] [[drive:][path]filename[...]] /D:device Specifies a print device. PS C:\temp> |
Keep on truckin..
More TuneWiz, less PowerShell!
(Says the guy who hasn’t posted in two months. J/K, keep up the good work!)
In PS1, if you include the Tee command in your Invoke-Expression expression like below, it’ll work.
Invoke-Expression “print.exe /?|tee -filepath test.log”
Invoke-Expression “print.exe /?|tee -variable test”