【问题标题】:Can I override a Powershell native cmdlet but call it from my override我可以覆盖 Powershell 本机 cmdlet 但从我的覆盖中调用它吗
【发布时间】:2020-07-04 09:49:59
【问题描述】:

我认为在 Javascript 中可以这样做。在 Powershell 中我不确定如何:

假设我想用我的自定义方法覆盖对 write-host 的每个调用,但有时我想在我的覆盖中执行本机 write-host。是否可以将本机实现存储在另一个名称下,以便以后从新实现中调用它?

更新:在我看来,https://serverfault.com/a/642299/236470 的答案并没有完全回答我问题的第二部分。如何存储和调用本机实现?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    对函数的调用将覆盖 cmdlet。您可以从about_Command_Precedence on TechNet 阅读更多相关信息...

    如果不指定路径,Windows PowerShell 使用以下 运行命令时的优先顺序:

    1. 别名
    2. 功能
    3. Cmdlet
    4. 本机 Windows 命令

    因此,只需创建一个与本机 cmdlet 同名的函数即可满足您的需求。

    function Write-Host{
        [cmdletbinding()]
        param(
            [Parameter(Mandatory,ValueFromPipeline)]
            $string
        )
        Process {
            # Executes once for each pipeline object
            If ($string -match "bagels"){
                Microsoft.PowerShell.Utility\Write-Host $string -ForegroundColor Green
            }else{
                Microsoft.PowerShell.Utility\Write-Host $string
            }
        }
    }
    

    所以现在write-host 与我们可以过滤的管道输入一起工作。调用“真正的”cmdlet 就像在调用中指定模块一样简单。你可以看到我在上面的代码示例中做了两次。一些示例用法和输出如下:

    如果您将其保存在个人资料或类似性质的东西中,请注意不要忘记您已完成此操作。如有疑问,请使用Get-Command Write-Host。在我的情况下,您可以通过调用 Remove-Item function:write-host

    来删除覆盖

    您也可以查看所谓的代理函数,但我认为这对于您打算做的事情来说太过分了。

    【讨论】:

    • @user310291 除非我误解了我已经回答过的问题。您可以通过在其模块名称前面加上本机实现来调用它。这是我在示例函数中所做的。你不需要存储它。它总是在那里。
    • 注意:$_ 只在流水线时有效,所以如果你像 Write-Host "anything" 这样调用它,该函数根本不起作用
    • @DineiRockenbach 是的,这是真的。涵盖应该如何实施的所有细微差别不应该是答案的范围。
    • 谢谢!做了一个小的更正,希望我没有搞砸任何事情(我假设 write-host "bagels""bagels" | write-host 的行为不同是无意的)。
    【解决方案2】:

    是的,你可以。 I have an answer for that here on ServerFault,但由于它是不同的站点,我将复制它,因为我无法将其关闭为另一个站点。


    是的,您可以覆盖 Get-ChildItem 或 Powershell 中的任何其他 cmdlet。

    将您的函数命名为相同

    如果你在同一个范围内创建一个同名的函数,你的会被使用。

    例子:

    Function Get-ChildItem {
    [CmdletBinding()]
    param(
        # Simulate the parameters here
    )
        # ... do stuff
    }
    

    使用别名

    创建您自己的函数,然后为该函数创建一个别名,与您要覆盖的 cmdlet 同名。

    例子:

    Function My-GetChildItem {
    [CmdletBinding()]
    param(
        # Simulate the parameters here
    )
        # ... do stuff
    }
    
    New-Alias -Name 'Get-ChildItem' -Value 'My-GetChildItem' -Scope Global
    

    这种方式很好,因为它更容易测试你的功能,而无需 stomping内置功能,您可以控制cmdlet 是否在您的代码中被覆盖。

    删除别名:

    Remove-Item 'Alias:\Get-ChildItem' -Force
    

    【讨论】:

    • 我为 SF 答案提供的建议是链接到 about_Command_Precedence,因为它解释了它的工作原理
    • 头奖我帮了你一次:)
    • @briantist 在我看来,serverfault.com/a/642299/236470 的答案并没有完全回答我问题的第二部分。如何存储和调用本机实现?
    • @user310291 我认为您实际上是正确的;您应该接受马特的回答,因为他充分解释了如何调用本机版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    相关资源
    最近更新 更多