Is there a way to set a variable up to place output to stdout or null?

前端 未结 3 1853
北恋
北恋 2020-12-07 00:05

I would like to set up a variable in my code that would ultimately define if I\'ll see some output or not.

  • \"hello\" writes to stdout
相关标签:
3条回答
  • 2020-12-07 00:19

    All right. Thanks to all the brainiacs here for the motivation. This answer may not be the best way to go about it, but it works!

    Two things you need to understand to achieve this:

    1. If you are used to using Write-Host, it won't work, you'll have to go with Write-Output.
    2. You may have to learn to use a block of script as a function parameter.

    One is self explanatory, so here's how to attain #2:

    Function Test-SctiptBlockParam {
      Param(
        $scriptblock
      )
      if ($debugOutput) {
        Invoke-Command $scriptblock
      } else {
        (Invoke-Command $scriptblock) > $null
      }
    }
    
    Test-SctiptBlockParam -scriptblock { Write-Output "I want to see on the STDOUT sometimes" }
    

    Finally, here is an example of my output and code

    0 讨论(0)
  • 2020-12-07 00:26

    Again may not be the best way, but works.

    As @Bender the Greatest has already mentioned a function with [CmdletBinding] should help the purpose.

    I'll try to provide a very basic example -

    A selective logger function like this -

    function Selective-Log {
     [CmdletBinding()]
     param(
         [Parameter()]
         [ValidateNotNullOrEmpty()]
         [string]$Message,
    
         [Parameter()]
         [ValidateNotNullOrEmpty()]
         [ValidateSet('Info','Warning','Error')]
         [string]$Severity = 'Info'
     )
    
     if($Severity -eq 'Info'){
     Write-Output $Message > $null
     }else{
     Write-Output $Message 
     }}
    

    Now when you use it in your scripts as

    Selective-Log -Message Test1 -Severity Info

    it wouldn't log anything

    Then if you wish to log you'd choose severity other than Info

    Selective-Log -Message Test2 -Severity Error

    you could also use it like Selective-Log Test2 Error

    Hope this helps someone

    0 讨论(0)
  • 2020-12-07 00:38

    What you want to read up on are output streams and redirection in Powershell. This includes information on all of the different output streams and how to control their relevance using built-in constructs. Just like there are the Write-Host and Write-Output cmdlets, there are also several others that control which stream to write to.

    About the Output Streams

    There are 6 streams in total. Make note of their numbers, because these stream identifiers are used to control which streams to redirect:

    • 1 - Success Stream - This stream is used when passing information along the Powershell Pipeline. This is the "default" stream, but can also be written to with Write-Output.
    • 2 - Error Stream - Errors should be written to this stream. Can be written to with Write-Error, accompanied by further error information.
    • 3 - Warning Stream - Used to write warning information. Can be written to with Write-Warning.
    • 4 - Verbose Stream - Used to write verbose output. Does not display by default but can be made to display by either setting $VerbosePreference = "Continue", or by using the [CmdletBinding()] attribute on a function or script and passing in the -Verbose flag. Write to the verbose stream with Write-Verbose.
    • 5 - Debug Stream - Used to write to the debug stream, and optionally trigger a breakpoint. Does not display or trigger a breakpoint by default, but can be controlled with the $DebugPreference variable, or by using the [CmdletBinding()] attribute on a script or function and using the -Debug flag. You can write to the debug stream by using the Write-Debug cmdlet.
    • 6 - Information Stream - Can be written to by Write-Host. This is the console host output and is not part of the pipeline.

    Redirecting Streams

    You can use redirection operators to redirect other streams to the success stream as well. Each stream above has a number associated with it. This is the numeric representation of each stream.

    The redirection operators are as follows:

    • > - Redirect success stream to file (overwrite)
    • #> - Redirect the # stream to file (e.g. 2> somefile.txt)
    • >> - Redirect success stream to file (appends, you can also use a numbered stream as with the overwrite file operator)
    • >&1 - Redirect any stream to success stream (note that unlike the other redirection operators you can only redirect to the success stream. Using other stream identifiers will result in an error).

    Also note that in place of a stream number, you can use * which will redirect all streams at the same time.

    Here are some examples of redirecting output from one stream to another (if you're familiar with it, it's somewhat UNIX-y):

    # Write success stream to file
    Write-Output "Here is some text for a file" > .\somefile.txt
    
    # Write error stream to file (you have to first
    Write-Error "Some error occurred" 2> .\somefile.txt
    
    # Redirect all error output to the success stream
    $myErrorOutput = Write-Error "My error output" 2>&1
    
    # Append all script output streams to a single file
    Get-OutputFromAllStreams.ps1 *>> somefile.txt
    

    Output to a File and the Pipeline Simultaneously

    You can redirect the output stream to a file and the pipeline at the same time as well, using the Tee-Object cmdlet:

    $myString = "My Output" | Tee-Object -FilePath .\somefile.txt
    

    Sample function to show how to use the different Write- cmdlets

    Note how the following function is decorated with the [CmdletBinding()] attribute. This is key in making the -Verbose and -Debug switches work without you having to define them yourself.

    [CmdletBinding()]
    function Write-DifferentOutputs {
      # These all visible by default but only the output stream is passed down the pipeline
      Write-Output "Output stream"
      Write-Warning "Warning stream"
      Write-Error "Error stream"
      Write-Host "Information stream"
    
      # These are not visible by default, but are written when the `-Verbose` or `-Debug` flags are passed
      # You can also manually set the $VerbosePreference or $DebugPreference variables to control this without parameters
      Write-Verbose "Verbose stream"
      Write-Debug "Debug stream"
    }
    

    Call the above function with the -Verbose or -Debug switches to see how the behavior differs, and also call it with neither flag.

    Redirecting output to $null if you really need to

    If there is output that you never want to see or for some other reason using the Write- cmdlets to write to the Verbose or Debug streams isn't an option, you can still redirect output to $null or make use of the Out-Null cmdlet. Recall the numbered streams at the top of this answer, they will be referenced here:

    Using redirection

    # Don't forget that *> redirects ALL streams, and may be what you want
    Write-Output 'Success Stream' > $null
    Write-Error 'Error Stream' 2> $null
    Write-Warning 'Warning Stream' 3> $null
    Write-Verbose 'Verbose Stream' 4> $null
    Write-Debug 'Debug Stream' 5> $null
    Write-Host 'Information Stream (yes you can suppress/redirect me)' 6> $null
    

    Using Out-Null

    Remember, you can redirect other streams to the success stream by redirecting the output to &1.

    # Remember, to pass information on the pipeline
    # it MUST be on the success stream first
    
    # Don't forget that *> redirects ALL streams, and may be what you want
    Write-Output 'Success Stream' | Out-Null
    Write-Error 'Error Stream' 2>&1 | Out-Null
    Write-Warning 'Warning Stream' 3>&1 | Out-Null
    Write-Verbose 'Verbose Stream' 4>&1 | Out-Null
    Write-Debug 'Debug Stream' 5>&1 | Out-Null
    Write-Host 'Information Stream (yes you can suppress/redirect me)' 6>&1 | Out-Null
    

    Redirecting whole command outputs to Write- cmdlets

    You can easily pipe all output of a command or cmdlet to one of the Write- cmdlets. I'll use the Write-DifferentOutputs provided earlier in my example below, but this will work with any cmdlet, script, or command you run:

    Write-DifferentOutputs *>&1 | Write-Verbose
    

    What the above will do is only show the command output if $VerbosePreference = $Continue, or if you passed -Verbose as an argument to your script or function.

    In Summarium

    In your original question, you are attempting to reinvent a wheel that Powershell already supports fairly well. I would suggest that you learn how to make use of the different Write-Output cmdlets for each stream and especially learn how to make use of the Write-Warning, Write-Verbose, Write-Error, and Write-Debug cmdlets.

    0 讨论(0)
提交回复
热议问题