WMI调用发生 InitializationFailure 错误的解决过程

调用 WMI 接口是获取系统信息的常用手段。本人在一个项目中需要获取本机的网卡信息,自然而然地就采用 WMI 调用的方式,代码也非常简洁。程序部署在绝大多数的客户机器上都运行得非常顺利,但在其中一台机器上却由于调用WMI而抛出 ManagementException,ErrorCode 为 InitializationFailure ,中文提示为“初始化失败”。由于是初次使用 WMI ,解决问题着实花了一番功夫,故在此记录问题的解决过程,为遇到类似问题的时提供参考。

先看通过WMI获取网卡信息的C#代码:

获取网卡MAC和IP地址
1 try
2 {
3 List<NetworkAdapterConfiguration> nacfgList = new List<NetworkAdapterConfiguration>();
4 ManagementClass mc = new
5 ManagementClass("Win32_NetworkAdapterConfiguration");
6 ManagementObjectCollection moc2 = mc.GetInstances();
7 NetworkAdapterConfiguration nacfg;
8 foreach (ManagementObject mo in moc2)
9 {
10 if ((bool)mo["IPEnabled"] == true)
11 {
12 nacfg = new NetworkAdapterConfiguration();
13 nacfg._macAddress = mo["MacAddress"].ToString();
14 nacfg._ipAddress = (string[])mo["IPAddress"];
15 nacfgList.Add(nacfg);
16
17 mo.Dispose();
18 }
19 }
20 return nacfgList.ToArray();
21 }
22 catch (ManagementException ex)
23 {
24 Logger.Error("=========Get NetwordAdapterConfiguration=========");
25 Logger.Error(ex);
26 Logger.Error("=== Data:{0}", ex.Data == null ? "null" : ex.Data.ToString());
27
28 Logger.Error("=== ErrorCode:{0}", ex.ErrorCode);
29 Logger.Error("=== ErrorInformation:{0}", ex.ErrorInformation);
30 Logger.Error("=== HelpLink:{0}", ex.HelpLink);
31 throw;
32 }

错误是在第 6 行 ManagementObjectCollection moc2 = mc.GetInstances(); 抛出 ManagementException,ErrorCode 为 InitializationFailure 。

经查MSDN,InitializationFailure 是.NET命名空间 System.Management 中的 ManagementStatus 枚举值之一,对该值的说明是:组件(如提供程序)由于内部原因未能初始化。

但如何解决问题呢?在MSDN中没有找到答案,只好寻求百度帮忙。

一番查找之后,终于了解了 WMI 的体系结构,以下是转载的WMI体系结构说明:

 

Windows管理规范WMI的四层结构(由低到高)

  • 托管系统(管理系统)是数据来源,通常是操作系统、服务、应用程序、设备驱动、网络、打印机等。
  • 提供程序作为托管系统与上层的公共信息模型对象管理器CIMOM间的中间层,为上层提取下层的相关信息、触发事件,为下层生成事件通知,并将管理信息和接口映射到CIM库的类上。
  • 公共信息模型对象管理器CIMOM是公共信息模型CIM储存库的管理接口。CIM储存库是一个面向对象的数据库,这些对象间可以建立关联,开发人员也可以在现有环境中添加新的类来表示新的托管对象。两者统一由WinMGMT表示,通过一组COM接口进行访问。而这个CIMOM又相当于上层使用者的代理。
  • 使用者就是系统管理应用程序(如 Microsoft Systems Management Server)或者第三方的应用程序或者脚本,它就是最终要向用户显示托管系统相关信息的程序。

如图

WMI的体系结构

 

根据一些资料的提示,InitializationFailure 有可能是 CIM 储存库已损坏导致的,于是朝着这个方向进行尝试,进行 CIM 储存库的重建。

重建过程操作如下:

  1. 停止 WMI 服务
    WMI在系统中表现为一个系统服务 winmgmt(显示名称:Windows Management Instrumentation),要进行 WMI 调用必须启动该服务。
    注:系统中的杀毒软件、防火墙或者其它的服务有可能会依赖于该服务,停止winmgmt服务时,必须先停止这些依赖服务。
  2. 移除原来的存储库
    可以在控制台输入以下命令,通过重命名 Repository 目录的方式移除原来的储存库。
        cd /d %windir%\system32\wbem
        rename Repository Rep_bak
  3. 执行 Mofcmp 命令,重新编译 wbem 目录下的 mof 和 mfl 文件
    Mofcomp.exe 是一个操作系统工具,用于编译 MOF 文件,并将文件中包含的信息添加到 WMI 的存储库中。
    在控制台输入以下命令:
        cd /d %windir%\system32\wbem
        for %i in (*.mof,*.mfl) do Mofcomp %i
    命令执行成功后,存储库即完成重建。

执行完重建操作后,重新运行程序,WMI 调用恢复正常,至此,问题成功解决!

 

参考资料:

  1、WMI问题全解(Windows管理规范)<转>

 

 

posted @ 2011-01-14 14:19  haiq  阅读(6171)  评论(0编辑  收藏  举报