Redirect PoweShell to text file

Welcome Forums General PowerShell Q&A Redirect PoweShell to text file

This topic contains 18 replies, has 5 voices, and was last updated by

 
Participant
2 weeks, 5 days ago.

  • Author
    Posts
  • #130728

    Participant
    Points: 28
    Rank: Member

    I've been slow to adopt PoweShell because I have not been able to figure out how to capture what the script is doing and the results of each command. Here is an example on what I am doing with my Batch files.

    This redirects the output of the batch to a txt file as it is running
    Script.bat C:\ScriptResults.txt 2>&1

    The redirect will give me the command that was run and in many cases the results of the command. In this case I can see each command as it processed and I can see that one file was copied. Most of the time I get successes and failures logged in the txt file.
    C:\WINDOWS\ccmcache\l>msiexec.exe /i "C:\Windows\ccmcache\l\Setup.msi" /qn
    C:\WINDOWS\ccmcache\l>if not exist "C:\ProgramData\Software" mkdir "C:\ProgramData\Software"
    C:\WINDOWS\ccmcache\l>copy /y "C:\Windows\ccmcache\l\Config_QA.ini" "C:\ProgramData\Software\Config.ini"
    1 file(s) copied.
    C:\WINDOWS\ccmcache\l>exit

    I cannot find a way to do something similar with PowerShell. I found ways to only give errors but in a long script I can't always tell where the error was in the script because it doesn't log the command that was used. Some things would be much easier with PowerShell.

    Does anyone know of a way to do this is PowerShell?

     

     

  • #130755

    Participant
    Points: 232
    Helping Hand
    Rank: Participant

    Check out the Start-Transcript Cmdlet. That would probably be your best option.

    Get-Help start-transcript -ShowWindow
    
  • #130760
    js

    Participant
    Points: 413
    Helping Hand
    Rank: Contributor

    If you're running a script within powershell, you can redirect all streams like this (2>&1 also works):

    .\test.ps1 *> test.log
    

    https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-5.1

    If you're actually running powershell from the outside, all streams will go to a file:

    powershell -file .\test.ps1 > test.log
    
  • #130880

    Participant
    Points: 28
    Rank: Member

    I've tried both the Start-Transcript and variations of the redirects. Nothing that I have tried includes the actual command that is being run. It is nice having the command listed and then the results of that command. It just makes troubleshooting quicker.

  • #130898

    Participant
    Points: 232
    Helping Hand
    Rank: Participant

    Start-Transcript works just fine for me, commands and output are located in the .log file upon inspection.

    Start-Transcript -Path C:\temp\test_transcript.log
    Get-Process -Name explorer
    Write-Output -InputObject "This should be visible in the transcript"
    Stop-Transcript
    notepad 'C:\temp\test_transcript.log'
    

    .....**results truncated**.....
    PSRemotingProtocolVersion: 2.3
    SerializationVersion: 1.1.0.1
    **********************
    Transcript started, output file is C:\temp\test_transcript.log
    C:\>
    PS>Get-Process -Name explorer

    Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
    ——- —— —– —– —— — — ———–
    1938 101 55292 119708 82.81 3964 1 explorer

    C:\>
    PS>Write-Output -InputObject "This should be visible in the transcript"
    This should be visible in the transcript
    C:\>
    PS>Stop-Transcript
    **********************
    Windows PowerShell transcript end
    End time: 20181220120651
    **********************

  • #130901

    Participant
    Points: 28
    Rank: Member

    That's odd and would be perfect but mine looks different so I must be doing something wrong. How are you running it?

    Here are my results.

    PSRemotingProtocolVersion: 2.3
    SerializationVersion: 1.1.0.1
    **********************

    Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
    ——- —— —– —– —— — — ———–
    2748 145 141192 215432 1,754.73 24616 4 explorer
    This should be visible in the transcript
    **********************
    Windows PowerShell transcript end
    End time: 20181220134043
    **********************

  • #130904

    Participant
    Points: 232
    Helping Hand
    Rank: Participant

    I am running the commands as pasted in my previous response. That is strange output on your transcript file! What version of PS are you running?

    C:\> $PSVersionTable
    
    Name                           Value
    ----                           -----
    PSVersion                      5.1.14393.2636
    PSEdition                      Desktop
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
    BuildVersion                   10.0.14393.2636
    CLRVersion                     4.0.30319.42000
    WSManStackVersion              3.0
    PSRemotingProtocolVersion      2.3
    SerializationVersion           1.1.0.1
    
  • #130911

    Participant
    Points: 28
    Rank: Member

    Here is what I am running.

    PS U:\> $PSVersionTable

    Name Value
    —- —–
    PSVersion 5.1.16299.785
    PSEdition Desktop
    PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
    BuildVersion 10.0.16299.785
    CLRVersion 4.0.30319.42000
    WSManStackVersion 3.0
    PSRemotingProtocolVersion 2.3
    SerializationVersion 1.1.0.1

     

  • #130980

    Participant
    Points: 77
    Rank: Member

    Could you try this on a different machine?
    I've never seen transcription only partially work.

    I have had issues where transcription completely breaks, but that has always resulted in hard errors vs incomplete results

    there are always other options using error-handling, but I'd recommend you learn the PowerShell equivalent to the older dos commands.
    if you utilize those you can have proper controls and messaging around file move activities.

  • #130992
    js

    Participant
    Points: 413
    Helping Hand
    Rank: Contributor

    Ok, I didn't understand the original question. Start-transcript works for me. What exactly are you running?

    PS C:\users\admin> Start-Transcript log
    Transcript started, output file is log
    
    PS C:\users\admin> ls foo
    ls : Cannot find path 'C:\users\admin\foo' because it does not exist.
    At line:1 char:1
    + ls foo
    + ~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\users\admin\foo:String) [Get-ChildItem], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    
    PS C:\users\admin> Stop-Transcript
    Transcript stopped, output file is C:\users\admin\log
    
    PS C:\users\admin> cat log
    **********************
    Windows PowerShell transcript start
    Start time: 20181221091851
    Username: admin
    RunAs User: admin
    Configuration Name:
    Machine: JS (Microsoft Windows NT 10.0.16299.0)
    Host Application: powershell
    Process ID: 9056
    PSVersion: 5.1.16299.820
    PSEdition: Desktop
    PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.16299.820
    BuildVersion: 10.0.16299.820
    CLRVersion: 4.0.30319.42000
    WSManStackVersion: 3.0
    PSRemotingProtocolVersion: 2.3
    SerializationVersion: 1.1.0.1
    **********************
    Transcript started, output file is log
    PS C:\users\admin> ls foo
    ls : Cannot find path 'C:\users\admin\foo' because it does not exist.
    At line:1 char:1
    + ls foo
    + ~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\users\admin\foo:String) [Get-ChildItem], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    ls : Cannot find path 'C:\users\admin\foo' because it does not exist.
    At line:1 char:1
    + ls foo
    + ~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\users\admin\foo:String) [Get-ChildItem], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    
    PS C:\users\admin> Stop-Transcript
    **********************
    Windows PowerShell transcript end
    End time: 20181221091900
    **********************
    
  • #131001

    Participant
    Points: 77
    Rank: Member

    I did change slightly Logan's code below, instead of calling a full path for the log file, this will build the test_transcript.log file in whatever path your powershell session is open in
    open a fresh PowerShell window.
    paste the following commands in

    Start-Transcript test_transcript.log
    Get-Process -Name explorer
    Write-Output -InputObject "This should be visible in the transcript"
    Stop-Transcript
    notepad.exe test_transcript.log
    

    Look at the contents of the file that is opened up, you should see results that match relatively closely with what Logan provided.

    in your pasted example "Start-Transcript log" you don't actually give a really valid filename..

  • #131006

    Participant
    Points: 28
    Rank: Member

    I have tried this on several Windows 10 computers and always get the same results.

    I just tried it from a command prompt "C:\Temp>powershell .\TranscriptTest.ps1" to see if that would change the results but it didn't. I have been running it from PowerShell ISE but either way it is the same.

    It creates the file in Logan's code probably because C:\Temp exists on my computers. I used your code and here is the result.

    Machine: TestComputer (Microsoft Windows NT 10.0.16299.0)
    Host Application: C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell_ISE.exe
    Process ID: 13608
    PSVersion: 5.1.16299.785
    PSEdition: Desktop
    PSCompatibleVersions: 1.0, 2.0, 3.0, 4.0, 5.0, 5.1.16299.785
    BuildVersion: 10.0.16299.785
    CLRVersion: 4.0.30319.42000
    WSManStackVersion: 3.0
    PSRemotingProtocolVersion: 2.3
    SerializationVersion: 1.1.0.1
    **********************

    Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
    ——- —— —– —– —— — — ———–
    2991 159 166516 184808 2,118.03 24616 4 explorer
    This should be visible in the transcript
    **********************
    Windows PowerShell transcript end
    End time: 20181221084402
    **********************

  • #131009

    Participant
    Points: 77
    Rank: Member

    is that the content of the text file that is opened in notepad?
    if so, i'd see if you can try to run this on another machine.

  • #131010
    js

    Participant
    Points: 413
    Helping Hand
    Rank: Contributor

    It looks like start-transcript has to be run interactively, not within a script, to get the results you want.

  • #131015

    Participant
    Points: 28
    Rank: Member

    Looks like you are correct. Start-Transcript doesn't work in non-interactive. Well I guess I'm back to square one.

  • #131052

    Participant
    Points: 232
    Helping Hand
    Rank: Participant

    I have hacked together a way to achieve these results, but its not pretty and its requires additional coding. I used get-help to learn more about Powershell Redirection

    Get-Help about_redirection -ShowWindow
    

    I found this little gem here:

    WINDOWS POWERSHELL REDIRECTION OPERATORS
    The redirection operators enable you to send particular types of output
    to files and to the success output stream.

    The Windows PowerShell redirection operators use the following characters
    to represent each output type:
    * All output
    1 Success output
    2 Errors
    3 Warning messages
    4 Verbose output
    5 Debug messages
    6 Informational messages

    NOTE: The All (*), Warning (3), Verbose (4) and Debug (5) redirection operators were introduced
    in Windows PowerShell 3.0; the Information (6) redirection operator was introduced
    in Windows PowerShell 5.0. They do not work in earlier versions of Windows PowerShell.

    The Windows PowerShell redirection operators are as follows.
    Operator Description Example
    ——– ———————- ——————————
    > Sends output to the Get-Process > Process.txt
    specified file.

    >> Appends the output to dir *.ps1 >> Scripts.txt
    the contents of the
    specified file.

    2> Sends errors to the Get-Process none 2> Errors.txt
    specified file.

    2>> Appends errors to Get-Process none 2>> Save-Errors.txt
    the contents of the
    specified file.

    2>&1 Sends errors (2) and Get-Process none, Powershell 2>&1
    success output (1)
    to the success
    output stream.

    3> Sends warnings to the Write-Warning "Test!" 3> Warnings.txt
    specified file.

    3>> Appends warnings to Write-Warning "Test!" 3>> Save-Warnings.txt
    the contents of the
    specified file.

    3>&1 Sends warnings (3) and function Test-Warning
    success output (1) { Get-Process PowerShell;
    to the success Write-Warning "Test!" }
    output stream. Test-Warning 3>&1

    4> Sends verbose output to Import-Module * -Verbose 4> Verbose.txt
    the specified file.

    4>> Appends verbose output Import-Module * -Verbose 4>> Save-Verbose.txt
    to the contents of the
    specified file.

    4>&1 Sends verbose output (4) Import-Module * -Verbose 4>&1
    and success output (1)
    to the success output
    stream.

    5> Sends debug messages to Write-Debug "Starting" 5> Debug.txt
    the specified file.

    5>> Appends debug messages Write-Debug "Saving" 5>> Save-Debug.txt
    to the contents of the
    specified file.

    5>&1 Sends debug messages (5) function Test-Debug
    and success output (1) { Get-Process PowerShell
    to the success output Write-Debug "PS" }
    stream. Test-Debug 5>&1

    6> Sends informational Write-Information "Here they are" 6> Info.txt
    messages to a specified
    file

    6>> Appends informational Write-Information "Nothing found" 6>> Info.txt
    messages to the contents
    of a specified file.

    6>&1 Sends informational function Test-Info
    messages and success { Get-Process P*
    output to the success Write-Information "Here you go" }
    output stream. Test-Info 6>&1

    *> Sends all output types function Test-Output
    to the specified file. { Get-Process PowerShell, none
    Write-Warning "Test!"
    *>> Appends all output types Write-Verbose "Test Verbose"
    to the contents of the Write-Debug "Test Debug" }
    specified file.
    Test-Output *> Test-Output.txt
    *>&1 Sends all output types Test-Output *>> Test-Output.txt
    (*) to the success output Test-Output *>&1
    stream.

    The syntax of the redirection operators is as follows:

      [\]
    

    That gave me a couple of ideas. One, write transcript manipulation into your scripts and two, make use of the "Write-Information" Cmdlet. See below for an example.

    # This produces output that the OP requested
    $hereString = @'
    Start-Transcript C:\Temp\Test_transcript.txt
    Write-Information -MessageData "Write-Output 'This is a test. Will this command be redirected, or only the output?'"
    Write-Output "This is a test. Will this command be redirected, or only the output?"
    Stop-Transcript
    '@
    
    $hereString | Out-File C:\TEMP\test_redirect.ps1 -Force
    
    Start-Process cmd -ArgumentList "/C powershell.exe -file C:\temp\test_redirect.ps1" -Wait
    notepad C:\Temp\Test_transcript.txt
    

    .....*truncated*.....
    WSManStackVersion: 3.0
    PSRemotingProtocolVersion: 2.3
    SerializationVersion: 1.1.0.1
    **********************
    Transcript started, output file is C:\Temp\Test_transcript.txt
    INFO: Write-Output 'This is a test. Will this command be redirected, or only the output?'
    This is a test. Will this command be redirected, or only the output?
    **********************
    Windows PowerShell transcript end
    End time: 20181221160639
    **********************

    Again, not pretty but technically achieves your desired outcome.

  • #131579

    Participant
    Points: 28
    Rank: Member

    Thanks Logan but I couldn't get the Write-Information to work.

    Does anyone know if there would be issues using Set-Debug? On more advanced scripts it gives a lot of info but that might be good for troubleshooting.

    I took Logan's code and replaced the Transcript cmdlet's with the PSDebug cmdlet's
    Set-PSDebug -Trace 2
    Get-Process -Name explorer
    Write-Output -InputObject "This should be visible in the transcript"
    Set-PSDebug -Off

    From a command prompt I run.
    powershell -file .\TranscriptTest.ps1 *> c:\temp\Debug.txt

    Here are the results of the Debug.txt
    DEBUG:    3+  >>>> Get-Process -Name explorer
    Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
    ——-  ——    —–      —–     ——     —  — ———–
    2368      95    96828      89692      48.64   4296   1 explorer
    DEBUG:    4+  >>>> Write-Output -InputObject "This should be visible in the transcript"
    This should be visible in the transcript

    It appears to give me what I want which is the command and then the results of that command but hopefully this won't cause any other issues.

  • #131582

    Participant
    Points: 77
    Rank: Member

    I think you would be much happier if you instituted some try/catch blocks around each of your cmdlets, you could then manually create text strings to have output to a log file in a location of your choosing.
    a really fast hatchet-job to get something that should work, something like the following..

    $logfile = c:\temp\log.txt
    
    try
    {
        $msiargumentlist = "/i C:\Windows\ccmcache\l\Setup.msi /qn"
        $return = Start-Process msiexec -ArgumentList $msiArgumentList -Wait -passthru
        If (@(0,3010) -contains $return.exitcode) 
        {
            "Setup.msi executed successfully"| out-file $logfile -Append
        } 
        else
        {
            "Setup.msi did not succeed" | out-file $logfile -Append
        }
    }
    catch
    {
       "Eror starting msiexec" | out-file $logfile -Append
    }
    if (test-path "C:\ProgramData\Software")
    {
        "C:\ProgramData\Software existed no action taken"|out-file $logfile -Append
    }
    else
    {
        try
        {
            new-item -ItemType directory  "C:\ProgramData\Software"
            "Built folder location C:\ProgramData\Software" | out-file $logfile -Append
        }
        catch
        {
            "Error building folder location C:\ProgramData\Software" | out-file $logfile -Append
        }
    }
    try
    {
        copy-item -Path "C:\Windows\ccmcache\l\Config_QA.ini" -Destination "C:\ProgramData\Software\Config.ini"
        "Copied Config_QA.ini to new location" | out-file $logfile -Append
    }
    catch
    {
        "Error Copying Config_QA.ini to new location" | out-file $logfile -Append
    }
    

    (note the error handling around msiexec I just did a fast google search for and found the following (no guarantee that bit works)

    How to catch error when msi install fails? from PowerShell

  • #131630

    Participant
    Points: 398
    Helping Hand
    Rank: Contributor

    Wow that's a long thread ... sorry ... tl;dr ... 😉

    If you want to have a reasonable logging for Powershell you will have to create something by yourself or you can use one of the available modules you can find in the PowershellGallery. There are a few you can choose from.

    Another great article about logging you can find here: Greater Visibility Through PowerShell Logging.

    If you want to know what exactly your MSI installation does you can use the integrated logging of the MSI-Service.

You must be logged in to reply to this topic.