Dominic Brunetti
Dominic Brunetti

Reputation: 1069

How does one test if a program/executable is present on a system in powershell?

I have a script that requires openssl be installed on the system. I want to do a check to see if it is installed. I've considered using test-path but because this script will be on many computers, there's no way of knowing where the user installed openssl or if it is in the system path.

Is there a way to do something like test-command openssl (I know that doesn't exist) and get an error level or the like to return in powershell?

Many thanks!

Upvotes: 5

Views: 2049

Answers (2)

mklement0
mklement0

Reputation: 437052

Use the Get-Command cmdlet to explicitly test if executables can be called by their name only (implying that they're in one of the directories listed in $env:PATH) and for command discovery in general:

$found = [bool] (Get-Command -ErrorAction Ignore -Type Application openssl)

Write-Verbose -vb "openssl.exe found? $found"

Casting to [bool] evaluates to $true only if Get-Command returns output, which it only does if the executable is found.

-Type Application ensures that only external programs are considered; by default, Get-Command finds commands of all types, including *.ps1 scripts, cmdlets, functions, and aliases.

The Get-Command by itself would also allow you to find out the executable's full path, via the output object's .Source property.


Alternatively, if all that matters is whether the executable is available, you can simply try to execute your actual command and handle an error indicating that the executable is not available via try / catch:

try {
  openssl ... # your *actual* command, not a test
} catch [System.Management.Automation.CommandNotFoundException] {
  # Handle the error, reflected in $_
  Write-Warning $_
  # ... 
}

Note that you don't strictly need to catch [System.Management.Automation.CommandNotFoundException] specifically, if you're confident that the only error that can occur is due to a missing executable, but note that you could then get potential false positives from errors that occur during evaluation of expression-based arguments, such as attempting to pass (1 / 0) as an argument.

Also note that attempting to test the availability of an executable by invoking it without arguments inside a try / catch statement is not a viable approach, because the executable may enter an interactive shell (as is the case with openssl) or produce undesired side effects.

Upvotes: 10

kpogue
kpogue

Reputation: 700

You can use try/catch blocks to do something like the following:

$OpenSSLMissing = $false
try {openssl} catch {$OpenSSLMissing = $true}
if ($OpenSSLMissing)
{
    # Do something
}
else
{
    # Do something else
}

Upvotes: 2

Related Questions