Execute process conditionally in Windows PowerShel

2019-06-18 07:24发布

问题:

I'm wondering if anybody knows of a way to conditionally execute a program depending on the exit success/failure of the previous program. Is there any way for me to execute a program2 immediately after program1 if program1 exits successfully without testing the LASTEXITCODE variable? I tried the -band and -and operators to no avail, though I had a feeling they wouldn't work anyway, and the best substitute is a combination of a semicolon and an if statement. I mean, when it comes to building a package somewhat automatically from source on Linux, the && operator can't be beaten:

# Configure a package, compile it and install it
./configure && make && sudo make install

PowerShell would require me to do the following, assuming I could actually use the same build system in PowerShell:

# Configure a package, compile it and install it
.\configure ; if ($LASTEXITCODE -eq 0) { make ; if ($LASTEXITCODE -eq 0) { sudo make install } }

Sure, I could use multiple lines, save it in a file and execute the script, but the idea is for it to be concise (save keystrokes). Perhaps it's just a difference between PowerShell and Bash (and even the built-in Windows command prompt which supports the && operator) I'll need to adjust to, but if there's a cleaner way to do it, I'd love to know.

回答1:

You could create a function to do this, but there is not a direct way to do it that I know of.

function run-conditionally($commands) {
   $ranAll = $false
   foreach($command in $commands) {
      invoke-command $command
      if ($LASTEXITCODE -ne 0) {
          $ranAll = $false
          break; 
      }
      $ranAll = $true
   }

   Write-Host "Finished: $ranAll"

   return $ranAll
}

Then call it similar to

run-conditionally(@(".\configure","make","sudo make install"))

There are probably a few errors there this is off the cuff without a powershell environment handy.



回答2:

I was really hurting for the lack of &&, too, so wrote the following simple script based on GrayWizardX's answer (which doesn't work as-is):

foreach( $command in $args )
{
  $error.clear()
  invoke-command $command
  if ($error) { break; }
}

If you save it as rc.ps1 (for "run conditionally") in a directory in your path, you can use it like:

rc {.\configure} {make} {make install}

Using script blocks (the curly braces) as arguments instead of strings means you can use tab completion while typing out the commands, which is much nicer. This script is almost as good as &&, and works.