Suppress verbose/debug streams while still logging to file

Hello all,
I have a large function that is used to scan permissions on Windows folders in large volumes. This function generates lots of verbose and debug messages, which I output to a Log File using the Start-Transcript/Stop-Transcript functions. The script also outputs some results via custom psobjects. All good so far.

My issue comes in when this function is run against very large Windows server volumes (i.e. 800,000+ folders). This of course generates an extremely large amount of verbose/debug messages to the console, which as it runs causes server memory utilization to increase and script speed to decrease.

What I am trying to do is find a way to simultaneously redirect my verbose/debug messages (Streams 4 and 5) to a log file, my results (Stream 1) to a Results file, all while suppressing any output to the console.

Here is a test script I put together to demonstrate what I’ve tried (the Start/Stop-Transcript method and the “redirection” method), all to no avail.

function Output-Message {
    [CmdletBinding()]
    param(
        [string]$Message
    )

    # Set DEBUG and VERBOSE preference
        If($PSBoundParameters['Debug']){
            $DebugPreference = 'Continue'
        }
        Else{
            $DebugPreference = 'SilentlyContinue'
        }

        If($PSBoundParameters['Verbose']){
            $VerbosePreference = 'Continue'
        }
        Else{
            $VerbosePreference = 'SilentlyContinue'
        }

    # Create Output Object
    $Table = @{
        "ObjectType"="Message";`
        "ObjectValue"=$Message
    }
    
    # Stream 1 (Success) - output object
    New-Object psobject -Property $Table | select "ObjectType","ObjectValue"

    # Stream 4 (Verbose)
    Write-Verbose "(DON'T WANT THIS MESSAGE ON CONSOLE, ONLY IN LOG FILE) - Outputting Verbose message: $Message"

    # Stream 5 (Debug)
    Write-Debug "(DON'T WANT THIS MESSAGE ON CONSOLE, ONLY IN LOG FILE) - Outputting Debug message: $Message"

}  # End of function Print-Message

cls

# LogFiles
$LogFileTranscript = "C:\temp\LogFile-TranscriptMethod.log"
If(test-path $LogFileTranscript){ Clear-Content $LogFileTranscript }

$LogFileRedirection = "C:\temp\LogFile-RedirectionMethod.log"
If(test-path $LogFileRedirection){ Clear-Content $LogFileRedirection }

# Results File
$ResultsFile = "C:\temp\ResultsFile.csv"
If(test-path $ResultsFile){ Clear-Content $ResultsFile }


#########################
#   Transcript Method   #
#########################
    
    Write-Host "Starting Transcript method" -ForegroundColor Yellow

    # This "Transcript" method still outputs the Verbose and Debug logs to the console, which I would like to suppress
    
    Start-Transcript -Path $LogFileTranscript

    # Run function
    Output-Message -Message "Transcript Method" -Verbose -Debug | Export-Csv $ResultsFile -NoTypeInformation -Append

    Stop-Transcript


##########################
#   Redirection Method   #
##########################
    
    Write-Host "Starting Redirection method" -ForegroundColor Yellow

    # This "Redirection" method suppresses output to the console, which is good, but by nature it also outputs
    # the "results" of the Output-Message function to the log file, since the results are part of Stream 1.
    # Thus, there is no data in Stream 1 left for the Export-CSV function, and so nothing from this "redirection"
    # method gets output to the Results file.
    
    1..100 | foreach{
        Output-Message -Message "$_ - Redirection Method" -Verbose -Debug 5>&1 4>&1 >> $LogFileRedirection | Export-Csv $ResultsFile -NoTypeInformation -Append

        Output-Message -Message "$_ - Redirection Method All At Once" -Verbose -Debug *>> $LogFileRedirection | Export-Csv $ResultsFile -NoTypeInformation -Append
    }

    

# Open our files for review
notepad $LogFileTranscript
notepad $LogFileRedirection

Invoke-Item $ResultsFile

Hi vv0bbles, welcome to the forum.

I would start by reading this topic fully

hello krzydoug, thank you for the welcome! good to be here.

And yes I have read that article fully (more than once now that I think about it. I meant to mention that I’d read that article in my initial post but forgot).

My concern is that i don’t think redirection can accomplish what I’m wanting, i.e. a way to redirect Streams 4 and 5 to a separate file, while NOT redirecting Stream 1 so I can pipe Stream 1 to the Export-Csv cmdlet. It would be great if I could redirect a stream to any other stream (e.g. redirect Stream 5 to Stream 4 and then redirect Stream 4 to my log file), but per the article you mentioned, Unlike some Unix shells, you can only redirect other streams to the Success stream.

I have tried “stacking” redirects, e.g. 4>>$LogFile 5>>$LogFile but that won’t work b/c the initial 4>>$LogFile redirect retains the open handle to $LogFile such that the successive 5>>$LogFile request errors out (“can’t access $LogFile b/c it’s being used by another process”).

So, I’m left with my initial problem:

  1. I want to output Streams 4 and 5 to a separate log file.
  2. I want to suppress Streams 4 and 5 from the console.
  3. I do not want to redirect Stream 1, so it can still be present to pipe to Export-CSV.

I do have a workaround where I just add Export-CSV inside the function, but I wanted to know if there was another way to solve my 3-fold problem above.

Is there something in the article I’m missing, or a piece that you think could solve my issue?