创建不具有参数的 Cmdlet
本部分介绍如何创建一个 cmdlet,该 cmdlet 从本地计算机检索信息而不使用参数,然后将信息写入管道。 此处所述的 cmdlet 是一个 Get-Proc cmdlet,用于检索有关本地计算机进程的信息,然后在命令行中显示该信息。
注释
请注意,编写 cmdlet 时,Windows PowerShell® 引用程序集将下载到磁盘上(默认情况下,C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0)。 它们未安装在全局程序集缓存(GAC)中。
命名 Cmdlet
cmdlet 名称由一个谓词组成,该谓词指示 cmdlet 执行的作,以及指示 cmdlet 所针对的项的名词。 由于此示例 Get-Proc cmdlet 检索进程对象,因此它使用由 System.Management.Automation.VerbsCommon 枚举定义的谓词“Get”,以及名词“Proc”来指示该 cmdlet 适用于进程项。
命名 cmdlet 时,请勿使用以下任何字符:# 、() {} [] & - /\ $ ;:“'<> | ? @ ` .
选择名词
应选择一个特定于名词。 最好使用以缩短版本的产品名称为前缀的单一名词。 此类型的 cmdlet 名称示例为“Get-SQLServer
”。
选择谓词
应使用一组已批准的 cmdlet 谓词名称中的谓词。 有关批准的 cmdlet 谓词的详细信息,请参阅 Cmdlet 谓词名称。
定义 Cmdlet 类
选择 cmdlet 名称后,定义用于实现 cmdlet 的 .NET 类。 下面是此示例 Get-Proc cmdlet 的类定义:
[Cmdlet(VerbsCommon.Get, "Proc")]
public class GetProcCommand : Cmdlet
<Cmdlet(VerbsCommon.Get, "Proc")> _
Public Class GetProcCommand
Inherits Cmdlet
请注意,在类定义之前,System.Management.Automation.CmdletAttribute 属性(语法 [Cmdlet(verb, noun, ...)]
)用于将此类标识为 cmdlet。 这是所有 cmdlet 的唯一必需属性,它允许 Windows PowerShell 运行时正确调用它们。 可以根据需要设置属性关键字以进一步声明类。 请注意,示例 GetProcCommand 类的属性声明仅声明 Get-Proc cmdlet 的名词和谓词名称。
注释
对于所有 Windows PowerShell 属性类,可以设置的关键字对应于属性类的属性。
命名 cmdlet 的类时,最好在类名中反映 cmdlet 名称。 为此,请使用格式“VerbNounCommand”,并将“Verb”和“Noun”替换为 cmdlet 名称中使用的谓词和名词。 如前面的类定义所示,示例 Get-Proc cmdlet 定义了一个名为 GetProcCommand 的类,该类派生自 System.Management.Automation.Cmdlet 基类。
重要
如果要定义直接访问 Windows PowerShell 运行时的 cmdlet,则 .NET 类应派生自 System.Management.Automation.PSCmdlet 基类。 有关此类的详细信息,请参阅 创建定义参数集的 Cmdlet。
注释
cmdlet 的类必须显式标记为公共。 未标记为公共的类将默认为内部类,并且不会由 Windows PowerShell 运行时找到。
Windows PowerShell 对其 cmdlet 类使用 Microsoft.PowerShell.Commands 命名空间。 建议将 cmdlet 类放置在 API 命名空间的 Commands 命名空间中,例如 xxx.PS。命令。
重写输入处理方法
System.Management.Automation.Cmdlet 类提供三种主要的输入处理方法,其中至少一种是 cmdlet 必须重写的。 有关 Windows PowerShell 如何处理记录的详细信息,请参阅 Windows PowerShell 的工作原理。
对于所有类型的输入,Windows PowerShell 运行时调用 System.Management.Automation.Cmdlet.BeginProcessing 以启用处理。 如果 cmdlet 必须执行一些预处理或设置,则可以通过重写此方法来执行此作。
注释
Windows PowerShell 使用术语“record”来描述调用 cmdlet 时提供的参数值集。
如果 cmdlet 接受管道输入,则必须替代 System.Management.Automation.Cmdlet.ProcessRecord 方法,并选择性地替代 System.Management.Automation.Cmdlet.EndProcessing 方法。 例如,如果 cmdlet 使用 System.Management.Automation.Cmdlet.ProcessRecord 收集所有输入,然后一次对输入执行作,而不是一个元素,就像 Sort-Object
cmdlet 一样,则 cmdlet 可能会重写这两种方法。
如果 cmdlet 不采用管道输入,则应替代 System.Management.Automation.Cmdlet.EndProcessing 方法。 请注意,此方法经常用于代替 System.Management.Automation.Cmdlet.BeginProcessing 当 cmdlet 一次不能对一个元素进行作时,就像排序 cmdlet 的情况一样。
由于此示例 Get-Proc cmdlet 必须接收管道输入,因此它将替代 System.Management.Automation.Cmdlet.ProcessRecord 方法,并使用 System.Management.Automation.Cmdlet.BeginProcessing 的默认实现,System.Management.Automation.Cmdlet.EndProcessing。 System.Management.Automation.Cmdlet.ProcessRecord 重写检索进程,并使用 System.Management.Automation.Cmdlet.WriteObject 方法将其写入命令行。
protected override void ProcessRecord()
{
// Get the current processes
Process[] processes = Process.GetProcesses();
// Write the processes to the pipeline making them available
// to the next cmdlet. The second parameter of this call tells
// PowerShell to enumerate the array, and send one process at a
// time to the pipeline.
WriteObject(processes, true);
}
Protected Overrides Sub ProcessRecord()
'/ Get the current processes.
Dim processes As Process()
processes = Process.GetProcesses()
'/ Write the processes to the pipeline making them available
'/ to the next cmdlet. The second parameter of this call tells
'/ PowerShell to enumerate the array, and send one process at a
'/ time to the pipeline.
WriteObject(processes, True)
End Sub 'ProcessRecord
有关输入处理的注意事项
输入的默认源是用户在命令行上提供的显式对象(例如字符串)。 有关详细信息,请参阅 创建 Cmdlet 来处理命令行输入。
输入处理方法还可以从管道上上游 cmdlet 的输出对象接收输入。 有关详细信息,请参阅 创建 Cmdlet 以处理管道输入。 请注意,cmdlet 可以从命令行和管道源的组合接收输入。
下游 cmdlet 可能不会长时间返回,或者根本不返回。 因此,在调用 System.Management.Automation.Cmdlet.WriteObject 时,cmdlet 中的输入处理方法不应持有锁,尤其是范围扩展到 cmdlet 实例之外的锁。
重要
Cmdlet 绝不应调用 System.Console.Writeline* 或其等效项。
- cmdlet 在完成处理时可能具有要清理的对象变量(例如,如果在 System.Management.Automation.Cmdlet.BeginProcessing 方法中打开文件句柄,并使句柄保持打开状态以供 System.Management.Automation.Cmdlet.ProcessRecord使用)。 请务必记住,Windows PowerShell 运行时并不总是调用 System.Management.Automation.Cmdlet.EndProcessing 方法,该方法应执行对象清理。
例如,如果 cmdlet 在中途取消或 cmdlet 的任何部分发生终止错误,则可能不会调用 System.Management.Automation.Cmdlet.EndProcessing。 因此,需要对象清理的 cmdlet 应实现完整的 System.IDisposable 模式,包括终结器,以便运行时可以在处理结束时调用 System.Management.Automation.Cmdlet.EndProcessing 和 System.IDisposable.Dispose*。
代码示例
有关完整的 C# 示例代码,请参阅 GetProcessSample01 示例。
定义对象类型和格式
Windows PowerShell 使用 .NET 对象在 cmdlet 之间传递信息。 因此,cmdlet 可能需要定义自己的类型,或者 cmdlet 可能需要扩展另一个 cmdlet 提供的现有类型。 有关定义新类型或扩展现有类型的详细信息,请参阅 扩展对象类型和格式。
生成 Cmdlet
实现 cmdlet 后,必须通过 Windows PowerShell 管理单元将其注册到 Windows PowerShell。 有关注册 cmdlet 的详细信息,请参阅 如何注册 Cmdlet、提供程序和主机应用程序。
测试 Cmdlet
将 cmdlet 注册到 Windows PowerShell 后,可以通过在命令行上运行它来测试它。 示例 Get-Proc cmdlet 的代码很小,但它仍然使用 Windows PowerShell 运行时和现有的 .NET 对象,这足以使其有用。 让我们测试它,以更好地了解 Get-Proc 可以执行的作及其输出的使用方式。 有关从命令行使用 cmdlet 的详细信息,请参阅 windows PowerShell 入门。
启动 Windows PowerShell,并获取计算机上运行的当前进程。
Get-Proc
将显示以下输出。
Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ---------- 254 7 7664 12048 66 173.75 1200 QCTRAY 32 2 1372 2628 31 0.04 1860 DLG 271 6 1216 3688 33 0.03 3816 lg 27 2 560 1920 24 0.01 1768 TpScrex ...
将变量分配给 cmdlet 结果,以便更轻松地作。
$p=Get-Proc
获取进程数。
$p.Length
将显示以下输出。
63
检索特定进程。
$p[6]
将显示以下输出。
Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 1033 3 2400 3336 35 0.53 1588 rundll32
获取此过程的开始时间。
$p[6].StartTime
将显示以下输出。
Tuesday, July 26, 2005 9:34:15 AM
$p[6].StartTime.DayOfYear
207
获取句柄计数大于 500 的进程,然后对结果进行排序。
$p | Where-Object {$_.HandleCount -gt 500 } | Sort-Object HandleCount
将显示以下输出。
Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ---------- 568 14 2164 4972 39 5.55 824 svchost 716 7 2080 5332 28 25.38 468 csrss 761 21 33060 56608 440 393.56 3300 WINWORD 791 71 7412 4540 59 3.31 492 winlogon ...
使用
Get-Member
cmdlet 列出每个进程可用的属性。$p | Get-Member -MemberType Property
TypeName: System.Diagnostics.Process
将显示以下输出。
Name MemberType Definition ---- ---------- ---------- BasePriority Property System.Int32 BasePriority {get;} Container Property System.ComponentModel.IContainer Conta... EnableRaisingEvents Property System.Boolean EnableRaisingEvents {ge... ...