PowerShell: Is there an automatic variable for the last execution result?

前端 未结 10 1871
名媛妹妹
名媛妹妹 2021-02-05 00:29

I\'m looking for a feature comparable to Python interactive shell\'s \"_\" variable. In PowerShell I want something like this:

> Get-Something # this returns          


        
相关标签:
10条回答
  • 2021-02-05 00:54

    Not exactly. There's the $_ automatic value which contains the current object in the pipe-line.

    The pipeline is the usual way to pass a result from one cmdlet to the next, and cmdlets are set to accept parameters from the pipeline or from the properties of objects in the pipeline making the use of a "last result" variable irrelevant.

    Still some situations do require a specific reference to the "piped" object and for those there's the $_ automatic value.

    Here's an example of its usage: Using the Where-Object Cmdlet and here's a list of powershell's automatic variables: Chapter 4. PowerShell Automatic Variables

    Scripting in powershell requires a different style than programming in Python (same as Python requires a different style than C++.)

    Powershell is built so pipes are used extensively, if you want to break up a pipeline into a more procedural step by step structure you'll need to save your results in named variables not automatic ones.

    0 讨论(0)
  • 2021-02-05 00:55

    An approach that has worked for me is to process the command's output with Select-Object as a pass-through. For instance, I had a console EXE that output verbose output to stderr and meaningful output to stdout, of which I wanted to capture only the last line.

    $UtilityPath = ""
    
    (UpdateUtility.exe $ArgList 2>&1) | % {
        If ($_ -Is [System.Management.Automation.ErrorRecord]) {
            $_.Exception.Message
        }
        Else {
            $_
            $UtilityPath = $_
        }
    }
    

    The way this script was being invoked, having output on PowerShell's Error output stream was considered a hard error, which didn't mesh nicely with the way PowerShell takes external apps' stderr output and turns it into Error output. This approach of wrapping the output allowed me to control how it passed through, as well as capture the stdout line I wanted. It seems to me that this would be a fairly flexible approach that would allow you to intercept output and do anything you want with it as it passes through. For instance:

    $CommandOutput = ""
    
    SomeOtherCommand | % {
        $CommandOutput += "$_`r`n"
        $_
    }
    
    0 讨论(0)
  • 2021-02-05 00:59

    Use the module PowerShellCookbook and add a call to Add-ObjectCollector to your startup script

    0 讨论(0)
  • 2021-02-05 01:02

    For my specific use case, I was running a batch file from PowerShell, and I wanted to print the output of that batch file in real-time AND save the output into a variable. I was able to accomplish this by piping the output of my call operator to Tee-Object:

    $args = @('-r', '-a');
    & "C:\myFile.bat" $args | Tee-Object -Variable output;
    $output | Set-Clipboard;
    

    The first command sets up my arguments for the batch file. The second command runs the batch file using the call operator with my arguments, and it pipes the output to the Tee-Object command, which prints the output in real-time from the call operator, but also saves all the information into a new variable called output. The last command simply copies the contents of $output to the clipboard.

    Tee-Object also allows saving output to a file (Unicode encoding), and if I need to save to a file and a variable (in addition to printing to the console), I can chain multiple calls to Tee-Object together in one pipeline. See this link for more information:

    https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/tee-object

    0 讨论(0)
  • 2021-02-05 01:05

    How about invoking the last command with "r" (alias for Invoke-History) and wrapping it in parentheses() to execute it first?

    Yes this reruns the last command, but in my use cases this is by far the most streamlined solution especially for times when I don't realize that I'll need the last commands output at first.

    It also keeps the object structure intact.

    PS C:\Users\user> Get-NetAdapter -InterfaceIndex 3 | Where {$_.State -match "2"}
    
    Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
    ----                      --------------------                    ------- ------       ----------             ---------
    Ethernet                  Intel(R) Ethernet Connection I217-LM          3 Up           XX-XX-XX-XX-XX-XX       100 Mbps
    
    PS C:\Users\user> (r) |where {$_.LinkSpeed -eq "100 Mbps"}
    Get-NetAdapter -InterfaceIndex 3 | Where {$_.State -match "2"}
    
    Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
    ----                      --------------------                    ------- ------       ----------             ---------
    Ethernet                  Intel(R) Ethernet Connection I217-LM          3 Up           XX-XX-XX-XX-XX-XX       100 Mbps
    
    PS C:\Users\user> (r).MacAddress
    Get-NetAdapter -InterfaceIndex 3 | Where {$_.State -match "2"}
    XX-XX-XX-XX-XX-XX
    
    0 讨论(0)
  • 2021-02-05 01:07

    You can also print the result of the command and capture the output object(s) using the OutVariable parameter, later on then use $anObj to display the variable content.

    Get-Something -OutVariable anObj
    
    0 讨论(0)
提交回复
热议问题