- 示例工程
【免费下载链接】Windows-classic-samples
This repo contains samples that demonstrate the API used in Windows classic desktop applications.
导读
本文以 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,本样例演示两件事:
- 创建最基本的 cmdlet——一个名为
Get-Proc的命令,功能是枚举本地计算机上的进程; - 创建可用的 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.csproj | MSBuild 项目文件,输出类库(Library)并引用 PowerShell 程序集 |
| GetProcessSample01.sln | Visual 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); }这是本样例最核心的代码,其工作流分两步:
- 数据获取:调用 .NET 的
System.Diagnostics.Process.GetProcesses()(源码已using System.Diagnostics;)一次性取得本地计算机当前全部进程数组; - 管道输出:调用
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 步骤:
- 启动 Microsoft Visual Studio,选择File→Open→Project/Solution;
- 进入样例目录(仓库内即 Samples/PowerShell/Process/GetProcess01/cs),双击其中的 Visual Studio 解决方案文件
GetProcessSample01.sln; - 按F7或使用Build→Build Solution构建样例,类库将生成到默认的
\bin或\bin\Debug目录。
运行样例:从注册到执行 Get-Proc
运行前需明确:cmdlet 必须先经Installutil注册、再由 PowerShell 加载 snap-in 后才能使用。完整流程如下:
- 打开管理员命令提示符(Start an elevated Command Prompt window),注册操作需要管理员权限;
- 切换到 DLL 所在目录,即包含
GetProcessSample01.dll的构建输出目录; - 注册程序集:执行
installutil "GetProcessSample01.dll"这一步通过
[RunInstaller(true)]特性触发的安装器把 snap-in 元数据写入系统注册表。README 特别提醒:在 64 位操作系统上,必须运行 64 位版本的 installutil,否则会因位数不匹配导致注册失败; - 启动 Windows PowerShell;
- 加载 snap-in:
Add-PSSnapin GetProcPSSnapIn01此命令把 snap-in 添加到当前 Shell 会话。
GetProcPSSnapIn01正是源码中Name属性返回的注册名; - 执行 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 执行”的完整链路。其中值得记住的三个核心知识点:
[Cmdlet(VerbsCommon.Get, "Proc")]+ 继承Cmdlet定义了命令身份与执行上下文;- 重写
ProcessRecord()+WriteObject(obj, true)实现了进程枚举与逐对象管道输出,这也是所有“产出型” cmdlet 的标准写法; 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.
相关推荐
Bioicons许可证解析:CC-0与MIT协议下的图标使用规范
Bioicons许可证解析:CC 0与MIT协议下的图标使用规范 Bioicons是一个为生物学和化学科学插图提供免费开源图标的库,其图标资源采用多种开源许可证
GPT-SoVITS 完全指南:5 秒参考音频语音克隆,1 分钟数据微调专属 TTS
GPT SoVITS 完全指南:5 秒参考音频语音克隆,1 分钟数据微调专属 TTS 给播客、视频或游戏角色配音,你通常得付钱请人专业录音,或者接受机械感的默认
语音音频人工智能大模型微调模型推理服务本地部署终极指南:从零实现自定义CAM算法,基于PyTorch-Grad-CAM框架
终极指南:从零实现自定义CAM算法,基于PyTorch Grad CAM框架 想要深入理解深度学习模型的黑箱决策过程吗?🤔 想要为你的计算机视觉项目开发定制化
人工智能AI 可解释性计算机视觉深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考