85

I have a PowerShell script that needs to run under multiple hosts (PowerGUI, PowerShell ISE, etc...), but I am having an issue where sometimes a cmdlet doesn't exist under one of the hosts. Is there a way to check to see if a cmdlet exists so that I can wrap the code in an if block and do something else when it does not exist?

I know I could use the $host.name to section the code that is suppose to run on each host, but I would prefer to use Feature Detection instead in case the cmdlet ever gets added in the future.

I also could use a try/catch block, but since it runs in managed code I assume there is away to detect if a cmdlet is installed via code.

3 Answers 3

169

Use the Get-Command cmdlet to test for the existence of a cmdlet:

if (Get-Command $cmdName -errorAction SilentlyContinue)
{
    "$cmdName exists"
}

And if you want to ensure it is a cmdlet (and not an exe or function or script) use the -CommandType parameter e.g -CommandType Cmdlet

Sign up to request clarification or add additional context in comments.

5 Comments

Didn't know there was an errorAction parameter. Found the list of all Common Parameters here: msdn.microsoft.com/en-us/library/dd901844(VS.85).aspx which is good to know. Thanks!
NOTE: you can also check for Modules using if (get-module | Where-Object {$_.Name -eq "ServerManager"}) { "Module Exists" }. More details: stackoverflow.com/questions/10027156/…
cmdlet may exist, but not be available. Good example: Get-WinEvent exists on Windows 2003, but it throws NotImplemented exception. How would you handle this situation?
I'm not sure there is an easy way to handle this for an arbitrary cmdlet. If you're only testing Get-WinEvent, you would know appropriate parameters to pass and wrap with a try/catch. I don't think that's feasible for an arbitrary cmdlet. That said, I think it is a corner-case for a cmdlet to throw a NotImplementedException- at least I hope so. :-(
@Neolisk can't you try $test = Get-WinEvent -LogName system -MaxEvents 1; [bool]$test and if it returns False then the cmdlet is not available?
36

This is a simple function to do what you're like to do :)

function Check-Command($cmdname)
{
    return [bool](Get-Command -Name $cmdname -ErrorAction SilentlyContinue)
}

How to use (for example):

if (Check-Command -cmdname 'Invoke-WebRequest')
{
     Invoke-WebRequest $link -OutFile $destination
}
else
{
     $webclient.DownloadFile($link, $destination)
}

Comments

7

If the command is in Verb-Noun form then you can use Get-Command with Verb and Noun parameters.

# Usage:
if (Get-Command -Verb Invoke -Noun MyCommand) {
  # cmdlet Invoke-MyCommand exists
}

Get-Command -Verb Get -Noun Item

# Output:
# CommandType     Name                  Version    Source
# -----------     ----                  -------    ------
# Cmdlet          Get-Item              7.0.0.0    #Microsoft.PowerShell.Management
Get-Command -Verb Take -Noun One

# No output.
function Take-One { [CmdletBinding()]param() }
Get-Command -Verb Take -Noun One

# Output:
# CommandType     Name                   Version    Source
# -----------     ----                   -------    ------
# Function        Take-One

Tested on Windows PowerShell 5.1 and PowerShell Core 7.0.

Edit 2020-11-09 Additional example. Also usage example (adapted from Keith Hill answer).

2 Comments

I know this question is very old. Just a memo for my future self.
This is the appropriate answer where errors will confound an operation even with -ErrorAction SilentlyContinue like in, for example, the Start-Job -InitializationScript scriptblock.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.