本部分介绍编写 cmdlet 时应遵循的准则。 它们分为用于设计 cmdlet 的准则和编写 cmdlet 代码的准则。 你可能会发现这些准则不适用于每个方案。 但是,如果他们适用,并且你不遵循这些准则,则用户在使用 cmdlet 时可能体验不佳。
设计指南
设计 cmdlet 时,应遵循以下准则,以确保使用 cmdlet 和其他 cmdlet 之间的用户体验一致。 找到适用于你的情况的设计准则时,请务必查看类似准则的代码指南。
将特定名词用于 Cmdlet 名称(SD01)
cmdlet 命名中使用的名词需要非常具体,这样用户才能查找到你的 cmdlet。 将“server”等泛型名词的前面加上产品名称的缩写版。 例如,如果名词引用运行Microsoft SQL Server实例的服务器,请使用名词,例如“SQLServer”。 特定名词和批准的谓词短列表的组合使用户能够快速发现和预测功能,同时避免在 cmdlet 名称之间重复。
为了增强用户体验,为 cmdlet 名称选择的名词应是单一的。 例如,使用名称 Get-Process 而不是 Get-Processes. 最好针对所有 cmdlet 名称遵循此规则,即使 cmdlet 可能针对多个项执行操作也是如此。
对 Cmdlet 名称使用 Pascal Case (SD02)
请使用 Pascal 命名法 来命名参数。 换句话说,将谓词的第一个字母和名词中使用的所有术语大写。 例如“Clear-ItemProperty”。
参数设计准则 (SD03)
cmdlet 需要参数来接收待处理的数据,并指示确定操作特性的信息。 例如,cmdlet 可能具有 Name 从管道接收数据的参数,并且 cmdlet 可能有一个 Force 参数来指示该 cmdlet 可以强制执行其操作。 cmdlet 可以定义的参数数没有限制。
使用标准参数名称
cmdlet 应使用标准参数名称,以便用户可以快速确定特定参数的含义。 如果需要更具体的名称,请使用标准参数名称,然后将更具体的名称指定为别名。 例如, Get-Service cmdlet 具有具有泛型名称(Name)和更具体的别名(ServiceName)的参数。 这两个术语都可用于指定参数。
有关参数名称及其数据类型的详细信息,请参阅 Cmdlet 参数名称和功能准则。
使用单一参数名称
避免对值为单个元素的参数使用复数名称。 这包括采用数组或列表的参数,因为用户可能只提供一个元素的数组或列表。
仅当参数的值始终为多元素值的情况下,才应使用复数参数名称。 在这些情况下,cmdlet 应验证是否提供了多个元素,如果未提供多个元素,cmdlet 应向用户显示警告。
对参数名称使用 Pascal 命名法
对参数名称使用 Pascal 大小写。 换句话说,将参数名称中每个单词的第一个字母大写,包括名称的第一个字母。 例如,参数名称 ErrorAction 使用正确的大写。 以下参数名称使用不正确的大写形式:
errorActionerroraction
采用选项列表的参数
可通过两种方法创建一个可从一组选项中选择其值的参数。
定义指定有效值的枚举类型(或使用现有枚举类型)。 然后,使用枚举类型创建该类型的参数。
将 ValidateSet 属性添加到参数声明。 有关此属性的详细信息,请参阅 ValidateSet 属性声明。
对参数使用标准类型
若要确保与其他 cmdlet 保持一致性,请尽可能对参数使用标准类型。 有关应用于不同参数的类型的详细信息,请参阅 标准 Cmdlet 参数名称和类型。 本主题提供了指向多个主题的链接,这些主题描述标准参数组的名称和.NET框架类型,例如“活动参数”。
使用强类型 .NET 框架类型
参数应定义为.NET框架类型,以提供更好的参数验证。 例如,限制为一组值中的一个值的参数应定义为枚举类型。 若要支持统一资源标识符(URI)值,请将参数定义为 System.Uri 类型。 避免在所有属性中使用基本字符串参数,但自由格式文本属性除外。
使用一致参数类型
当多个 cmdlet 使用相同的参数时,请始终使用相同的参数类型。 例如,如果 Process 参数是一个 cmdlet 的 System.Int16 类型,请不要将另一个 cmdlet 的参数设置为 ProcessSystem.Uint16 类型。
取值为 True 和 False 的参数
如果参数仅采用 true 和 false,请将参数定义为 System.Management.Automation.SwitchParameter 类型。
指定在命令中的[switch]参数被视为true。 如果命令中不包含该参数,Windows PowerShell 会将参数的值false。
不要定义布尔参数。
如果参数需要区分 3 个值:$true、$false 和“unspecified”,则定义 nullable<bool> 类型的参数。 当 cmdlet 可以修改对象的布尔属性时,通常会发生第三个“未指定”值的需求。 在这种情况下,“未指定”表示不更改属性的当前值。
支持参数数组
通常,用户必须对多个参数执行相同的操作。 对于这些用户,cmdlet 应接受数组作为参数输入,使用户可以将参数作为 Windows PowerShell 变量进行传递。 例如,Get-Process cmdlet 对标识要检索的进程名称的字符串使用数组。
支持 PassThru 参数
默认情况下,许多修改系统的 cmdlet(如 Stop-Process cmdlet)作为“对象接收器”运行,并且不返回结果。 这些 cmdlet 应实现参数 PassThru 以强制 cmdlet 返回对象。
PassThru指定参数后,cmdlet 通过使用对 System.Management.Automation.Cmdlet.WriteObject 方法的调用返回对象。 例如,以下命令停止 Calc(CalculatorApp.exe),并将生成的进程传递给管道。
Stop-Process -Name CalculatorApp -PassThru
在大多数情况下,“添加”、“设置”和“新建 cmdlet”应支持参数 PassThru 。
支持参数集
cmdlet 旨在实现单个目的。 但是,描述操作或操作目标的方法通常不止一种。 例如,进程可以按其名称、标识符或进程对象来标识。 该 cmdlet 应支持其目标的所有合理表示形式。 通常,cmdlet 通过指定一起操作的参数集(称为参数集)来满足此要求。 单个参数可以属于任意数量的参数集。 有关参数集的详细信息,请参阅 Cmdlet 参数集。
指定参数集时,仅将其中一个参数设置为 ValueFromPipeline。 有关如何声明 Parameter 属性的详细信息,请参阅 ParameterAttribute 声明。
使用参数集时,默认参数集由 Cmdlet 属性定义。 默认参数集应包含最有可能在交互式Windows PowerShell 会话中使用的参数。 有关如何声明 Cmdlet 属性的详细信息,请参阅 CmdletAttribute 声明。
向用户提供反馈(SD04)
使用本部分中的指南向用户提供反馈。 此反馈允许用户了解系统中发生的情况,并做出更好的管理决策。
Windows PowerShell 运行时允许用户通过设置首选项变量来指定如何处理对 Write 方法的每个调用的输出。 用户可以设置多个首选项变量,包括一个变量,用于确定系统是否应显示信息,以及一个变量,该变量确定系统是否应在执行进一步操作之前查询用户。
支持 WriteWarning、WriteVerbose 和 WriteDebug 方法
当 cmdlet 即将执行可能具有意外结果的操作时, cmdlet 应调用 System.Management.Automation.Cmdlet.WriteWarning 方法。 例如,当 cmdlet 即将覆盖只读文件时,应调用此方法。
当用户需要有关 cmdlet 执行的操作的一些详细信息时, cmdlet 应调用 System.Management.Automation.Cmdlet.WriteVerbose 方法。 例如,如果 cmdlet 作者认为在某些情况下可能需要详细了解 cmdlet 正在执行的操作,则 cmdlet 应调用此信息。
当开发人员或产品支持工程师必须了解 cmdlet 操作损坏的内容时,该 cmdlet 应调用 System.Management.Automation.Cmdlet.WriteDebug 方法。 cmdlet 不必在调用 System.Management.Automation.Cmdlet.WriteVerbose 方法的同一代码中调用 System.Management.Automation.Cmdlet.WriteDebug 方法,因为 Debug 参数提供了这两组信息。
支持对于长时间运行操作的写入进度
需要很长时间才能完成且无法在后台运行的 Cmdlet 操作应支持通过定期调用 System.Management.Automation.Cmdlet.WriteProgress 方法进行进度报告。
使用主机接口
有时,cmdlet 必须直接与用户通信,而不是使用 System.Management.Automation.Cmdlet 类支持的各种 Write 或 Should 方法。 在这种情况下,该 cmdlet 应派生自 System.Management.Automation.PSCmdlet 类,并使用 System.Management.Automation.PSCmdlet.Host* 属性。 此属性支持不同级别的通信类型,包括 PromptForChoice、Prompt 和 WriteLine/ReadLine 类型。 在最具体的级别,它还提供了读取和写入单个密钥以及处理缓冲区的方法。
除非 cmdlet 专门用于生成图形用户界面(GUI),否则它不应使用 System.Management.Automation.PSCmdlet.Host* 属性绕过主机。 旨在生成 GUI 的 cmdlet 的一个示例是 Out-GridView cmdlet。
注释
Cmdlet 不应使用 System.Console API。
创建 Cmdlet 帮助文件 (SD05)
对于每个 cmdlet 程序集,请创建一个 Help.xml 文件,其中包含有关 cmdlet 的信息。 此信息包括 cmdlet 的说明、cmdlet 参数的说明、cmdlet 的使用示例等。
代码准则
编码 cmdlet 时,应遵循以下准则,以确保使用 cmdlet 和其他 cmdlet 之间的一致用户体验。 找到适用于你的情况的代码准则时,请务必查看类似准则的设计指南。
编码参数 (SC01)
通过声明使用 Parameter 属性修饰的 cmdlet 类的公共属性来定义 参数 。 参数不必是 cmdlet 派生的 .NET Framework 类的静态成员。 有关如何声明 Parameter 属性的详细信息,请参阅 参数属性声明。
支持 Windows PowerShell 路径
Windows PowerShell 路径是规范化对命名空间的访问的机制。 将Windows PowerShell 路径分配给 cmdlet 中的参数时,用户可以定义充当特定路径快捷方式的自定义“驱动器”。 当用户指定此类驱动器时,可以采用一致的方式使用存储的数据(如注册表中的数据)。
如果 cmdlet 允许用户指定文件或数据源,则应定义 System.String 类型的参数。 如果支持多个驱动器,则类型应为数组。 参数的名称应为 Path别名 PSPath。
此外,参数 Path 应支持通配符。 如果不需要对通配符的支持,请定义参数 LiteralPath 。
如果 cmdlet 读取或写入的数据必须是文件,则 cmdlet 应接受 Windows PowerShell 路径输入,并且该 cmdlet 应使用 System.Management.Automation.SessionState.Path 属性将 Windows PowerShell 路径转换为文件系统识别的路径。 具体机制包括以下方法:
- System.Management.Automation.PSCmdlet.GetResolvedProviderPathFromPSPath
- System.Management.Automation.PSCmdlet.GetUnresolvedProviderPathFromPSPath
- System.Management.Automation.PathIntrinsics.GetResolvedProviderPathFromPSPath
- System.Management.Automation.PathIntrinsics.GetUnresolvedProviderPathFromPSPath
如果 cmdlet 读取或写入的数据只是一组字符串而不是文件,则 cmdlet 应使用提供程序内容信息(Content 成员)来读取和写入。 此信息是从 System.Management.Automation.Provider.CmdletProvider.InvokeProvider 属性获取的。 这些机制允许其他数据存储参与数据的读取和写入。
支持通配符
如果可能,cmdlet 应支持通配符。 对通配符的支持发生在 cmdlet 的许多位置(尤其是在参数采用字符串来标识一组对象时)。 例如,Stop-Proc中的示例 cmdlet 定义了一个Name参数来处理表示进程名称的字符串。 此参数支持通配符,以便用户可以轻松地指定要停止的进程。
当支持通配符时,cmdlet 操作通常会生成数组。 有时,支持数组并不有意义,因为用户一次只能使用单个项。 例如,Set-Location cmdlet 不需要支持数组,因为用户仅设置单个位置。 在此示例中,cmdlet 仍然支持通配符,但它会强制解析到一个单独位置。
有关通配符模式的详细信息,请参阅 Cmdlet 参数中支持通配符。
定义对象
本部分包含定义 cmdlet 对象和扩展现有对象的指南。
定义标准成员
定义标准成员以在自定义 Types.ps1xml 文件中扩展对象类型(使用 Windows PowerShell Types.ps1xml 文件作为模板)。 标准成员由名为 PSStandardMembers 的节点定义。 这些定义允许其他 cmdlet 和 Windows PowerShell 运行时以一致的方式处理对象。
定义要用作参数的对象成员
如果要为 cmdlet 设计对象,请确保其成员直接映射到将使用它的 cmdlet 的参数。 此映射使对象能够轻松地发送到管道,并在 cmdlet 之间传递。
cmdlet 返回的预先存在的.NET Framework 对象经常缺少脚本开发人员或用户所需的一些重要或方便的成员。 这些缺失成员对于显示和创建正确的成员名称尤其重要,以便可以正确将对象传递给管道。 创建自定义 Types.ps1xml 文件来记录这些所需成员。 创建此文件时,建议使用以下命名约定: <Your_Product_Name>。Types.ps1xml。
例如,可以将脚本属性添加到 ModeSystem.IO.FileInfo 类型,以便更清楚地显示文件的属性。 此外,可以将一个Count别名属性添加到System.Array类型中,以便一致地使用该属性名称(代替Length)。
实现 IComparable 接口
在所有输出对象上实现 System.IComparable 接口。 这使输出对象可以轻松地通过管道传递给各种排序和分析 cmdlet。
更新显示信息
如果对象的显示未提供预期结果,请为该对象创建自定义 <YourProductName> Format.ps1xml 文件。
支持良好定义的管道输入(SC02)
为管道中间部分实现
实现一个 cmdlet,假设它将从管道中间调用(也就是说,其他 cmdlet 将生成其输入或使用其输出)。 例如,你可能会假设 Get-Process cmdlet 是因为生成数据,所以它仅用于管道中的第一个 cmdlet。
但是,由于此 cmdlet 是为管道中间部分设计的,因此它允许管道中之前的 cmdlet 或数据指定要获取的进程。
支持来自管道的输入
在 cmdlet 的每个参数集中,至少包含一个支持管道输入的参数。 对管道输入的支持允许用户检索数据或对象,将其发送到正确的参数集,并将结果直接传递给 cmdlet。
如果 Parameter 属性在其声明中包括 ValueFromPipeline 关键字、 ValueFromPipelineByPropertyName 关键字属性或两个关键字,则参数接受管道中的输入。 如果参数集中的参数都不支持 ValueFromPipeline 或 ValueFromPipelineByPropertyName 关键字,则 cmdlet 不能在另一个 cmdlet 后面有意义地放置,因为它将忽略任何管道输入。
支持 ProcessRecord 方法
若要接受管道中上述 cmdlet 中的所有记录,cmdlet 必须实现 System.Management.Automation.Cmdlet.ProcessRecord 方法。 Windows PowerShell 针对发送到 cmdlet 的每个记录多次调用此方法。
将单个记录写入管道(SC03)
当 cmdlet 返回对象时,cmdlet 应立即在生成对象时写入这些对象。 该 cmdlet 不应保存它们,以便将它们缓冲到组合数组中。 接收作为输入的对象的 cmdlet 随后将能够处理、显示或处理和显示输出对象,而不会延迟。 一个一次生成输出对象的 cmdlet 应调用 System.Management.Automation.Cmdlet.WriteObject 方法。 一个 cmdlet 可分批生成输出对象(例如,因为基础 API 返回输出对象的数组)应调用 System.Management.Automation.Cmdlet.WriteObject 方法,其第二个参数设置为 true。
使 Cmdlet 不区分大小写且保留大小写(SC04)
默认情况下,Windows PowerShell 本身不区分大小写。 但是,由于它处理了许多预先存在的系统,Windows PowerShell 确实保留了方便操作和兼容性的情况。 换句话说,如果字符以大写字母提供,Windows PowerShell 将其保留为大写字母。 若要使系统正常工作,cmdlet 需要遵循此约定。 如果可能,它应以不区分大小写的方式运行。 但是,它应保留命令或管道中后续出现的 cmdlet 的原始大小写。