WMI问题全解(Windows管理规范)<转>
问题 3:如果 WMI 向外界暴露特定的功能,我如何才能知道?
问题 4:如果 WMI 没有提供我想要的功能,我应该怎么办?
问题 6: 为什么我的脚本可以在某个版本的 Windows 上运行,但在另外一个版本的 Windows 上却不能运行?
问题 1:WMI 是什么,它能帮我做什么?
Windows 管理规范(Windows Management Instrumentation)是一项核心的 Windows 管理技术;用户可以使用 WMI 管理本地和远程计算机。WMI 通过编程和脚本语言为日常管理提供了一条连续一致的途径。例如,用户可以:
• 在远程计算机器上启动一个进程。
• 设定一个在特定日期和时间运行的进程。
• 远程启动计算机。
• 获得本地或远程计算机的已安装程序列表。
• 查询本地或远程计算机的 Windows 事件日志。
WMI 中的“Instrumentation”特指 WMI 可以获得关于计算机内部状态的信息,这与汽车仪表盘获得并显示引擎的状态信息非常类似。WMI 对磁盘、进程、和其他 Windows 系统对象进行建模,从而实现“指示”功能。这些计算机系统对象采用类来建立模型,例如 Win32_LogicalDisk 或 Win32_Process; 如您所料,Win32_LogicalDisk 类用于建立在计算机上安装的逻辑磁盘的模型,Win32_Process 类用于建立正在计算机上运行的任何进程的模型。这些类基于一个名为通用信息模型(Common Information Model,CIM)的可扩展架构。CIM 架构是分布式管理任务组(Distributed Management Task Force)的一个公开标准( http://www.dmtf.org).
WMI 的功能还包括事件触发、远程调用、查询、查看、架构的用户扩展、指示等等。
问题 2: WMI 适用于那些平台?
WMI 适用于所有最新版本的 Windows。WMI 附带在 Windows Me、Windows 2000、Windows XP 和 Windows Server 2003 之中。
对于 Windows 98 和 Windows NT 4.0,可以访问http://www.microsoft.com/downloads. 并搜索“Windows Management Instrumentation (WMI) CORE 1.5 (Windows 95/98/NT 4.0)”。
注意:在 Windows NT 4.0 上安装并运行 WMI 之前,需要首先安装 Service Pack 4 或更高版本。
WMI 需要的其他软件包括:
1. Microsoft? Internet Explorer 5.0 或更高版本。
2. Windows Script Host(WSH)。Windows 2000、Windows XP、Windows Server 2003、和 Windows Me 附带的 WSH,而不是 Windows NT4 或 Windows 98 附带的 WSH。您可以从以下地址下载 WSH http://www.microsoft.com/downloads. WSH 的最新版本—— 包括在 Windows XP 和 Windows Server 2003 之中——是 WSH 5.6。
问题 3:如果 WMI 向外界暴露特定的功能,我如何才能知道?
MSDN 是了解 WMI 及其功能的详细参考信息的最佳场所;请参考以下地址获取 WMI 参考信息:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_reference.asp. WMI 参考中包含了关于 WMI 标准安装中大多数类、对象和 API 的信息。注意:不属于操作系统一部分的 WMI 提供者可能会创建既没有记录在 MSDN,也没有记录在平台 SDK 中的类。
一旦熟悉了信息的分类方式,用户就可以方便地搜索自己想要的类,并确定自己想要的功能是否存在。 请注意:为了完成一个特定的任务,您可能需要使用多个类。例如,假定您想要获得一台计算机的基本系统信息。 尽管可以使用 Win32_OperatingSystem 类来获得可用内存的相关信息,但如果同时需要获得关于计算机可用磁盘的信息,您必须使用第二个类 Win32_LogicalDisk。请看问题为什么我的脚本可以在某个版本的 Windows 上运行,但在另外一个版本的 Windows 上却不能运行? 想要知道 WMI 可以做什么、不可以做什么?
CIM Studio 是一种工具,用户可以通过它浏览 Windows 2000 或更高版本平台上的 WMI 类。想要进一步了解这个工具,以及其中包含的内容(CIM Studio 中包含一系列由 WMITools.exe 安装的工具),请访问 http://www.microsoft.com 并搜索关键字“WMI tools”。您也可以运行微软不提供支持的 Wbemtest.exe 工具——安装 WMI 的时候自动被安装——来浏览 WMI 数据。
在 Windows XP 或 Windows Server 2003 上,用户可以使用以下脚本搜索类名中包含特定关键字的类。 请将该脚本保存为一个名为 Search.vbs 的文本文件然后运行,并指定想要搜索的关键字。例如,想要搜索名称中包含 “service”的类,
请在命令提示行运行以下命令:
cscript search.vbs service |
' Script for finding a class in WMI Repository |
该脚本只能运行在 Windows XP 或 Server 2003 之上,因为作为 WMI 查询语言一部分的 LIKE 运算符只能用于这两个平台。
问题 4:如果 WMI 没有提供我想要的功能,我应该怎么办?
用户迟早会发现 WMI 无法完成有些自己想要的任务或者无法高效地完成。 在这种情况下,您应该首先检查操作系统提供的其他脚本技术是否可以提供该功能。 例如,ADSI(Active Directory Service Interfaces)可以帮助用户管理 Active Directory;CDO(Collaboration Data Objects)提供了在脚本中发送电子邮件的功能。如果 Windows 操作系统没有提供合适的脚本接口,也许某些第三方的软件可以提供您所需要的功能。
如果确实没有这样的脚本接口,理论上讲您可以编写一个 WMI 提供者来提供相应的功能。不过,不能用脚本语言来编写 WMI;而必需使用 C++ 或 C#。关于这方面的更多信息,请参阅 MSDN 的“Using WMI”(使用 WMI)部分,其中一些主题介绍了如何编写典型的 WMI 提供者。如果您想要使用 .NET Framework 来编写提供者,请在 MSDN 库中搜索“Managing Applications Using WMI”(使用 WMI 管理应用程序)。
问题 5:在哪里可以找到使用 WMI 的示例脚本?
Microsoft Developers Network(MSDN)和 TechNet 都是获得示例的好地方。以下是一些指向这些站点上的有用资源的链接:
• TechNet 脚本中心
包含数百个按照技术和管理任务分类的示例脚本。
http://go.microsoft.com/fwlink/?LinkId=24771.??
• MSDN
http://msdn.microsoft.com/library.
想要获得 WMI 脚本,请搜索“WMI System Administration scripts”(WMI 系统管理脚本)。
想要获得 WMIC(WMI 命令行工具),请访问:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmic.asp?.
• WMI 软件开发工具包(SDK)
想要获得按照类别划分的问题解决方案,请参阅“Using WMI > WMI Tasks for Scripts and Applications(针对脚本和应用程序的 WMI 任务)”。http://www.microsoft.com/msdownload/platformsdk/sdkupdate?
• Windows 2000 脚本编写指南(在线阅读)
本书的全部内容,其中包含很多 WMI 脚本示例。
http://www.microsoft.com/resources/documentation/windows/2000/server/scriptguide/en-us/default.mspx?
• TechNet 的“脚本故事” 栏目
内容包括有关脚本的初级和中级话题。
http://www.microsoft.com/technet/community/columns/scripts/default.mspx?
• MSDN 的“脚本诊所”栏目
更多的高级脚本话题。
http://msdn.microsoft.com/library/default.asp?url=/nhp/Default.asp?contentid=28001169
• 新闻组
您可以在位于 Msnews.microsoft.com 新闻服务器上的以下新闻组中发布关于 WMI 和 WMI 应用或脚本的问题:
Microsoft.public.win32.programmer.wmi
Microsoft.public.windowsxp.wmi
Microsoft.public.windows.server.scripting
问题 6: 为什么我的脚本可以在某个版本的 Windows 上运行,但在另外一个版本的 Windows 上却不能运行?
这个问题通常是由于新版本的 Windows 中引入了一些新的类、属性、或方法,但较早版本的操作系统没有包含它们。想要验证可用性,请在 MSDN 中查找 WMI 软件开发工具包(SDK)中每个类的“Requirements”(要求)部分(http://msdn.microsoft.com/library/default.asp). 例如,Win32_PingStatus 类的“要求”中指定该类需要 Windows XP 或 Windows Server 2003。所以试图在 Windows 2000 上访问 Win32_PingStatus 类的脚本将会导致“Class not found”(无法找到类)错误。
与此类似,一些 WMI 数据提供者,例如 SNMP Provider 要么在所有操作系统上不可用,要么不是 WMI 默认安装的一部分。关于这些提供者的 SDK 主题都包含指向 “About WMI”(关于 WMI )部分的“Operating System Availability of WMI Components”(WMI 组件的操作系统要求)主题的引用。
想要获得标准 WMI 提供者的列表,请参考“WMI Reference”(WMI 参考)下的“WMI Providers”(WMI 提供者)。
一般情况下,当一个新的提供者被添加到 Windows 的一个新版本中,它的功能在先前版本的 Windows 中不会提供。例如,由 Ping 提供者定义的Win32_PingStatus 类不会在 Windows 2000 中提供。因为这些新的提供者通常利用了 Windows 新版本中的某些功能,但这些功能在较早版本中并不存在。
问题 7:为什么 WMI 操作返回一个错误?
在开始之前,请首先确认错误是否的确是一个 WMI 错误。WMI 错误编号从 8004xxxx 开始(例如 80041001)。您可以查找 WMI 错误编号并返回代码,方法是访问http://msdn.microsoft.com/library/default.asp 并搜索“WMI Return Codes”(WMI 返回代码)。如果找不到需要的信息,请尝试在 MSDN 中搜索特定的错误编号。
如果在运行脚本的过程中没有返回任何错误编号,您可以查看位于 %windir%\system32\wbem\logs 文件夹的 WMI 日志文件。如果很难判断刚刚运行的脚本返回的是什么错误,请删除所有日志然后重新运行一次。这样应该可以轻松找到与脚本相关的错误。
如果在日志文件中找不到错误,您也许需要重新设定日志的记录等级。要获得尽可能多的信息,请将记录等级设置为“详细”(verbose)。如果操作系统是 Windows 2000、Windows NT 和 Windows Me/98/95,修改记录等级之后需要重启 WMI;对于 Windows XP 和 Windows Server 2003 则无需这样。关于配置记录等级的详细信息,请访问http://msdn.microsoft.com/library/default.asp 并搜索“Logging WMI Activity”(记录 WMI 操作)。
错误也可能被记录在 Windows 事件日志中。查看来源为 Winmgmt的事件。
在 Windows XP 或 Windows Server 2003 上,您可以使用 MSFT_WMIProvider 类来诊断提供者操作,例如提供者的载入和卸载、对查询的响应、执行一个方法、等等。举个例子,在提供者取消对一个查询的响应之前,WMI 会生成 MSFT_WmiProvider_CancelQuery_Pre 类的一个实例。在取消发生之后会生成 MSFT_WmiProvider_CancelQuery_Post 类的一个实例。如果一段特定脚本中的查询操作失败了,您可以编写一段脚本来等待这些事件类的实例被生成。如果监视到脚本接收了一个事件,数据将会指出相关的 提供者、提供者的类型、正在被处理的查询、以及相关的命名空间。
更多信息,请访问http://msdn.microsoft.com/library/default.asp 并搜索“Troubleshooting Classes”。
以下是一段示例脚本,用于诊断 Ping 提供者的问题。这段脚本可以报告作为 Ping 操作组成部分的所有动作,例如提供者的载入、查询接收、错误生成。这些信息可以帮助用户诊断问题出在提供者中还是 WMI 服务中。请在输出中查找 ResultCode 不等于 0 的事件;一般来说,错误代码不等于 0 说明操作失败了。
请将以下代码保存到一个 .VBS 文件并运行脚本。
Option Explicit |
问题 8:WMI 不工作。如何解决这个问题?
运行脚本、诸如 CIM Studio 这样的基于 WMI 的工具或者运行 WMI 控件的时候,可能会遇到 WMI 服务错误。脚本可能不运行,或者可能收到一个“Access Denied”(拒绝访问)错误;导致这种错误的原因可能是 WMI 没有运行,或者命名空间没有被正确地配置。引起错误的原因还可能是 WMI 提供者提供的类没有被载入,或者 WMI 存储库(存储类定义的场所)已经损坏。
请遵循以下步骤来诊断 WMI 服务的 WMI 问题:
1. 如果连接远程计算机出现故障,请在本地计算机上运行脚本。
2. 重启 WMI 服务。
3. 重建 WMI 存储库。
4. 重新注册所有 WMI 组件。
5. 重新安装操作系统。
6. 联系 Microsoft 产品支持服务。
如果连接远程计算机出现故障,请在本地计算机上运行脚本。
如果连接远程计算机出现故障,在采取其它措施之前应该首先尝试在本地计算机上运行脚本。如果脚本可以在本地计算机上运行,请参考主题:如何使用 WMI 管理远程计算机? 如果脚本在本地计算机上也无法运行,请执行以下诊断步骤:
如果一个本地 WMI 操作返回预料之外的错误代码,或者无法启动 WMI Control,请首先确定本地 WMI 服务是否正在运行。请将以下代码保存到一个 .VBS 文件并在命令提示行运行该脚本:
Set Svc = GetObject ("winmgmts:root\default") |
如果脚本成功运行,表明 WMI 服务正常工作,它可能不是导致故障的原因。
如果脚本运行失败,请验证脚本中指定的命名空间是否是一个有效的命名空间。示例代码尝试连接 root\default 命名空间。如果该命名空间不存在,您将会得到一个错误 WBEM_E_INVALID_NAMESPACE (0x8004100E)。
如果命名空间存在,但试图连接的类不存在会怎样呢?在这种情况下,当试图访问该类时,可能会看到以下这些错误代码:
• WBEM_E_NOT_FOUND ( 0x80041002)
• WBEM_E_OUT_OF_MEMORY (0x80041006)
连接类失败还可能表明 WMI 存储库已经损坏。在这种情况下,您可能会看到以下错误代码中的一个:
• WBEM_E_INITIALIZATION_FAILURE????( 0x80041014 )
• WBEM_E_CRITICAL_ERROR ( 0x8004100a )
• WBEM_E_FAILED ( 0x80041001)
如果认为存储库已经损坏,最应该采取的动作就是重建存储库。
重启 WMI 服务。
通常 WMI 服务(winmgmt)总是运行的;任何时候当计算机启动的时候它也启动,并直到计算机关闭的时候才关闭。如果该服务意外地停止了,可以在命令行键入 net start winmgmt 重启。除此之外,每次使用基于 WMI 的工具(例如 Wbemtest)或脚本连接 WMI namespace 的时候,该服务也会自动重启。通常在 WMI 服务停止的情况下运行一段使用 WMI 的脚本也会使其自动重启。
如果遇到关于 WMI 服务的故障,您也许需要手工停止并重启该服务。请按照以下步骤操作:
1. 首先,启用 WMI 的“详细的日志记录”选项;这将在 WMI 错误日志中提供更加详细的信息,可能有助于故障的诊断。可以配置以下注册表值来启用“详细的日志记录”:
1. 设置 HKLM\Software\Microsoft\WBEM\CIMOM\Logging 为 2。
2. 设置 HKLM\Software\Microsoft\WBEM\CIMOM\Logging file Max Size 为 4000000。
2. 停止 WMI 服务。众所周知,WMI 服务名为“winmgmt”。可以通过执行以下命令来停止该服务:
winmgmt /kill
如果正在运行 Windows XP 或 Windows Server 2003,WMI 服务运行在一个名为 Svchost 的进程之内;该进程还包含运行在同一帐户下的其他服务。除此之外,您还可能看到计算机上运行着多个 Svchost 实例。不要尝试停止 Svchost 本身;相反,请使用以下两个命令来停止 WMI 服务:winmgmt /kill 或 net stop winmgmt
3. 如果步骤 2 成功,请跳过该步骤,直接进入步骤 4。如果步骤 2 没能成功停止 winmgmt 服务,请重启计算机然后进入步骤 4。
4. 再次运行脚本。如果脚本运行失败,您可能需要重建 WMI Repository。
重建存储库。
WMI Repository 是 WMI 提供者创建的类定义的集中存储位置,它位于 %systemDrive%\%windir%\system32\wbem\Repository 文件夹。如果感觉存储库已经损坏,您应该重建它。注意:这么做可能会导致存储库中的 WMI 信息丢失。您可能需要手工恢复这些信息,方法是运行可以将信息放入存储库的特定应用程序。要重建存储库,请按以下步骤操作:
1. 停止 WMI 服务。
2. 在命令行键入以下命令:
cd /d %windir%\system32\wbem
rename Repository Rep_bak
3. 这个命令将会重命名包含 WMI Repository 的文件。重命名文件之后,操作系统将无法找到存储库。在这种情况下,Windows 会在用户下次访问 WMI 的时候尝试重建存储库。如果 AutoRecover(自动恢复)机制失败,您可以尝试手工重建存储库。
通过 WMI AutoRecover 机制重建存储库:
• 建立一个到 Root\Default 的 WMI 连接;可以通过运行一段脚本或者类似 Wbemtest.exe 的基于 WMI 的工具做到这一点。如果连接成功,存储库就会被重建。如果连接失败,请尝试手工重建存储库。
手工重建 WMI 存储库:
• 想要手工重建存储库,应该首先编辑一个批处理文件,该文件将会向存储库补充信息。注册表键 HKLM\Software\Microsoft\WBEM\CIMOM\Autorecover MOFs 包含一个 WMI(或操作系统) 安装时的 Managed Object Format 文件(MOF 文件)列表。想要重建存储库,请将注册表值中列出的文件名复制到一个名为 WMI_Recover.bat 的批处理文件;确保包含了扩展名为 .MOF 和 .MFL 的文件。(MFL 文件中包含了类、属性和方法的本地化描述。)
在记事本中,这个批处理文件应该象下面这样:
C:\WINDOWS\system32\WBEM\cimwin32.mof C:\WINDOWS\system32\WBEM\cimwin32.mfl C:\WINDOWS\system32\WBEM\system.mof C:\WINDOWS\system32\WBEM\wmipcima.mof C:\WINDOWS\system32\WBEM\wmipcima.mfl |
• 在批处理文件的每行开头添加 Mofcomp 命令。Mofcomp.exe 是一个操作系统工具,用于编译 MOF 文件,并将文件中包含的信息添加到 WMI 存储库中。例如,您的批处理文件可能象下面这样:
Mofcomp C:\WINDOWS\system32\WBEM\cimwin32.mof Mofcomp C:\WINDOWS\system32\WBEM\cimwin32.mfl Mofcomp C:\WINDOWS\system32\WBEM\system.mof Mofcomp C:\WINDOWS\system32\WBEM\wmipcima.mof Mofcomp C:\WINDOWS\system32\WBEM\wmipcima.mfl |
• 运行这个批处理文件。
• 您也可以使用以下命令编译所有的 MOF 和 MFL 文件:
cd /d %windir%\system32\wbem
for %i in (*.mof,*.mfl) do Mofcomp %i
• 命令完成之后,请检查 .\Logs\Mofcomp.log,查看是否有编译错误发生。
4. 再次运行脚本。
重新注册 WMI 组件
如果到 root\default 的连接仍然失败,无法被正确注册的 WMI 组件可能是导致故障的原因。WMI 使用的 .DLL 和 .EXE 文件位于 %windir%\system32\wbem。您也许需要重新注册该目录内的所有 .DLL 和 .EXE 文件。如果运行在 64 位的系统之上,您可能还需要检查位于 %windir%\sysWOW64\wbem 的 .DLL 和 .EXE 文件。
1. 要重新注册 WMI 组件,请在命令提示行运行以下命令:
cd /d %windir%\system32\wbem
for %i in (*.dll) do RegSvr32 -s %i
for %i in (*.exe) do %i /RegServer
2. 再次运行脚本。
重新安装操作系统
如果仍然无法连接到 root\default,您需要重新安装操作系统。重新安装 Windows,然后尝试再次运行脚本。
联系 Microsoft 产品支持服务
如果 WMI 仍然无法正常工作,您需要联系 Microsoft 产品支持服务(PSS)。更多信息,请访问:http://support.microsoft.com/default.aspx.
问题 9:如何设置 WMI 命名空间的安全性?
使用 WMI 控件设置命名空间的安全性
WMI 控件提供了一种管理命名空间安全性的方法。可以在命令提示行运行以下命令来启动 WMI 控件:
wmimgmt
在安装了 WMI 的 Windows 9x 或 Windows NT4 计算机上,输入以下命令:
wbemcntl.exe
或者您也可以通过以下方式访问 WMI Control 和“安全性”选项卡:
1. 右键单击“我的电脑”,然后单击 管理。
2.双击 服务和应用程序 ,然后双击 WMI 控件。
3. 右键单击 WMI 控件 ,然后单击 属性。
4. 在 WMI 控件属性 对话框中单击 安全 选项卡。
5. 一个名为 Root ,前面带加号 (+) 的文件夹将会出现。如果必要,展开这个树状结构,定位到想要设置权限的命名空间。
6. 单击 安全设置 按钮。一组用户和权限显示出来。如果用户在这个列表中,请按照需要修改权限。如果用户不再这个列表中,请单击 添加 按钮,然后从账户所在的位置(本地计算机、域等等)添加用户。
注意:
• 为了查看和设置 namespace 安全性,用户必需拥有 读取安全设置 和 编辑安全设置 权限。系统管理员默认具备这些权限,并可以按照需要将权限赋予其他用户。
• 如果一个用户需要远程访问命名空间,必须为其选中 远程启用 权限。
• 默认情况下,针对一个命名空间设置的用户权限只对该命名空间有效。如果希望用户可以访问该命名空间和其下所有子命名空间,或者只能访问子命名空间,请单击 高级 按钮。单击 编辑 并在出现的对话框中指定允许访问的范围。
问题 10:如何使用 WMI 管理远程计算机?
使用 WMI 工具连接远程命名空间
1. 想使用类似 CIM Studio 或 Wbemtest 这样的工具进行远程连接,必需按照以下格式指定一个命名空间:“\\<machinename>\root\<namespace>”
例如:\\myserver\root\cimv2
2. 身份验证可以使用 Kerberos 或 NTLM 进行处理。如果使用 NTLM 或默认(非 Kerberos)验证,请指定如下内容:
User:<domain>\<User>
Password:<password>
Authority:保留空白,或者输入“NTLMDomain:<domain>”。如果想要包含 Authority 参数,请把“<domain>\”从 User 参数中去掉,只输入用户名即可。例如:
User:kenmyer
Password:45Tgfr98q
Authority:NTLMDomain:fabrikam
3. 要使用 Kerberos 认证,请按如下指定:
User:<domain>\<User>
Password:<password>
Authority:在这里输入“Kerberos:<domain>\<machinename>”。例如:
User:kenmyer
Password:45Tgfr98q
Authority:Kerberos:fabrikam\atl-ws-01
使用脚本连接到远程计算机上的 WMI
1. 开始之前,请确保对远程命名空间拥有相应的权限。 如果拥有权限,您可以在不指定用户身份信息的情况下连接到远程计算机。WMI 将使用您登陆时输入的用户身份进行连接。
2. 如果不指定用户身份信息,您可以使用被称作 别名字符串 的简短连接语法连接到远程计算机。更多信息,请访问:http://msdn.microsoft.com/library/default.asp 并搜索 “Constructing a Moniker String”(构造一个别名字符串)。例如,以下别名字符串将连接到一个名为 TargetComputer 的远程计算机的默认命名空间(因为没有指定命名空间,会自动连接到默认的命名空间):
•Set objWMIService = GetObject("winmgmts:\\TargetComputer”) |
• 如果 TargetComputer 位于另外一个域中,还必需在命名空间中包含域名。否则将会返回一个“拒绝访问”错误。例如,以下命名空间连接到位于 DomainName 域的 TargetComputer 计算机:
Set objWMIService = GetObject("winmgmts:\\DomainName\TargetComputer”) |
• 尽管不是必需的,您也可以在别名字符串中指定 WMI 命名空间。这对连接到不同平台是非常有帮助的,因为在不同版本的操作系统上默认的命名空间不完全相同。例如,在 Windows 2000、Windows XP 和 Windows Server 2003 上,默认的命名空间是 root\cimv2;但是,在 Windows NT 4.0 和 Windows 98 上,默认的命名空间是 root\default。
以下别名字符串连接到远程计算机 TargetComputer 的 root\cimv2 命名空间:
Set objWMIService = GetObject("winmgmts:\\TargetComputer\root\cimv2) |
• 如果需要处理多种平台,您可能还需要指定 Impersonation(模拟)级别; 尽管 Windows 2000 和更高版本的默认 Impersonation 级别为“Impersonate”,但之前版本的 Windows 的默认 Impersonation 级别为“Identify”。如果需要处理 Windows NT 4.0 和(或)Windows 98 计算机,需要在别名字符串中包含 Impersonation 级别;使用委派的时候也需要包含 Impersonation 级别。
以下别名连接到 TargetComputer 的 root\cimv2 命名空间,并且指定了“Impersonate”作为 Impersonation 级别:
Set objWMIService = GetObject _ ("winmgmts:{impersonationLevel=Impersonate}!\\TargetComputer\root\cimv2") |
• 最后,您可能还需要根据操作系统版本的不同来设置 Authentication(身份验证)级别。您可以通过指定 Authentication 级别来请求 DCOM 的身份验证类型和在整个连接过程中需要用到的隐私数据。它的设置的范围从“无身份验证”一直到“每数据保加密身份验证”(per-packet encrypted authentication)。
以下别名连接到名为 TargetComputer 的计算机的 root\cimv2 命名空间,同时指定了 Impersonation 级别为“Impersonate”。另外,它还将 Authentication 级别配置为 pkt:
Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate," _ & "authenticationLevel=pkt}!\\ _ TargetComputer\root\cimv2") |
3. 也可以在脚本中指定用户的身份验证信息;这样,即使您用一个标准用户账户登录到远程计算机,仍然可以运行需要管理员权限的脚本。更多信息,请访问:http://msdn.microsoft.com/library/default.asp 并搜索 “Creating a WMI Script”(创建 WMI 脚本)。
wbemImpersonationLevelImpersonate = 3 Set objLocator = CreateObject("WbemScripting.SWbemLocator") |
注意。一般来说,在脚本代码中写入管理员密码是不明智的。更好的办法是在每次运行的时候询问密码。
使用 WMIC 连接 WMI
如果对远程命名空间拥有权限并且远程计算机支持远程操作,则连接的时候可以不指定用户名和密码,WMIC 会自动使用当前的用户身份信息。例如:
WMIC /NODE:"computer1" OS GET Caption,CSDVersion,CSName |
如果需要使用委派,应该在 WMIC 连接字符串中包含 /IMPLEVEL:Delegate 和 /AUTHORITY 设置。例如:
WMIC /NODE:"computer1" /IMPLEVEL:Delegate /AUTHORITY:"Kerberos:domain\computer1" OS
另外,您也可以选择指定用户账户和密码(对于 WMI 脚本,默认只有管理员拥有 WMI 远程连接权限)。例如:
WMIC /NODE:"computer1" /USER:"domainname\username" OS GET Caption,CSDVersion
下面这个命令的例子包含了密码和用户名:
WMIC /NODE:"computer1" /USER:"domainname\username" /PASSWORD:"userpassword" OS GET Caption,CSDVersion,CSName
更多信息,请访问http://msdn.microsoft.com/library/default.asp 并搜索 “Connecting to WMI on a Remote Computer”(连接到远程计算机上的 WMI)。
“拒绝访问”(Access Denied)错误意味着什么?
试图连接到 WMI 命名空间或对象的时候可能会遇到“Access Denied”错误。Access Denied 错误有多种类型:
0x80041003 (WBEM_E_ACCESS_DENIED)
试图连接命名空间的进程如果没有必需的 WMI 权限通常是出现该错误的原因。试图进行远程访问的账户应该是目标计算机的管理员;另外,该账户的具体权限也需要被启用。
要解决该错误,请检查远程计算机上的命名空间的安全性,确定是否为该账户启用了相应的权限。
0x80070005 (DCOM ACCESS_DENIED)
如果远程计算机不能识别连接用户或者对其具有某种形式的限制(例如,该用户被锁定),就会导致该错误。 这种情况大多数是因为账户属于另外一个域。对 WMI 安全性的最新修改也可能导致该错误发生:
• 以前版本允许的空密码在 Windows XP 和 Windows Server 2003 中不被允许。
• WMI 不支持针对 Windows 98 客户端的异步回调。从 Windows 98 计算机到 Windows XP 计算机的 SWbemServices.ExecNotificationQueryAsync 调用将会向 Windows 98 计算机返回一个“拒绝访问”错误。
• DCOM 访问设置可能发生了改变。
• 如果目标计算机运行 Windows XP,注册表键 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa 下的 Forceguest 值可能被设置为强制禁止 Guest 账户(值为 0)。
0x800706xx (DCOM RPC 错误)
如果远程计算机配置了防火墙,通常会导致该错误。 您需要在防火墙上打开特定端口,允许通过 DCOM 进行远程管理。
或者,计算机可能在映射 IP 和主机名方面出现了问题。要测试这种可能性,请尝试在连接字符串中使用 IP 地址代替主机名:
Set objWMIService = GetObject("winmgmts:\\192.168.1.1") |
要排除远程错误
1. 请检查用户是否可以访问远程计算机。在命令提示行执行以下命令:
net user \\<remotecomputer>\\C$ /u:<domain\username> *
2. 在远程计算机上启用“详细的日志记录”,然后重新运行脚本。脚本运行之后, 检查远程计算机上的日志文件(%windir%\system32\wbem\Logs\)。
3. 启用审核事件来判断哪一个账户连接失败。启用之后,您将在事件日志中看到类似如下的事件:
Event Type: Failure Audit
Event Source: Security
Event Category: Logon/Logoff
Event ID: 529
Date: 6/14/2004
Time: 10:52:35 AM
User: NT AUTHORITY\SYSTEM
Computer: <remote machine>
Description:
Logon Failure:
Reason: Unknown user name or bad password
User Name: xuser
Domain: NTDEV
Logon Type: 3
Logon Process: NtLmSsp
Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0
Workstation Name: <console Machine >
4. Check the DCOM configuration for the Access\Launch permission; the user running the script must have this permission.
5. 如果所有这些检查都正常,如果用户可以被远程计算机识别,但仍然会发生“DCOM 拒绝访问”错误,请联系产品支持服务(http://support.microsoft.com/default.aspx)并提供以下信息:
• 每台计算机运行的操作系统。
• 安装历史
• 导致错误发生的步骤
• 发生错误的脚本或工具
• 进行 WMI 连接的用户身份信息,包括“身份验证”和“模拟”的级别。
• 两台计算机的 %windir%\system32\wbem\logs 目录的 zip 文件
问题 11:远程操作涉及到第三台计算机的时候为何失败?
如果客户端计算机(计算机 A)需要通过远程服务器(计算机 B)将域身份验证信息转发给第三台计算机(计算机 C)时,就需要用到委派。类似这样的情况,也就是说一个特定操作需要涉及两次或更多网络通讯时,需要使用委派。如果不通过委派,计算机 B 就无法转发来自计算机 A 的身份验证信息;从而导致到计算机 C 的连接失败。
以下两种情况需要使用委派。
• 通过 WMI 服务器列举所有打印机。在这种情况下,WMI 试图搜集连接到打印机服务器的远程打印机的属性,该操作需要用到委派。您可以在计算机 A 上运行一段脚本,它连接到打印服务器 B。接着,打印服务器 B 再试图访问连接到计算机 C 的打印机。
• 从 WMI 服务器通过 NT 验证连接到 SQL Server。只有借助委派,WMI 才能将服务器上的身份验证信息转发到 SQL Server。如果 SQL Server 采用 SQL Server 标准身份验证(基于 SQL Server 的安全性),而不是 NT 验证,则连接 SQL server 的连接字符串不需要委派。
委派支持的情境如下:
• 三台计算机必须全部运行 Windows 2000、Windows XP 或 Windows Server 2003。委派不能被用于 Windows NT 4.0 或 Windows 98。
• 必须在 Active Directory 中为计算机 B 启用委派。
• 必须在 WMI 客户端进程(计算机 A)到 WMI 服务器(计算机 B)的连接中指定身份验证机构(authentication authority) 为 Kerberos。想要指定身份验证机构,请调用 SWbemLocator.ConnectServer。该方法是 WMI Scripting API 的一部分 (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/swbemlocator_connectserver.asp).
完成这些步骤之后,计算机 B 可以受到信任进行委派了。例如,假设计算机 B 向位于计算机 C 的远程文件共享发送一个请求。在这种情况下,计算机 C 可以使用转发来的身份验证信息来验证最初在计算机 A 上执行客户进程的用户。
尽管委派是一种可用的管理选项,但通常不建议使用,因为如果计算机 A 把身份验证信息提供给计算机 B,计算机 B 就可以在任何地方使用这些身份验证信息,从而可能带来安全隐患。
以下脚本可以在 Active Directory 中为一个计算机账户启用委派。已经在 Windows Server 2003 域中使用管理员账户对该脚本进行了测试。另外:
• WMI 客户端计算机(计算机 A )运行 Windows XP SP1 Professional。
• WMI 服务器(计算机 B)运行 Windows Server 2003。
• 三台计算机位于同一个 Active Directory 域中。委派要求所有计算机位于同一个域中。
• 在这个例子中,文件服务器共享(计算机 C)与 WMI 客户端位于同一台物理计算机上。当然,共享也可以位于相同域中的另外一台计算机上。
'Purpose: Script to enable delegation on a computer and 'Requirements: The client computer must be a member of the same Active Directory 'Permissions required: The user that runs this script should be a member of Set objEnum = svc.ExecQuery _ Set svc = GetObject("Winmgmts:root\directory\ldap") Set octx = CreateObject("wbemscripting.swbemnamedvalueset") modified = False userAccountControlOriginal = obj.ds_userAccountControl |
如果其中的一台计算机运行 Windows NT 4.0 或 Windows 98,则以上脚本不可用。如果目标位于 Windows NT 4.0 文件共享上,脚本也会执行失败。
可以按照以下步骤手工设置委派:
1. 单击 开始 按钮,然后单击 所有程序。
2. 指向 管理工具 然后单击 Active Directory 用户和计算机。
3. 在“Active Directory 用户和计算机”中展开 计算机 节点,找到想要设置委派的计算机
4. 右键单击该计算机并单击 属性。
5. 选择 信任此计算机进行委派 ,然后单击 确定。
问题 12:为什么我的查询需要很长时间才能完成?
这通常是因为查询会返回大量的数据。如果查询请求一个非常庞大的数据集,但您只对其中一个子集感兴趣,通常可以对返回信息进行限制以提高操作速度。WQL(WMI 查询语言)可以帮助用户过滤返回的实例(记录)或者属性(字段)集合。想要查看范例,请访问http://msdn.microsoft.com/library 并搜索“Querying with WQL”(利用 WQL 进行查询),另外请参考主题“SELECT Statement for Data Queries”(用于数据查询的 SELECT 语句)。
在一些情况下,provider 已经基于特定的属性在过滤方面进行了优化。在 WHERE 字句中指定这些信息可以改善性能,因为 provider 能够动态地过滤结果集,不再依赖 WMI 在获得整个数据空间之后执行的‘后过滤’。CIM_DataFile 的 Drive 和 Path 属性都是优化属性的典型例子。
默认情况下,WMI 查询会返回一个枚举器,允许在两个方向上多次浏览集合;这意味着您可以遍历集合中的条目,如果愿意的话,还可以遍历第二次、第三次。当返回的数据集比较庞大时,此种类型的枚举器需要占用非常大的内存,从而影响性能。在发起此类查询的时候,您可以通过指定 WBEM_FLAG_FORWARD_ONLY 标记来避免这个问题。虽然只能使用此种类型的枚举器遍历一遍集合,但每个对象在使用之后都会从内存中释放,从而避免了性能的下降。更多信息,请参见 Making a Semisynchronous Call with VBScript(http://msdn.microsoft.com/library/en-us/wmisdk/wmi/making_a_semisynchronous_call_with_vbscript.asp).??
尽管半同步查询的性能在大多数情况下要优于异步查询,但如果查询非常庞大时,半同步查询可能会独占主应用线程,或者被 WMI 扼杀以避免系统过载。在这种情况下,应该使用异步查询来改善性能。但您应该记住,异步调用在大多数操作系统中安全性较差。 更多信息,请参见“调用异步查询”(http://msdn.microsoft.com/library/en-us/wmisdk/wmi/invoking_an_asynchronous_query.asp) 和“异步调用的安全性设置”(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/setting_security_on_an_asynchronous_call.asp).
问题 13:如何列出特定计算机上已经安装的所有应用?
Win32_Product WMI 类代表通过 Windows Installer 安装的所有应用程序。但是,这个 WMI 类可能不会列出所有出现在‘添加/删除程序’中的程序。 解决该问题的一种方法是从注册表中搜集已安装程序的信息(注意:并不是所有程序在安装的时候都会向注册表写入信息)。本主题给出了达到此目的的两种方法:使用脚本直接读取注册表中的信息,使用 MOF 文件和脚本从 WMI 中获取该信息。
1. 以下脚本用于列出计算机上已经安装的应用程序。使用 WMI System Registry Provider 直接从注册表中搜集信息的脚本:
strHost = "." Const HKLM = &H80000002 Set objReg = GetObject("winmgmts://" & strHost & _ "/root/default:StdRegProv") Const strBaseKey = _ "Software\Microsoft\Windows\CurrentVersion\Uninstall\" objReg.EnumKey HKLM, strBaseKey, arrSubKeys For Each strSubKey In arrSubKeys intRet = objReg.GetStringValue(HKLM, strBaseKey & strSubKey, _ "DisplayName", strValue) If intRet <> 0 Then intRet = objReg.GetStringValue(HKLM, strBaseKey & strSubKey, _ "QuietDisplayName", strValue) End If If (strValue <> "") and (intRet = 0) Then WScript.Echo strValue End If Next |
2. 以下 MOF 文件和它的配套脚本展示了另外一种从注册表中获取已安装应用的方法。如果使用 MOF 文件,请按以下步骤操作:
步骤 1:复制以下 MOF 语法到记事本并保存为一个 .MOF 文件(例如 products.mof)。
qualifier dynamic:ToInstance; qualifier ProviderClsid:ToInstance; qualifier ClassContext:ToInstance; qualifier propertycontext:ToInstance; [dynamic, provider("RegProv"), ProviderClsid("{fe9af5c0-d3b6-11ce-a5b6-00aa00680c3f}"), ClassContext ("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall") ] class Products { [key] string KeyName; [read, propertycontext("DisplayName")] string DisplayName; [read, propertycontext("DisplayVersion")] string DisplayVersion; [read, propertycontext("InstallLocation")] string InstallLocation; }; |
步骤 2:在命令提示行键入 mofcomp products.mof.该命令将 MOF 文件存入 WMI 存储库。
步骤 3:MOF 存入存储库之后,使用以下脚本获取数据。
strComputer = "." Set WMI = GetObject("winmgmts:\\" & strComputer & _ "\root\default") Set colItems = WMI.ExecQuery("Select * from Products") For Each objItem In colItems WScript.Echo "DisplayName: " & objItem.DisplayName WScript.Echo "DisplayVersion: " & objItem.DisplayVersion WScript.Echo "InstallLocation: " & objItem.InstallLocation WScript.Echo "KeyName: " & objItem.KeyName Next |
问题 14:如何获得性能计数器数据?
对 Cooked Counter Provider——使用 WMI 获取性能数据的最快最方便的方法——的支持在 Windows XP 中首次引入。在 Windows 2000 上,您同样可以获取性能数据;不过,由于这些数据以“未经加工”的格式出现,您必需自己格式化这些数据以获得有用的计数器数值。与此形成对比,在 Windows XP 和 Windows Server 2003 上,可以通过 Win32_PerfFormattedData 类直接获取性能数据。更多信息,请参见“示例:获得经过加工的性能数据”:http://msdn.microsoft.com/library/en-us/wmisdk/wmi/example__obtaining_cookedperformance_data.asp.
因为 Windows 2000 没有提供 Cooked Counter Provider,所以必须在“未加工的”计数器数据上执行计算以获得有意义的性能信息。更多信息,请参见 “示例:获得原始性能数据”:http://msdn.microsoft.com/library/en-us/wmisdk/wmi/example__obtaining_raw_performance_data.asp.??
如果想查找针对每种计数器类型的正确公式,请首先使用 WMI SDK (“Performance Counter Classes”主题)或针对该属性的“类似”限定器确定属性的数值计数器类型。该计数器类型的公式可以在位于以下地址的 "WMI Performance Counter Types"(WMI 性能计数器类型) 一节中找到:http://msdn.microsoft.com/library/en-us/wmisdk/wmi/wmi_performance_counter_types.asp.
在 Windows 2000 版本之前的系统上,必须使用 Performance Monitoring Provider(性能监视提供者)来获得性能计数器。请参见“利用 Performance Monitoring Provider 监视性能”:http://msdn.microsoft.com/library/en-us/wmisdk/wmi/monitoring_performance_with_the_performance_monitoring_provider.asp.