如何编写 PowerShell 二进制模块

二进制模块可以是包含 cmdlet 类的任何程序集(.dll)。 默认情况下,导入二进制模块时,将导入程序集中的所有 cmdlet。 但是,可以通过创建根模块为程序集的模块清单来限制导入的 cmdlet。 (例如,清单的 CmdletsToExport 密钥可用于仅导出所需的 cmdlet。此外,二进制模块可以包含其他文件、目录结构以及单个 cmdlet 无法提供的其他有用管理信息片段。

以下过程介绍如何创建和安装 PowerShell 二进制模块。

如何创建和安装 PowerShell 二进制模块

  1. 使用所需的功能创建二进制 PowerShell 解决方案(如用 C# 编写的 cmdlet),并确保其正常运行。

    从代码的角度来看,二进制模块的核心是 cmdlet 程序集。 事实上,PowerShell 将单个 cmdlet 程序集视为用于加载和卸载的模块,开发人员无需进行额外的努力。 有关编写 cmdlet 的详细信息,请参阅 编写 Windows PowerShell Cmdlet

  2. 如有必要,请创建解决方案的其余部分:(其他 cmdlet、XML 文件等),并使用模块清单对其进行描述。

    除了在解决方案中描述 cmdlet 程序集外,模块清单还可以描述如何导出和导入模块、将公开哪些 cmdlet 以及哪些附加文件将进入模块。 不过,如前所述,PowerShell 可以像模块一样处理二进制 cmdlet,无需额外工作。 因此,模块清单主要用于将多个文件合并到单个包中,或用于显式控制给定程序集的发布。 有关详细信息,请参阅 如何编写 PowerShell 模块清单

    以下代码是一个简化的 C# 示例,其中包含同一个文件(可用作模块)中的三个 cmdlet。

    using System.Management.Automation;           // Windows PowerShell namespace.
    
    namespace ModuleCmdlets
    {
      [Cmdlet(VerbsDiagnostic.Test,"BinaryModuleCmdlet1")]
      public class TestBinaryModuleCmdlet1Command : Cmdlet
      {
        protected override void BeginProcessing()
        {
          WriteObject("BinaryModuleCmdlet1 exported by the ModuleCmdlets module.");
        }
      }
    
      [Cmdlet(VerbsDiagnostic.Test, "BinaryModuleCmdlet2")]
      public class TestBinaryModuleCmdlet2Command : Cmdlet
      {
          protected override void BeginProcessing()
          {
              WriteObject("BinaryModuleCmdlet2 exported by the ModuleCmdlets module.");
          }
      }
    
      [Cmdlet(VerbsDiagnostic.Test, "BinaryModuleCmdlet3")]
      public class TestBinaryModuleCmdlet3Command : Cmdlet
      {
          protected override void BeginProcessing()
          {
              WriteObject("BinaryModuleCmdlet3 exported by the ModuleCmdlets module.");
          }
      }
    
    }
    
  3. 打包解决方案,并将包保存到 PowerShell 模块路径中的某个位置。

    全局 $env:PSModulePath 环境变量描述 PowerShell 用于查找模块的默认路径。 例如,在系统上保存模块的常见路径 %SystemRoot%\Users\<user>\Documents\WindowsPowerShell\Modules\<moduleName>。 如果不使用默认路径,则需要在安装过程中显式声明模块的位置。 请务必创建一个文件夹来保存模块,因为可能需要该文件夹来存储解决方案的多个程序集和文件。

    从技术上来说,无需在任意 $env:PSModulePath 位置安装模块 - 这些位置只是 PowerShell 将查找模块的默认位置。 但是,最佳做法是这样做,除非有充分的理由将模块存储在其他位置。 有关详细信息,请参阅 安装 PowerShell 模块about_PSModulePath

  4. 通过调用 Import-Module将模块导入 PowerShell。

    调用 Import-Module 会将模块加载到活动内存中。 如果使用 PowerShell 3.0 及更高版本,请在代码中调用模块中的命令也会导入它。 有关其他信息,请参阅导入 PowerShell 模块

模块初始化和清理代码

如果模块需要在导入或删除时执行某些作,例如发现任务或初始化,则可以实现 IModuleAssemblyInitializerIModuleAssemblyCleanup 接口。

注释

除非绝对必要,否则不建议使用此模式。 若要保持 PowerShell 性能,应在调用命令而不是导入时延迟加载内容。

将管理单元程序集导入为模块

管理单元程序集中存在的 Cmdlet 和提供程序可以作为二进制模块加载。 当管理单元程序集作为二进制模块加载时,管理单元中的 cmdlet 和提供程序可供用户使用,但程序集中的管理单元类将被忽略,并且未注册管理单元。 因此,Windows PowerShell 提供的管理单元 cmdlet 无法检测管理单元,即使该 cmdlet 和提供程序可用于会话。

此外,无法将管理单元引用的任何格式或类型文件导入为二进制模块的一部分。 若要导入格式设置和类型文件,必须创建模块清单。 请参阅 如何编写 PowerShell 模块清单

另请参阅