可移植模块

Windows PowerShell 是为 .NET Framework 编写的,而 PowerShell Core 是为 .NET Core编写的。 可移植模块是适用于 Windows PowerShell 和 PowerShell Core 的模块。 虽然 .NET Framework 和 .NET Core 高度兼容,但两者之间的可用 API 存在差异。 Windows PowerShell 和 PowerShell Core 中提供的 API 也有差异。 这两个环境中要使用的模块需要注意这些差异。

移植现有模块

移植 PSSnapIn

PowerShell Core 不支持 PowerShell SnapIns。 但是,将 PSSnapIn 转换为 PowerShell 模块并不简单。 通常,PSSnapIn 注册代码位于派生自 PSSnapIn类的单个源文件中。 从生成中删除此源文件;不再需要它。

使用 New-ModuleManifest 创建新的模块清单,以替换 PSSnapIn 注册代码的需求。 PSSnapIn(如 说明)中的某些值可以在模块清单中重复使用。

模块清单中的 RootModule 属性应设置为实现 cmdlet 的程序集的名称(.dll)。

.NET 可移植性分析器(即 APIPort)

若要移植为 Windows PowerShell 编写的模块以使用 PowerShell Core,请从 .NET 可移植性分析器开始。 针对已编译的程序集运行此工具,以确定模块中使用的 .NET API 是否与 .NET Framework、.NET Core 和其他 .NET 运行时兼容。 该工具建议备用 API(如果存在)。 否则,可能需要添加运行时检查并限制特定运行时中不可用的功能。

创建新模块

如果创建新模块,建议使用 .NET CLI

安装 PowerShell 标准模块模板

安装 .NET CLI 后,安装模板库以生成简单的 PowerShell 模块。 该模块将与 Windows PowerShell、PowerShell Core、Windows、Linux 和 macOS 兼容。

以下示例演示如何安装模板:

dotnet new install Microsoft.PowerShell.Standard.Module.Template
The following template packages will be installed:
   Microsoft.PowerShell.Standard.Module.Template

Success: Microsoft.PowerShell.Standard.Module.Template::0.1.3 installed the following templates:
Template Name               Short Name  Language  Tags
--------------------------  ----------  --------  -------------------------
PowerShell Standard Module  psmodule    [C#]      Library/PowerShell/Module

创建新模块项目

安装模板后,可以使用该模板创建新的 PowerShell 模块项目。 在此示例中,示例模块称为“myModule”。

PS> mkdir myModule

    Directory: C:\Users\Steve

Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 8/3/2018 2:41 PM myModule

PS> cd myModule
PS C:\Users\Steve\myModule> dotnet new psmodule
The template "PowerShell Standard Module" was created successfully.

Processing post-creation actions...
Restoring  C:\Users\Steve\myModule\myModule.csproj:
  Determining projects to restore...
  Restored C:\Users\Steve\myModule\myModule.csproj (in 184 ms).
Restore succeeded.

构建模块

使用标准 .NET CLI 命令生成项目。

dotnet build
PS C:\Users\Steve\myModule> dotnet build
MSBuild version 17.6.3+07e294721 for .NET
  Determining projects to restore...
  All projects are up-to-date for restore.
  PowerShellPG -> C:\Users\Steve\myModule\bin\Debug\netstandard2.0\myModule.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.36

测试模块

生成模块后,可以导入它并执行示例 cmdlet。

Import-Module .\bin\Debug\netstandard2.0\myModule.dll
Test-SampleCmdlet -?
Test-SampleCmdlet -FavoriteNumber 7 -FavoritePet Cat
NAME
    Test-SampleCmdlet

SYNTAX
    Test-SampleCmdlet [-FavoriteNumber] <int> [[-FavoritePet] {Cat | Dog | Horse}] [<CommonParameters>]


ALIASES
    None


REMARKS
    None


FavoriteNumber FavoritePet
-------------- -----------
             7 Cat

调试模块

有关设置 Visual Studio Code 以调试模块的指南,请参阅 使用 Visual Studio Code 调试已编译的 cmdlet

支持技术

以下部分详细介绍了此模板使用的一些技术。

.NET 标准库

.NET Standard 是所有 .NET 实现中可用的 .NET API 的正式规范。 面向 .NET Standard 的托管代码适用于与 .NET Standard 版本兼容的 .NET Framework 和 .NET Core 版本。

注意

尽管 .NET Standard 中可能存在 API,但 .NET Core 中的 API 实现可能会在运行时引发 PlatformNotSupportedException,因此为了验证与 Windows PowerShell 和 PowerShell Core 的兼容性,最佳做法是在两个环境中运行模块的测试。 如果模块旨在跨平台,请在 Linux 和 macOS 上运行测试。

面向 .NET Standard 有助于确保随着模块的发展,不兼容的 API 不会意外引入模块。 不兼容性是在编译时而不是运行时发现的。

不过,只要使用兼容的 API,模块就不必必须面向 .NET Standard 也可以在 Windows PowerShell 和 PowerShell Core 中使用。 中间语言(IL)在两个运行时之间兼容。 可以将目标设定为与 .NET Standard 2.0 兼容的 .NET Framework 4.6.1。 如果不在 .NET Standard 2.0 之外使用 API,则模块可与 PowerShell Core 6 配合使用,而无需重新编译。

PowerShell 标准库

PowerShell Standard 库是所有大于或等于该标准的 PowerShell 版本中提供的 PowerShell API 的正式规范。

例如,PowerShell Standard 5.1 与 Windows PowerShell 5.1 和 PowerShell Core 6.0 或更高版本兼容。

建议使用 PowerShell 标准库编译模块。 该库可确保 API 在 Windows PowerShell 和 PowerShell Core 6 中都可用并实现。 PowerShell Standard 旨在始终与未来版本兼容。 使用 PowerShell 标准库 5.1 生成的模块将始终与将来的 PowerShell 版本兼容。

模块清单

指示与 Windows PowerShell 和 PowerShell Core 的兼容性

验证模块适用于 Windows PowerShell 和 PowerShell Core 后,模块清单应使用 CompatiblePSEditions 属性显式指示兼容性。 Desktop 值表示模块与 Windows PowerShell 兼容,而 Core 值表示该模块与 PowerShell Core 兼容。 包括 DesktopCore 意味着该模块与 Windows PowerShell 和 PowerShell Core 兼容。

注意

Core 并不意味着模块与 Windows、Linux 和 macOS 兼容。 PowerShell v5 中引入了 CompatiblePSEditions 属性。 使用 CompatiblePSEditions 属性的模块清单无法在 PowerShell v5 之前的版本中加载。

指示操作系统兼容性

首先,验证模块是否适用于 Linux 和 macOS。 接下来,在模块清单中指明与那些操作系统的兼容性。 这样,在将模块发布到 PowerShell 库后,用户可以更轻松地为其操作系统找到对应的模块。

在模块清单中,PrivateData 属性具有 PSData 子属性。 Tags 的可选 PSData 属性采用一组在 PowerShell 库中显示的值。 PowerShell Gallery 支持的兼容性值有:

标记 描述
PSEdition_Core 与 PowerShell Core 6 兼容
PSEdition_Desktop 与 Windows PowerShell 兼容
Windows操作系统 与 Windows 兼容
Linux 与 Linux 兼容(无特定发行版)
macOS 与 macOS 兼容

例:

@{
    GUID = "4ae9fd46-338a-459c-8186-07f910774cb8"
    Author = "Microsoft Corporation"
    CompanyName = "Microsoft Corporation"
    Copyright = "(C) Microsoft Corporation. All rights reserved."
    HelpInfoUri = "https://go.microsoft.com/fwlink/?linkid=855962"
    ModuleVersion = "1.2.4"
    PowerShellVersion = "3.0"
    ClrVersion = "4.0"
    RootModule = "PackageManagement.psm1"
    Description = 'PackageManagement (a.k.a. OneGet) is a new way to discover and install software packages from around the web.
 it's a manager or multiplexer of existing package managers (also called package providers) that unifies Windows package management with a single Windows PowerShell interface. With PackageManagement, you can do the following.
  - Manage a list of software repositories in which packages can be searched, acquired and installed
  - Discover software packages
  - Seamlessly install, uninstall, and inventory packages from one or more software repositories'

    CmdletsToExport = @(
        'Find-Package',
        'Get-Package',
        'Get-PackageProvider',
        'Get-PackageSource',
        'Install-Package',
        'Import-PackageProvider'
        'Find-PackageProvider'
        'Install-PackageProvider'
        'Register-PackageSource',
        'Set-PackageSource',
        'Unregister-PackageSource',
        'Uninstall-Package'
        'Save-Package'
    )

    FormatsToProcess  = @('PackageManagement.format.ps1xml')

    PrivateData = @{
        PSData = @{
            Tags = @('PackageManagement', 'PSEdition_Core', 'PSEdition_Desktop', 'Windows', 'Linux', 'macOS')
            ProjectUri = 'https://oneget.org'
        }
    }
}

本机库的依赖项

用于不同操作系统或处理器架构的模块可能会依赖一个托管库,而该托管库本身依赖于一些本机库。

在 PowerShell 7 之前,人们需要编写自定义代码来加载合适的本机 DLL,以便托管库能够正确地找到它。

借助 PowerShell 7,可以在托管库位置(在 .NET RID 目录表示法的子集后面)的子文件夹中搜索要加载的本机二进制文件。

managed.dll folder
    |
    |--- 'win-x64' folder
    |       |--- native.dll
    |
    |--- 'win-x86' folder
    |       |--- native.dll
    |
    |--- 'win-arm' folder
    |       |--- native.dll
    |
    |--- 'win-arm64' folder
    |       |--- native.dll
    |
    |--- 'linux-x64' folder
    |       |--- native.so
    |
    |--- 'linux-x86' folder
    |       |--- native.so
    |
    |--- 'linux-arm' folder
    |       |--- native.so
    |
    |--- 'linux-arm64' folder
    |       |--- native.so
    |
    |--- 'osx-x64' folder
    |       |--- native.dylib