构建 PowerShell cmdlet






4.20/5 (10投票s)
了解如何构建简单的 Windows PowerShell cmdlet,使用参数、通配符、CustomPSSnapin 和扩展类型系统。
什么是 Windows PowerShell?
Windows PowerShell(又名 Monad)是 Microsoft 提供的一个新的 CLI(命令行界面)。PowerShell 基于 .NET Framework 2.0,以 .NET 对象的形式传递数据。
我们将要做什么?
在本文中,您将了解如何开发支持通配符并使用 ETS(扩展类型系统)的 commandlet(cmdlet,PowerShell 命令),以及如何使用 CustomPSSnapIn。
该示例使用 IIS 7 和 IIS 7 .NET 库(Microsoft.Web.Administration)来检索本地 IIS 7 服务器上的网站列表。
如何开始?
Cmdlet 究竟是什么?
Cmdlet 是派生自 System.Management.Automation.Cmdlet
或 System.Management.Automation.PSCmdlet
的小型 .NET 类,并覆盖一些方法以实现您自己的逻辑。Cmdlet 被安装到 PowerShell 中,可以从 PowerShell 中使用,或者从使用 PowerShell 调用 cmdlet 的其他应用程序中使用。
Cmdlet 与 PSCmelet
Cmdlet 类可以派生自两个不同的类:Cmdlet
和 PSCmdlet
。区别在于您对 Windows PowerShell 环境的依赖程度。当派生自 Cmdlet
时,您实际上不依赖于 PowerShell。您不会受到 PowerShell 运行时任何更改的影响。此外,您的 cmdlet 可以直接从任何应用程序调用,而不是通过 Windows PowerShell 运行时调用。
在大多数情况下,派生自 Cmdlet
是最佳选择,除非您需要与 PowerShell 运行时完全集成、访问会话状态数据、调用脚本等。那时,您将派生自 PSCmdlet
。
Cmdlet 属性
每个 cmdlet 都遵循相同的模板命名:动词-名词。动词(get、set、new、add 等)来自内置的动词名称列表。名词由您选择。
Cmdlet 类(getWebsites.cs)的第一个部分是
[Cmdlet(VerbsCommon.Get, "ws" SupportsShouldProcess = true)]
动词是“Get
”(来自枚举 VerbsCommon
),名词是“ws
”,我们支持 ShouldProcess
。使用枚举中的动词非常重要。
请注意,在代码顶部,我有这些 using
语句
using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;
using System.Collections;
using Microsoft.Web.Administration;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reflection;
加粗的部分是“特殊”命名空间,与 PowerShell 相关,而 Microsoft.Web.Administration
用于管理 IIS 7。
参数
几乎任何 PowerShell cmdlet 都会使用参数来帮助用户获取相关信息。参数实际上是前面带有 ParameterAttribute
的属性
[Parameter(Position = 0,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Enter filter by site name (support wildcard)")]
[Alias("SiteName")]
public string Name
{
set { names = value; }
}
参数可以通过位置或属性名称访问。这意味着,如果我们在位置 0 设置参数,您可以这样调用 cmdlet:get-websites *。“*”是参数,或者使用属性名称:get-websites -Name *。在这里,我们还定义了别名:get-websites -SiteName *。
必需参数意味着用户必须为该参数输入一个值。
主要逻辑
在我们的 cmdlet 中,我们可以覆盖几个方法。我们至少需要覆盖此列表中的一个方法
BeginProcessing
这里的大部分代码用于准备 cmdlet。这段代码只运行一次,在调用 cmdlet 时执行。
ProcessRecord
这是最常被覆盖的方法。此方法包含主要逻辑。根据需要,代码可以运行多次。
EndProcessing
此被覆盖的方法用于完成 cmdlet 操作。
我们还可以覆盖 StopProcessing
方法,其中包含在 cmdlet 意外停止时(例如,用户按下 Ctrl+c)运行的代码。
我只覆盖了 ProcessRecord
方法。首先,我创建了一个通用的 System.Collections.ObjectModel.Collection<>
集合实例。这是 PowerShell 使用的集合类型。类型是 PSObject
,这是 PowerShell 使用的主要对象。
因为我们要支持通配符,所以我使用了 PowerShell 自带的通配符类。
WildcardOptions options = WildcardOptions.IgnoreCase |WildcardOptions.Compiled;
WildcardPattern wildcard = new WildcardPattern(names, options);
然后,我们创建 Microsoft.Web.Administration.ServerManager
的实例,该对象用于管理 IIS 7 网站。
在 foreach
循环中,我们检查每个站点是否与通配符匹配。如果匹配,则将其转换为 PSObject
。
扩展类型系统
扩展类型系统是 PowerShell 主要且最有趣的概念之一。我们可以扩展任何我们想要的类型,并在内置成员的基础上添加新成员。PSObject
对象是 PowerShell 中的主要对象,因为它在一个对象中包含了原始对象和扩展的成员,并允许调用此 cmdlet 的用户使用任何成员——原始成员和扩展成员。
ps.Properties.Add(new PSNoteProperty("MaxBandwidthMB", site.Limits.MaxBandwidth / 1024));
在这里,我们添加了一个名为 MaxBandwidthMB
的新属性,其值为原始带宽值 / 1024。
类型可以从代码或 XML 文件中以特定格式进行扩展。在这里,我们将看到一个通过新属性扩展类型的示例——但是我们可以从许多类型添加属性和方法:别名、脚本、代码方法等。
最后,我们将包含原始(早期绑定对象)和扩展成员的 PSObject
实例添加到集合中,并使用 WriteHost
方法将其写入主机(可以是 PowerShell 命令行主机,也可以是调用我们 cmdlet 的其他应用程序)。
完成 cmdlet 后,您可以获取从 cmdlet 返回的对象的成员列表。您可以在此处看到我们的扩展属性(已标记)
发生异常时...
我们使用 try...catch
语句,如果发生异常,我们使用 WriteError
方法将错误信息写入主机。
格式
现在从控制台使用此 cmdlet,我们将看到奇怪的输出,其中包括对象类型和一些值。我们必须指定我们想要的默认输出视图。我们在 format.ps1xml 文件中这样做。请注意,我们使用了 MaxBandwidthMB
属性,这是一个扩展属性。
这是没有格式化文件的输出
Snap In
Snap-in 包含 PowerShell 安装 cmdlet 所需的详细信息。我们可以从“默认”的 PSSnapIn
派生——安装所有能安装的,或者从 CustomPSSnapIn
派生,然后我们精确设置要做什么。
在这里,我们添加了 cmdlet 和格式文件。
首先,我们为 cmdlet、格式、类型和提供程序定义了一个集合。在构造函数中,我们添加了 cmdlet 和格式文件。我们还覆盖了一些属性以包含有关我们的 snap-in 的信息。并且,我们覆盖了返回我们的 cmdlet 和格式集合的属性。
安装
在 PowerShell 中,我们使用 installutil.exe(.NET Framework SDK 的一部分)来安装 snap-in。我写了一个可以添加到您的配置文件的简单函数。
function installutil
{
param([string]$dllPath=$(throw "Please Enter the DLL path to Install!"))
set-alias installutil $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil
if(test-path $dllPath)
{
installutil /u $dllpath
installutil $dllpath
write-host "snap-in installed. now, you can add it to your shell instance"
}
else{
write-error "The file does not exist"
}
}
现在,您只需输入
installutil dllPath
在 dllPath 处,输入包含项目 DLL 的 DLL 的完整路径。
现在,您需要添加 snap-in
add-pssnapin cpdemo
请注意,您可能需要在 snapin.cs 类文件中更改格式文件的路径。
就这样! cmdlet 已准备好使用,并返回一个 PSObject
集合,其中包含 Microsoft.Web.Administration.Site
和一个扩展属性。
在 PowerShell 中,您可以使用 cmdlet 返回的对象进行更多操作。例如,此命令将输出保存到 CSV 文件。
get-ws d* | Where{$_.MaxBandwidthMB -gt 4000000} |
Select-Object Name,MaxBandwidthMB | out-csv c:\csv.csv
此命令将保存一个新的 CSV 文件,其中包含所有网站的名称列表和 MaxBandwidthMB
属性,这些网站的名称以“d”开头,并且 MaxBandwidthMB
属性值 > 4000000。