65.9K
CodeProject 正在变化。 阅读更多。
Home

构建 PowerShell cmdlet

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (10投票s)

2007年10月14日

CPOL

6分钟阅读

viewsIcon

80927

downloadIcon

638

了解如何构建简单的 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 服务器上的网站列表。

如何开始?

  1. 首先,当然要 下载 Windows PowerShell
  2. 下载 Windows SDK
  3. 下载 Visual Studio 的 PowerShell 模板(可选)。

Cmdlet 究竟是什么?

Cmdlet 是派生自 System.Management.Automation.CmdletSystem.Management.Automation.PSCmdlet 的小型 .NET 类,并覆盖一些方法以实现您自己的逻辑。Cmdlet 被安装到 PowerShell 中,可以从 PowerShell 中使用,或者从使用 PowerShell 调用 cmdlet 的其他应用程序中使用。

Cmdlet 与 PSCmelet

Cmdlet 类可以派生自两个不同的类:CmdletPSCmdlet。区别在于您对 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 返回的对象的成员列表。您可以在此处看到我们的扩展属性(已标记)

Screenshot - Capture.jpg

发生异常时...

我们使用 try...catch 语句,如果发生异常,我们使用 WriteError 方法将错误信息写入主机。

格式

现在从控制台使用此 cmdlet,我们将看到奇怪的输出,其中包括对象类型和一些值。我们必须指定我们想要的默认输出视图。我们在 format.ps1xml 文件中这样做。请注意,我们使用了 MaxBandwidthMB 属性,这是一个扩展属性。

这是没有格式化文件的输出

Screenshot - Capture1.jpg

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。

© . All rights reserved.