【问题标题】:How to check if a cmdlet exists in PowerShell at runtime via script如何在运行时通过脚本检查 PowerShell 中是否存在 cmdlet
【发布时间】:2011-04-24 14:29:38
【问题描述】:

我有一个需要在多个主机(PowerGUI、PowerShell ISE 等)下运行的 PowerShell 脚本,但我遇到了一个问题,有时某个主机下不存在 cmdlet。有没有办法检查 cmdlet 是否存在,以便我可以将代码包装在 if 块中,并在它不存在时执行其他操作?

我知道我可以使用 $host.name 来分割假定在每个主机上运行的代码,但我更愿意使用 Feature Detection 来代替,以防将来添加 cmdlet。

我也可以使用 try/catch 块,但由于它在托管代码中运行,我假设可以检测是否通过代码安装了 cmdlet。

【问题讨论】:

    标签: powershell powershell-2.0


    【解决方案1】:

    使用Get-Command cmdlet 测试是否存在 cmdlet:

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

    如果您想确保它是一个 cmdlet(而不是 exe、函数或脚本),请使用 -CommandType 参数,例如 -CommandType Cmdlet

    【讨论】:

    • 不知道有errorAction参数。在此处找到所有常用参数的列表:msdn.microsoft.com/en-us/library/dd901844(VS.85).aspx,这很高兴知道。谢谢!
    • 注意:您也可以使用 if (get-module | Where-Object {$_.Name -eq "ServerManager"}) { "Module Exists" } 检查模块。更多详情:stackoverflow.com/questions/10027156/…
    • cmdlet 可能存在,但不可用。很好的例子:Windows 2003 上存在 Get-WinEvent,但它会引发 NotImplemented 异常。你会如何处理这种情况?
    • 我不确定是否有一种简单的方法可以为任意 cmdlet 处理此问题。如果您只测试 Get-WinEvent,您将知道要传递的适当参数并使用 try/catch 进行包装。我认为这对于任意 cmdlet 是不可行的。也就是说,我认为 cmdlet 抛出 NotImplementedException 是一种极端情况——至少我希望如此。 :-(
    • @Neolisk 你不能试试$test = Get-WinEvent -LogName system -MaxEvents 1; [bool]$test 如果它返回 False 则 cmdlet 不可用?
    【解决方案2】:

    这是一个简单的功能,可以做你喜欢做的事情:)

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

    如何使用(例如):

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

    【讨论】:

      【解决方案3】:

      如果命令是动词-名词形式,那么您可以使用带动词和名词参数的 Get-Command。

      # 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
      

      在 Windows PowerShell 5.1 和 PowerShell Core 7.0 上测试。

      编辑 2020-11-09 附加示例。还有用法示例(改编自 Keith Hill 的回答)。

      【讨论】:

      • 我知道这个问题很老了。只是给我未来的自己的备忘录。
      猜你喜欢
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 2010-09-12
      相关资源
      最近更新 更多