Powershell: How to capture output from the host - powershell

I am using powershell to automate some tasks related to checking out/merging in TFS. When I call
tf get * /recurse
I get a bunch of data scrolling by about the files that are getting checked out. The last line generated by this command (assuming its success) is one telling the checkin number. I would like to parse this out so it can be used later on in my script.
I know that I can do something like
$getOutput = tf get * /recurse
but then the output is suppressed entirely and I want the output of that command to be scrolled in realtime. I would basically like to grab everything that just got sent to the output buffer.

Try something like this:
tf get * /recurse | tee-Object -Variable getOutput

The tee-object in PowerShell 2.0 allows you to pipe results to two sources. If you leave the second source empty, the results go to the console.
ls | tee-object -filePath directoryListing.txt
This will write the directory listing to both the console and a text file.

Related

How to save the results of a function to a text file in Powershell

I have the function below that produce multiple outputs, is there a way I can put all the outputs of the function in a text file. I tried below to use Out-File it did not work any suggestions?
cls
function functionAD {Write-output ""...}
functionAD | Out-File -FilePath C:\test\task5.txt -Append
the script above still did not work.
UPDATE: This is, in fact, possible if you overwrite the Write-Host function. It can be done like this:
function Write-Host($toWrite) {
Write-Output $toWrite
}
Copy and paste this code into your PowerShell console, then run the program.
Don't worry about permanently overwriting the Write-Host command, this will only last for the current session.
OLD COMMENT:
Unfortunately, Write-Host can not be rerouted to another file stream. It is the only 'write' command that acts in that way. That is why PowerShell programmers generally try to avoid using it unless there is a specific reason to. It is intended for messages sent directly to the user and is thus send to the program (powershell) itself rather than a console.
I would suggest using some other command if the function is your own. Write-Output is always a safe bet because it can be redirected to any other stream.
Here is a link if you have more questions: https://devblogs.microsoft.com/scripting/understanding-streams-redirection-and-write-host-in-powershell/

Redirect all output streams except the success stream to a file

I want to redirect all PowerShell cmdlet output except stream 1 (success) to a file. How can I achieve that? I know how to achieve to redirect individual stream, and I know how to merge it to standard output, but I don't want to mess standard output. I just want to capture streams 2,3 4 and (optionally) 5 into a single file. I am using Windows platform.
As example, I used these commands:
#('c:\temp\', 'c:\temp2\') | % {Get-ChildItem $_}
I do have c:\temp folder with some files inside, and I do not have c:\temp2 folder. So my expected output in file is to get only an error about missing folder temp2.
I tried assigning value to a variable, but it did not help. Normal assigning is not generating the output, but once redirected output appears.
($Files = #('c:\temp\', 'c:\temp2\') | % {Get-ChildItem $_}) *>err.txt
Without redirection, I see only error that c:\temp2 is not existing. But once redirected, list of files from C:\temp appears in err.txt. And, it appears at the end of file. Furthermore, assignment to $Files in ISE environment is not happening!? In other hosts, assignment works fine, but redirect is also adding files to output.
If I try to redirect as 3>err.txt 2>err.txt it fails with: The process cannot access the file err.txt because it is being used by another process.
Merging to any other stream except 1, is not supported. This attempt 3>&2 2>err.txt gives the error: The '3>&2' operator is reserved for future use.
I was able to do something with Start-Transcript, but that creates additional text, and its flooding the output file with unnecessary text.
I was reading following articles, but I did not find proper answer
about_redirection
Understanding Streams, Redirection, and Write-Host in PowerShell
Stack Overflow question: Redirect two or more Powershell streams other than output stream to the same file
A pragmatic workaround is to use the common -ov (-OutVariable) parameter, which enables collecting a cmdlet's success output in a variable, independently of how/whether the success stream is redirected:
'c:\temp\', 'c:\temp2\' | % { Get-ChildItem $_ } -ov Files 1>$null *>err.txt
# Get-ChildItem success output is now stored in $Files
1>$null suppresses the success stream
*>err.txt redirects the remaining streams to file err.txt
Note how Files rather than $Files is passed to -ov, because you must pass the name of the variable, not its value.
A caveat is that the variable specified for -ov receives the entire output and stores it in memory, which can be problematic with large output sets.
Also, as of PSv5.1, note that the output variable is invariably a [System.Collections.ArrayList] instance, even if only a single item was received.
This may change in v6.
As an aside, a more efficient reformulation of your command is:
Get-ChildItem c:\temp\, c:\temp2\ -ov Files 1>$null *>err.txt

output will not format correctly

I am having some problems writing to a text file with powershell using the correct format. I am pulling some windows event logs and saving the output to a text file. When I issue the following 2 commands
$event = get-winevent -filterhashtable #{logname='ForwardedEvents'; id=4688}
$event | format-list >> C:\scripts\file01.txt
I get something like this saved to the text file with a bunch of white space and the line broken up because it is too long:
New Process Name:
C:\Windows\System32\SearchFilterHost.exe
Is there anyway to make the output look like this instead:
New Process Name: C:\Windows\System32\SearchFilterHost.exe
thanks
If you're only interested in the message content of the event, don't pipe the entire event object through Format-List - output the Message property directly instead:
$evt.Message >> C:\scripts\file01.txt

Is it possible for PowerShell to write message to multiple target

Is there a usage of pipeline for PowerShell to Write-Output & write to file in the same time, without using a custom wrapping function?
Take a look at Tee-Object. From help:
The Tee-Object cmdlet sends the output of a command in two directions
(like the letter "T"). It stores the output in a file or variable and
also sends it down the pipeline. If Tee-Object is the last command in
the pipeline, the command output is displayed in the console.

Output from external exe and my custom objects in powershell

(Sorry for strange title, haven't come up with anything better..)
Background
I use nunit-console to test my assemblies. It is called like this (simplified):
function Test-ByNunit {
param($assembly, $tempFile = 'c:\temp\nunit.xml')
& <path-to-nunit-console> $assembly /nologo /xml:$tempFile #othparam
}
Test-ByNunit c:\temp\myAssembly.dll
I have no problem with this, it works fine.
Problem
nunit-console should output its messages as so far. That means - if not captured, it should send them to screen, otherwise it could be stored in file (Test-ByNunit $dll | set-content path)
I'd like to return somehow information about each test-case that was run (the info is stored in the /xml file) in form of array of PSObject objects.
Question
Do you have any tip how to return the info and still leave nunit output its messages?
If I simply write it to output, the function will return array of strings (output from nunit-console) and array of my objects. Then redirection to output file will store my objects as well, but I'd like just display them in console window.
The only possibility that could work is to use [ref], but I'd like to avoid it.
(this is not only about nunit-console, but of course it is general question)
If I got the task right then Out-Host should help:
function Get-WithOutHost {
# external output is redirected to the host
cmd /c dir | Out-Host
# normal output to be reused later
Get-Process
}
# call
$result = Get-WithOutHost
# now $result holds the data to use, external output is on the screen
EDIT: of course this is not enough if external output should be reused, too, not just shown