实用工具特别推荐适用于 Windows PowerShell 的 SMS Cmdlet

Don Brown

下载这篇文章的代码: Utility2007_11.exe (1211KB)

过去,无法从命令行对 Microsoft System Management Server (SMS) 2003 客户端进行管理。幸运的是,最近出现了许多可帮助管理员管理复杂性、更改和配置的优良技术,其中的 Windows PowerShell 可以帮助解决此问题。

为了利用这项技术,我编写了一个小“实用程序”— SMS2003PowerShellSnapinSample(您可以在本专栏附带的代码下载中找到它,可从 technetmagazine.com/code07.aspx 上在线获得代码下载)。该实用程序实际是组合成一个 Windows PowerShellTM 管理单元的六个 cmdlet 的集合。使用这些 cmdlet,您可以从 Windows PowerShell 为本地计算机或远程计算机组配置 SMS 客户端本地策略。

对 SMS 客户端本地策略研究的越多,发挥的作用越大。额外的好处是,我还逐渐了解到有关 SMS 如何工作的更多内容。我了解到,通过谨慎应用 SMS 客户端本地策略,可以用全新方式控制 SMS 客户端:报告到相同站点的计算机无需都具有相同的配置。各种想法开始在脑海中出现 — 从设置特定计算机以便不需要权限来远程控制计算机,到更改客户端检查新策略的频率,再到在一天中的不同时间禁用特定的组件 — 您会发现使用 SMS 客户端本地策略没什么限制。让我们进一步了解一下。

关于 SMS 高级客户端本地策略

编程资源

所有功能 SMS 2003 高级客户端都有一个配置策略,它本质上是驱动其各种组件的设置列表。所有客户端、清单收集和软件分发设置(还有其他设置)都包含在这些配置策略中。策略本身是在站点服务器上创建的,并通过 SMS 管理点传到高级客户端。

SMS 策略的实际主体类似于托管对象格式 (MOF) 文件,因为它包含将要编译到高级客户端上的 \\.\root\CCM WMI(Windows® 管理规范)命名空间的一组实例。然后,各种其他代理将读取位于 \\.\root\ccm\policy\machine\requestedconfig 命名空间中的这些设置。但是,当通过 MOF 应用本地策略时,您仅可以在一台计算机上编译 MOF 并且它必须本地运行(确切地说,是当您直接登录计算机时)。但是由于其分布式特征,WMI 既可以本地访问又可以远程访问,因而产生了更多可以协助 SMS 管理员的方式。这意味着只要授予适当的管理权限,您就可以像连接到本地计算机上的 WMI 一样轻松连接到远程计算机上的 WMI。

SMS 客户端策略由各种客户端组件的配置设置组成,但是它还可能包括执行软件数据包内容的说明。像 Active Directory® 组策略一样,从 SMS 管理点获得的 SMS 2003 高级客户端策略可能会被 SMS 客户端本地策略覆盖。您不能覆盖策略的所有部分,但是可以覆盖某些确实值得注意的属性。这就赋予了 SMS 管理员对 SMS 客户端配置和操作进行更大程度的控制,因为它允许 SMS 站点上所应用的标准配置出现异常。

以一个安全稳固的环境为例,在此环境中,SMS 管理员将服务器和工作站作为单一 SMS 主站点的客户端来管理。在此虚构的环境中,安全策略可能声明,在技术支持专家可以对其计算机进行远程控制之前,必须提示用户输入权限。但如果技术支持专家希望使用远程控制来连接到服务器,那将明显成问题了:因为在通常情况下,没有用户登录到服务器,也不会有任何人授予远程控制权限。虽然应用本地策略时非常谨慎,但仍可能会在特定客户端覆盖用户权限的要求。您可能还可以想到许多其他情况,其中,SMS 本地策略可能在许可特殊的 SMS 客户端代理配置异常方面很有用。

Windows PowerShell 管理单元内幕

您对 Windows PowerShell 的基本知识有一些了解后,就可以添加到本专栏提供的示例源代码,以扩展您可以从命令行对 SMS 客户端本地策略执行的操作。在将类展现给 Windows PowerShell 之前,应该将一些特定的属性应用到该类。您需要确定该 cmdlet 的使用目的和应该执行什么操作。这就是所谓的“动词-名词”配对。在 Windows PowerShell 中,您会看到的一些常见动词有 Add、Get 和 Set。名词部分描述了您要对其执行操作的对象。Cmdlet 通常有一些在 Cmdlet 类中声明为各种类型公共属性的参数。最后,您需要使用 ProcessRecord 函数完成大部分工作。图 1 显示了您可用于自己的 cmdlet 的通用模板。

Figure 1 Cmdlet 模板

[Cmdlet( "Verb", "Noun", SupportsShouldProcess = true )]
public class Verb_Noun : PSCmdlet
{
    [Parameter( ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, 
        HelpMessage = "Parameter" )]
    [ValidateNotNullOrEmpty]
    [Alias( "param" )]
    public string Parameter
    {
        get { return MyParameter; }
        set { MyParameter = value; }
    }
    private string MyParameter;

    protected override void ProcessRecord( )
    {
        //Do your stuff here!
    }
}

编译完您的管理单元以后,您可以在定义了 RunInstaller 属性集和一些特定属性的项目中添加一个类别,向 Windows PowerShell 注册该管理单元。请参见本文附带的源代码以获得详细信息。要注册管理单元,您需要使用 Microsoft® .NET Framework 附带的 InstallUtil.exe 工具。图 2 显示了注册管理单元所要使用的语法。请注意,在 Windows Vista® 中,这是一项需要提升权限的操作,因此,您可能希望使用“以管理员身份打开”选项或使用 Windows Vista 的脚本提升 PowerToy(可从 technetmagazine.com/issues/2007/06/UtilitySpotlight 下载)来打开 Windows PowerShell。

Figure 2 安装 Windows PowerShell 管理单元

PS> set-alias installutil $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil 
PS> installutil C:\MySMSTools\SMS2003PowerShellSnapinSample.dll 
Microsoft (R) .NET Framework Installation utility Version 2.0.50727.42 
Copyright (C) Microsoft Corporation. All rights reserved. 
Running a transacted installation. 
... 
The transacted install has completed.

下一步是查看管理单元是否已经过 Windows PowerShell 确认。使用带有 Registered 参数的 Get-PSsnapin cmdlet,Windows PowerShell 会汇总列出当前加载的管理单元,后面附有将添加的已注册管理单元的列表。您的管理单元应可以在以下列表中找到:

PS> Get-PSsnapin -registered

现在可以使用 Add-PSsnapin cmdlet 将 Windows PowerShell 管理单元添加到外壳,如下所示:

PS> add-pssnapin SMS2003PowerShellSnapinSample

如果操作成功,您应能够在 Windows PowerShell 管理单元中执行 cmdlet。

要查看在任何 Windows PowerShell 管理单元中都可用的所有 cmdlet,只需使用 Get-Command cmdlet 指定特定的管理单元即可,这样就会将管理单元的名称作为 PSsnapin 参数的值传递。本专栏附带的示例管理单元显示了六个 cmdlet,包括 Verb-Noun Cmdlet 模板,如图 3 所示。

图 3 显示管理单元中的 cmdlet

图 3** 显示管理单元中的 cmdlet **(单击该图像获得较大视图)

在示例源代码中,我仅为 Get-SMSServerConnection cmdlet 编写了帮助来说明它是如何构建的。如果您希望扩展帮助,可以在 XML 文件中找到范例。图 4 显示了帮助输出。

Figure 4 Get-Help 输出示例

PS > get-help Get-SMSServerConnection

NAME
    Get-SMSServerConnection

SYNOPSIS
    This cmdlet establishes a connection to the specified SMS primary site server using your current credentials. An object of type "SMSProvider" is returned through the pipeline.

SYNTAX
    Get-SMSServerConnection [-SMSServerName] [<string>] [<CommonParameters>]

DETAILED DESCRIPTION
    This Cmdlet makes a connection to the specified SMS primary site server.  An object of type "SMSProvider" is returned. The "SMSProvider" object is not serializable and is used only to forward on through the pipeline to other cmdlets.

RELATED LINKS

现在,您已了解如何安装 Windows PowerShell 管理单元、如何查看管理单元中有哪些命令以及如何获得有关典型 cmdlet 的帮助,让我们开始使用这些 cmdlet 吧。要在 SMS 主站点服务器上显示所有集合的列表,可使用以下命令:

PS > Get-SMSServerConnection -server MYSMSSERVER | Get-Collections | Format-Table Name

请注意使用管道。这是 Windows PowerShell 工作原理的核心部分,是一种功能非常强大的工具。只需一行就有可能在 Windows PowerShell 中做任何事情。Get-SMSServerConnection cmdlet 建立了与 SMS 服务器的连接。由于 Get-Collections cmdlet 具有由 Get-SMSServerConnection 返回的类型的单一输入参数,因此,您可以直接将输出从 Get-SMSServerConnection cmdlet 传递到 Get-Collections cmdlet。这就是管道工作的原理,也是您如何在 cmdlet 之间传递复杂对象的极好示例。您还可以在变量中存储对象,如果您正在 Windows PowerShell 脚本中执行此操作,它可能会如下所示:

$SMS = Get-SMSServerConnection 
     -server MYSMSSERVER
Get-Collections -SMSServerProvider $SMS

如果不对输出进行一番精心的格式设置,输出阅读起来可能有些困难,这是因为 Get-Collections 返回 SMSCollection 类型的对象(它本质上是 SMSCollection 类型的对象的一个数组)。简言之,除非筛选出您没有兴趣查看的集合,或者对只包含您所关心的属性的表的显示进行格式设置,否则,显示不会很好看。您可以通过使输出经过管道从 Get-Collections cmdlet 传递到 Format-Table cmdlet 实现此操作,这样可以仅显示您指定的那些属性。例如,您可以附加 | Format-Table Name, Members。

但是,有一种更好的显示特定集合的所有成员的方法,在本示例中为 Get-CollectionMembers。该 cmdlet 返回一个字符串数组,代表集合每个成员的名称。正如您可能已经猜到的,这是将管道传递给下一个 cmdlet 的良好选择。

到现在为止,还没有涉及到 SMS 高级客户端本地策略 — 只是连接到 SMS 主站点服务器以及列举集合和集合成员。该示例 Windows PowerShell 管理单元中包含的最后两个 cmdlet,分别为 Enable-SoftwareDistribution 和 Disable-SoftwareDistribution。SMS 客户端本地策略会在这里派上用场。最后的这两个 cmdlet 为 SMS 高级客户端上的软件分发客户端代理组件操作 SMS 客户端本地策略。正如您可能已经通过 cmdlet 的动词部分猜到的,Disable 将添加一个指定软件分发客户端代理应被禁用的客户端本地策略覆盖。同样,动词 Enable 将删除所有客户端本地策略覆盖,使软件分发客户端代理返回其正常状态,这是由 SMS 管理点交付的 SMS 策略定义的。图 5 显示了一个 Windows PowerShell 单行指令示例,该示例将 SMS 客户端本地策略覆盖添加到软件分发客户端代理上,从而强制 Windows Server 2003 系统自定义集合的所有成员都禁用它。此外,还列出了用于删除同一集合上软件分发客户端代理的所有 SMS 客户端本地策略覆盖的单行指令。如果您只希望在几台计算机上操作 SMS 客户端本地策略,也可以单独使用 Disable-SoftwareDistribution 和 Enable-SoftwareDistribution cmdlet。

Figure 5 组建 cmdlet — 示例

PS >Get-SMSServerConnection -server MYSMSSERVER | Get-Collections | where-object {$_.Name -eq "Windows Server 2003 Systems"} | Get-CollectionMembers | Disable-SoftwareDistribution 
PS >
PS > Get-SMSServerConnection -server MYSMSSERVER | Get-Collections | where-object {$_.Name -eq "Windows Server 2003 Systems"} | Get-CollectionMembers | Enable-SoftwareDistribution
PS >
PS >Disable-SoftwareDistribution –hosts SMSCLIENT1, SMSCLIENT2, SMSCLIENT3
PS >
PS >Enable-SoftwareDistribution –hosts SMSCLIENT1, SMSCLIENT2, SMSCLIENT3

后续步骤

本文附带的示例源代码可以为您学习将 SMS 客户端本地策略覆盖应用到计算机组提供了很好的起点。此处的示例仅涉及 SMS 软件分发客户端代理,而且只涉及 Enabled 属性。其他客户端代理有更多属性,您可以用同样的方式应用覆盖。现在您已有了初步的了解,按逻辑下一步是查看 SMS 客户端本地策略的其他部分。您可以考虑一下,哪些托管系统组可以成为 SMS 客户端本地策略覆盖的候选者,以及使用哪些本地策略覆盖对您而言比较有意义。最后需要注意的一点是:最好事先了解您可能会遇到的情况,因此要在实验室环境中全面测试一切内容。

Don Brown是 Microsoft 的一位高级现场解决方案工程师,从很久以前他就一直在研究和支持 SMS(啊嗨,就是 SCCM)。请通过 donbrown@microsoft.com 与他联系。

© 2008 Microsoft Corporation 与 CMP Media, LLC.保留所有权利;不得对全文或部分内容进行复制.