news 2026/10/15 2:16:26

Windows PowerShell 自定义 Cmdlet 入门:基于 GetProcessSample01 从零实现 Get-Proc 与 Snap-in

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows PowerShell 自定义 Cmdlet 入门:基于 GetProcessSample01 从零实现 Get-Proc 与 Snap-in
  • 示例工程

【免费下载链接】Windows-classic-samples

This repo contains samples that demonstrate the API used in Windows classic desktop applications.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-classic-samples
点击查看免费下载

导读

本文以 Windows-classic-samples 仓库中的 GetProcessSample01 样例为骨架,完整讲解如何用 C# 编写一个最简单的 PowerShell 自定义 cmdlet,并通过 Windows PowerShell 1.0 时代经典的Snap-in(管理单元)机制将其注册到 Shell 中。读完本文,你将掌握Cmdlet基类与[Cmdlet(...)]特性的用法、ProcessRecord()重写与WriteObject()管道输出机制、PSSnapIn派生类的注册原理,以及installutil+Add-PSSnapin的完整部署运行流程,为后续学习带参数、带输入过滤的进阶 cmdlet 打下基础。

示例目标:第一个“能跑起来”的自定义 Cmdlet

根据 README.md 中的 Sample Objectives,本样例演示两件事:

  1. 创建最基本的 cmdlet——一个名为Get-Proc的命令,功能是枚举本地计算机上的进程;
  2. 创建可用的 PowerShell Snap-in——一个适用于 Windows PowerShell 1.0 及以上版本的 snap-in,用于承载上述 cmdlet。

值得注意的是,README 特别说明:后续样例将改用模块(Module,Windows PowerShell 2.0 引入的特性)来取代 snap-in。从仓库目录结构可以印证这一点:Samples/PowerShell/Process 下共有 GetProcess01 到 GetProcess05 五个渐进式样例,以及 StopProcessSample01 到 StopProcessSample04 四个配套样例,后续版本逐步引入了参数、管道输入、ShouldProcess 确认等更复杂的特性。

项目结构与文件清单

样例代码为 C# 实现,位于仓库的 Samples/PowerShell/Process/GetProcess01/cs 目录,文件组成如下:

文件作用
GetProcessSample01.cs核心源码:cmdlet 类 + snap-in 类
GetProcessSample01.csprojMSBuild 项目文件,输出类库(Library)并引用 PowerShell 程序集
GetProcessSample01.slnVisual Studio 2012 解决方案文件
AssemblyInfo.cs程序集元数据(AssemblyTitle / AssemblyDescription 等)
Readme.txt样例说明与构建/运行步骤

对应的顶层 README.md 给出官方摘要:本样例展示“如何创建一个简单 cmdlet”,适用于 Windows 8.1 客户端与 Windows Server 2012 R2 服务器环境。

源码精读:GetProcCommand 与 GetProcPSSnapIn01

Cmdlet 类的声明

源码在命名空间Microsoft.Samples.PowerShell.Commands下定义了命令类,声明方式如下:

[Cmdlet(VerbsCommon.Get, "Proc")] public class GetProcCommand : Cmdlet
  • [Cmdlet(VerbsCommon.Get, "Proc")]特性声明命令动词为Get、名词为Proc,两者组合即命令名Get-Proc。VerbsCommon.Get是 PowerShell SDK 提供的标准动词常量,遵循 PowerShell 的“动词-名词”命名规范。
  • 类必须继承自Cmdlet基类(位于System.Management.Automation命名空间),这是所有 cmdlet 实现的共同父类。源码文件顶部也相应引用了using System.Management.Automation;并注释标明这是 Windows PowerShell 命名空间。

重写 ProcessRecord():命令的真正逻辑

protected override void ProcessRecord() { // Retrieve the current processes. Process[] processes = Process.GetProcesses(); // Write the processes to the pipeline ... WriteObject(processes, true); }

这是本样例最核心的代码,其工作流分两步:

  1. 数据获取:调用 .NET 的System.Diagnostics.Process.GetProcesses()(源码已using System.Diagnostics;)一次性取得本地计算机当前全部进程数组;
  2. 管道输出:调用WriteObject(processes, true)将结果写入管道。第二个参数true的含义在源码注释中解释得很清楚——它指示 PowerShell枚举该数组,将每个进程对象逐一发送到管道(而非把整个数组当作单个对象输出)。

ProcessRecord()是Cmdlet基类的关键虚方法:当 cmdlet 处理管道中的每个输入对象时都会被调用。本样例没有声明输入参数,因此该方法在命令执行时调用一次,完成进程枚举与输出。正是这种“处理完立刻写出”的机制,使得 cmdlet 可以与其他命令级联,例如Get-Proc | Where-Object {...}、Get-Proc | Select-Object Name等。

Snap-in 类:让 cmdlet 可被 PowerShell 发现

仅有 cmdlet 类还不够——PowerShell 需要一种机制来发现并加载程序集中的命令。本样例采用 Snap-in 方式,定义如下:

[RunInstaller(true)] public class GetProcPSSnapIn01 : PSSnapIn { public override string Name => "GetProcPSSnapIn01"; public override string Vendor => "Microsoft"; public override string VendorResource => "GetProcPSSnapIn01,Microsoft"; public override string Description => "This is a PowerShell snap-in that includes the get-proc cmdlet."; }

关键点逐一说明:

  • 类继承自PSSnapIn基类,并标注[RunInstaller(true)](System.ComponentModel命名空间)——该特性使类可被 .NET 的Installutil.exe工具识别为安装器,从而完成 snap-in 的系统级注册;
  • Name:返回GetProcPSSnapIn01,这是 snap-in 的注册名,将直接用于后面的Add-PSSnapin GetProcPSSnapIn01命令;
  • Vendor/VendorResource:提供供应商信息与本地化资源定位字符串(格式为资源基名,资源名),本样例直接返回"Microsoft"与"GetProcPSSnapIn01,Microsoft";
  • Description:为 snap-in 提供一句话描述,说明其包含 get-proc cmdlet。

同时,源码文件头部的注释也给出了完整的自测路径提示:先运行installutil GetProcessSample01.dll注册 snap-in,再执行Add-PSSnapin GetProcessSnapIn01加载,最后执行get-proc。

项目配置解读:csproj 与解决方案

GetProcessSample01.csproj 中与本样例运行方式密切相关的配置项包括:

  • <OutputType>Library</OutputType>:输出类型为类库(DLL),而不是可执行程序——因为 cmdlet 不是独立程序,而是被 PowerShell 宿主进程加载的动态库;
  • <AssemblyName>GetProcessSample01</AssemblyName>:程序集名,编译产物即GetProcessSample01.dll;
  • <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>:目标框架为 .NET Framework 4.0;
  • 程序集引用:除标准System、System.Data、System.Xml外,还引用了System.Management以及System.Management.Automation, Version=3.0.0.0(PowerShell 命名空间所在程序集,HintPath 指向 GAC 中的对应 DLL),同时引用了System.Configuration.Install——这是Installutil注册器与[RunInstaller]特性工作的基础;
  • 输出路径:Debug 配置输出到.\bin\Debug\,Release 配置输出到.\bin\Release\,与 README 中“程序集构建于默认 \bin 或 \bin\Debug 目录”的描述一致。

GetProcessSample01.sln 为 Visual Studio 2012 格式(Format Version 11.00),仅含 GetProcessSample01 一个项目,提供 Debug/Release 与 Any CPU 平台配置。

构建样例:Visual Studio 三步走

按 README.md 的 Build the sample 步骤:

  1. 启动 Microsoft Visual Studio,选择File→Open→Project/Solution;
  2. 进入样例目录(仓库内即 Samples/PowerShell/Process/GetProcess01/cs),双击其中的 Visual Studio 解决方案文件GetProcessSample01.sln;
  3. 按F7或使用Build→Build Solution构建样例,类库将生成到默认的\bin或\bin\Debug目录。

运行样例:从注册到执行 Get-Proc

运行前需明确:cmdlet 必须先经Installutil注册、再由 PowerShell 加载 snap-in 后才能使用。完整流程如下:

  1. 打开管理员命令提示符(Start an elevated Command Prompt window),注册操作需要管理员权限;
  2. 切换到 DLL 所在目录,即包含GetProcessSample01.dll的构建输出目录;
  3. 注册程序集:执行
    installutil "GetProcessSample01.dll"

    这一步通过[RunInstaller(true)]特性触发的安装器把 snap-in 元数据写入系统注册表。README 特别提醒:在 64 位操作系统上,必须运行 64 位版本的 installutil,否则会因位数不匹配导致注册失败;

  4. 启动 Windows PowerShell;
  5. 加载 snap-in:
    Add-PSSnapin GetProcPSSnapIn01

    此命令把 snap-in 添加到当前 Shell 会话。GetProcPSSnapIn01正是源码中Name属性返回的注册名;

  6. 执行 cmdlet:
    Get-Proc

    命令运行后即输出本地全部进程对象——由于WriteObject(processes, true)的枚举语义,每个进程会作为独立对象逐条进入管道显示。

另外,在注册过程中若遇到问题,可通过Get-PSSnapin -Registered查看已注册的 snap-in 列表来验证安装是否成功;卸载时则可使用installutil /u "GetProcessSample01.dll"完成反注册。

从 Snap-in 到 Module:演进脉络

README 明确指出,后续样例将使用Module(Windows PowerShell 2.0 特性)取代 snap-in 机制。这一演进在本仓库中清晰可见:Samples/PowerShell/Process 目录下 GetProcess02 至 GetProcess05、StopProcessSample01 至 StopProcessSample04 等样例,逐步演示了带参数声明([Parameter])、管道输入处理(ProcessRecord输入对象)、ShouldProcess确认机制等能力。理解本文的 Snap-in 流程,是理解后续 Module 装载方式(Import-Module)以及 cmdlet 生命周期的基础——二者共享同一套Cmdlet基类与特性体系,差异主要在于程序集的发现与装载机制。

小结

通过 GetProcessSample01,我们走通了“编写 cmdlet 类 → 编写 snap-in 类 → 编译为类库 → Installutil 注册 → Add-PSSnapin 装载 → Get-Proc 执行”的完整链路。其中值得记住的三个核心知识点:

  1. [Cmdlet(VerbsCommon.Get, "Proc")]+ 继承Cmdlet定义了命令身份与执行上下文;
  2. 重写ProcessRecord()+WriteObject(obj, true)实现了进程枚举与逐对象管道输出,这也是所有“产出型” cmdlet 的标准写法;
  3. PSSnapIn派生类 +[RunInstaller(true)]是 PowerShell 1.0/2.0 时代注册自定义命令的必备机制,其注册名必须与Add-PSSnapin的参数完全一致。

如需继续深入学习,可对照阅读仓库中同目录的后续样例 GetProcess02 等文件,观察参数与管道输入如何一步步引入。

  • 示例工程

【免费下载链接】Windows-classic-samples

This repo contains samples that demonstrate the API used in Windows classic desktop applications.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-classic-samples
点击查看免费下载

相关推荐

上一篇:终极指南:Lime路线图重构如何让这款Sublime替代编辑器更强大?
下一篇:keyphrase-extraction-distilbert-inspec背后的技术:DistilBERT模型与Inspec数据集深度解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 2:12:51

Spring Boot应用监控实战:Actuator + Micrometer + Prometheus + Grafana

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 2:12:34

嵌入式GUI是库还是系统?FlyThings OS三层架构解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 2:12:28

Natron ClipTest 节点使用指南:用斑马纹精准检出画面颜色越界

音视频视频处理图形学桌面应用 【免费下载链接】Natron Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/na/Natron 点击查看 …

作者头像 李华