当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 创建不带参数的 Cmdlet

作者:精品下载站 日期:2024-12-14 02:49:37 浏览:12 分类:玩电脑

创建不带参数的 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 名称后,定义一个 .NET 类来实现该 cmdlet。以下是此示例 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 的类必须显式标记为 public。未标记为公共的类将默认为内部类,并且 Windows PowerShell 运行时不会找到它们。

Windows PowerShell 将 Microsoft.PowerShell.Commands 命名空间用于其 cmdlet 类。建议将 cmdlet 类放置在 API 命名空间的 Commands 命名空间中,例如 xxx.PS.Commands。

重写输入处理方法

System.Management.Automation.Cmdlet 类提供三种主要的输入处理方法,您的 cmdlet 必须至少重写其中一种方法。有关 Windows PowerShell 如何处理记录的详细信息,请参阅 Windows PowerShell 的工作原理。

对于所有类型的输入,Windows PowerShell 运行时都会调用 System.Management.Automation.Cmdlet.BeginProcessing 来启用处理。如果您的 cmdlet 必须执行某些预处理或设置,则可以通过重写此方法来完成此操作。

笔记

Windows PowerShell 使用术语“记录”来描述调用 cmdlet 时提供的参数值集。

如果您的 cmdlet 接受管道输入,则它必须重写 System.Management.Automation.Cmdlet.ProcessRecord 方法,也可以重写 System.Management.Automation.Cmdlet.EndProcessing 方法。例如,如果 cmdlet 使用 System.Management.Automation.Cmdlet.ProcessRecord 收集所有输入,然后将输入作为一个整体而不是一次对一个元素进行操作,则它可能会覆盖这两种方法,如 Sort-Object cmdlet 可以。

如果您的 cmdlet 不接受管道输入,则它应该重写 System.Management.Automation.Cmdlet.EndProcessing 方法。请注意,当 cmdlet 无法一次对一个元素进行操作(排序 cmdlet 的情况)时,经常使用此方法来代替 System.Management.Automation.Cmdlet.BeginProcessing。

由于此示例 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 可能很长时间不会返回,或者根本不会返回。因此,cmdlet 中的输入处理方法在调用 System.Management.Automation.Cmdlet.WriteObject 期间不应持有锁,尤其是范围超出 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 入门。

  1. 启动 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
    ...
    
  2. 将变量分配给 cmdlet 结果以便于操作。

    $p=get-proc
    
  3. 获取进程数。

    $p.length
    

    将出现以下输出。

    63
    
  4. 检索特定进程。

    $p[6]
    

    将出现以下输出。

    Handles  NPM(K)  PM(K)  WS(K)  VS(M)  CPU(s)  Id    ProcessName
    -------  ------  -----  -----  -----  ------  --    -----------
    1033     3       2400   3336   35     0.53    1588  rundll32
    
  5. 获取此过程的开始时间。

    $p[6].starttime
    

    将出现以下输出。

    Tuesday, July 26, 2005 9:34:15 AM
    
    $p[6].starttime.dayofyear
    
    207
    
  6. 获取句柄数大于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
    ...
    
  7. 使用 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...
    ...
    

参见

创建 Cmdlet 来处理命令行输入

创建 Cmdlet 来处理管道输入

如何创建 Windows PowerShell Cmdlet

扩展对象类型和格式

Windows PowerShell 的工作原理

如何注册 Cmdlet、提供程序和主机应用程序

Windows PowerShell 参考

Cmdlet 示例

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯