cmdlet 和函数之间有什么区别?

What is the difference between a cmdlet and a function?

module manifest 中有两个元素:cmdlet 和函数。

cmdlet 和函数有什么区别?

cmdlet 是用 C# 或其他 .NET 语言编写并包含在 .dll 中(即二进制模块)的 .NET class。函数直接在 PowerShell 中的脚本、脚本模块或命令行中指定。模块清单可能包括脚本和二进制模块,因此清单需要能够导出 cmdlet 和函数。甚至可以从单个清单导出具有相同名称的 cmdlet 和函数,但通常不推荐这样做。

补充

并非所有函数在 PowerShell 中都是平等创建的:

  • 一个advanced function is the written-in-PowerShell analog of a (binary) cmdlet (which, as stated, is compiled from a .NET language); decorating a function's param(...) block with the [CmdletBinding()] attribute or decorating at least one parameter with a [Parameter()] attribute thanks, Ansgar Wiechers 是什么使它成为高级;因此,它支持某些 标准行为:

    • 您获得对 common parameters 的自动支持,例如 -Verbose-OutVariable,并且在选择加入的基础上,对 -WhatIf-Confirm.

    • 无法绑定到显式声明的参数的参数会导致调用错误。

    • 通常,但不一定,高级函数通过 process { ... } 脚本块,通过用 ValueFromPipeline 装饰的参数绑定参数支持一对一的管道输入处理and/or ValueFromPipelineByPropertyName.

    • 不幸的是,即使 高级功能和 cmdlet 也不是完全平等的:

      • 高级函数 运行 在 子变量范围 中,与 cmdlet 不同。

        • 但是,即使在 模块 中的函数中也可以访问调用者的变量(对于模块外的函数,默认情况下调用者的变量是可见的,由于 PowerShell 的动态作用域),通过 $PSCmdlet.SessionState.PSVariable 对象,如 this answer.
        • 所示
      • 高级功能apply culture-invariant parameter conversions, unlike cmdlets.

      • 高级函数,在 Windows PowerShellhandle ValueFromRemainingArguments differently than cmdlets.

        • 这种不一致已在 PowerShell Core 中解决,但不幸的是,解决的问题比解决的问题多 - 请参阅 GitHub 问题 #5955 and #6451 .
  • 一个simple function,相比之下:

    • 适用于脚本和模块内部的 helper 函数
    • 需要更少的“仪式”(没有参数属性的更简单的语法,单脚本块主体)
      • 注意:与高级函数和 cmdlet 不同,简单函数接受任意参数,无论它们是否绑定到已声明的参数;未绑定的参数在 automatic $args variable; see this answer 中反映了如何 防止 传递未绑定(意外)参数。
    • 但是,如果需要,仍然可以通过自动变量 $Input 甚至通过 process { ... } 块处理管道输入。
    • 默认情况下,
    • 子范围 中也有 运行;在模块之外(无论如何都不应该从中导出简单函数),由于 PowerShell 的动态范围,调用者的变量是 可见的 修改它们(通常应该避免)需要用-Scope 1调用Set-Variable
    • 请注意,还有一个专门但很少使用的 变体 是为流水线处理优化的简单函数,使用 Filter 关键字定义。它的主体为每个管道输入对象隐式调用,反映在自动变量 $_.

虽然 将功能导出为模块的一部分 - 最好通过其模块清单 (*.psd1) - 不会 强制执行 函数是 高级 函数,好的做法是只导出 高级 函数.