用C#和WMI获取逻辑驱动器详细信息
2010年08月18日
一、 简介
若仅简单获取逻辑驱动器的名称列表我们使用.Net框架的Environment.GetLogicalDrives即可,但是若想获得更多关于磁盘驱动器的信息我们可以使用.Net框架下的System.Management 命名空间所提供的类和委托等对大量管理信息和管理事件的集合进行访问,这些信息和事件都与 WMI有关,该命名空间下的类实际上也是对WMI的一种封装,应用程序和服务可以使用从 ManagementObjectSearcher 和 ManagementQuery 派生的类,查询感兴趣的管理信息,例如在磁盘上还剩多少可用空间、当前 CPU 利用率是多少、某一应用程序正连接到哪一数据库等等,现在我们就以 C# 语言编写获取详细的逻辑驱动器信息的示例来展示.Net框架System.Management 命名空间的相关类和WMI编程,如下图:
二、技术要点
WMI最初是内置在 Windows 2000、Windows XP 和 Windows Server 2003 系列操作系统中核心的管理支持技术,目前WMI 已经是一种规范和基础结构,通过它可以访问、配置、管理和监视几乎所有的 Windows 资源例如磁盘、事件日志、文件、文件夹、文件系统、网络组件、操作系统设置、性能数据、打印机、进程、注册表设置、安全性、服务、共享、用户、组等等。在 WMI 之前,能够以编程方式访问 Windows 资源的惟一方法就是通过 Win32 API,现在我们除了使用WMI 脚本管理任何通过 WMI 公开的 Windows 资源外,还可以通过.Net框架对于WMI封装的System.Management 命名空间来轻松实现。
我们首先使用WMI查询来获取特定类名的SelectQuery实例,可以有两种方法创建该实例,一是可以传递一个已知的类名,譬如本文需要传递的类名为:Win32_LogicalDisk,代码如下:
或者使用wql查询来创建查询类的实例,代码如下:
或者只获取类的部分属性,代码如下:
WQL查询语言是 SQL 的一个子集,查询通过包含以下内容限制返回的数据量1、SELECT 子句,指定只返回某些属性的数据;2、WHERE 子句,指定要返回的实例。Win32_LogicalDisk类在默认的本地MSDN里是无法找到的,只有在联机的MSDN里,Win32 and COM Development下的WMI下才能找到,同样可以使用的类还有很多很多,包含登录用户信息的Win32_Account类、包含本地和共享打印机信息的Win32_PrinterShare类等等。Win32_LogicalDisk里所包含的驱动器属性相当丰富. 然后使用该指定的SelectQuery查询创建ManagementObjectSearcher实例,此类是用于检索管理信息的较为常用的入口点之一,实例创建结束,我们需要调用Get方法执行查询以便检索管理对象的集合,当调用该方法时,ManagementObjectSearcher 在指定的范围内执行给定的查询,并返回与 ManagementObjectCollection 中的查询匹配的管理对象的集合,这是就可以在一个循环中遍历集合中的所有对象,并获取我们所感兴趣的对象的属性,代码如下: …… SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery); int i=0; foreach (ManagementObject disk in searcher.Get()) { //获取驱动器盘符 listView1.Items.Add(disk["Name"].ToString()); } ……
三、 程序实现
我们使用Visual Studio 2005来创建该示例程序,首先创建C#的Windows应用程序空白项目,为解决方案和项目取名为 GetLogicDrives,在默认的Form1窗体上我们各放置一个ListView和一个Button控件,保留控件的默认名称不变,将ListView1的View属性设为Details,双击ListView1的Columns属性,为详细信息视图添加5个列,分别为:盘符、卷标、类型、容量和可用空间,设置Button1的Text属性为Refresh,为该Button1添加单击事件,代码如下: private void button1_Click(object sender, EventArgs e) { listView1.Items.Clear(); SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery); int i=0; foreach (ManagementObject disk in searcher.Get()) { //盘符 listView1.Items.Add(disk["Name"].ToString()); //卷标 try { listView1.Items[i].SubItems.Add(disk["VolumeName"] .ToString()); } catch { listView1.Items[i].SubItems.Add("设备未准备好"); } //驱动器类型 string DriveType; try { DriveType = disk["DriveType"].ToString(); switch (DriveType) { case "0": listView1.Items[i].SubItems.Add("未知设备"); break; case "1": listView1.Items[i].SubItems.Add("未分区"); break; case "2": listView1.Items[i].SubItems.Add("可移动磁盘"); break; case "3": listView1.Items[i].SubItems.Add("硬盘"); break; case "4": listView1.Items[i].SubItems.Add("网络驱动器"); break; case "5": listView1.Items[i].SubItems.Add("光驱"); break; case "6": listView1.Items[i].SubItems.Add("内存磁盘"); break; } } catch { listView1.Items[i].SubItems.Add("未知类型"); } //容量 try { listView1.Items[i].SubItems.Add(GetSizeUseUnit(dis k["Size"].ToString())); } catch { listView1.Items[i].SubItems.Add("设备未准备好"); } //剩余空间 try { listView1.Items[i].SubItems.Add(GetSizeUseUnit(dis k["FreeSpace"].ToString())); } catch { listView1.Items[i].SubItems.Add("设备未准备好"); } i++; } }
2010年08月18日
一、 简介
若仅简单获取逻辑驱动器的名称列表我们使用.Net框架的Environment.GetLogicalDrives即可,但是若想获得更多关于磁盘驱动器的信息我们可以使用.Net框架下的System.Management 命名空间所提供的类和委托等对大量管理信息和管理事件的集合进行访问,这些信息和事件都与 WMI有关,该命名空间下的类实际上也是对WMI的一种封装,应用程序和服务可以使用从 ManagementObjectSearcher 和 ManagementQuery 派生的类,查询感兴趣的管理信息,例如在磁盘上还剩多少可用空间、当前 CPU 利用率是多少、某一应用程序正连接到哪一数据库等等,现在我们就以 C# 语言编写获取详细的逻辑驱动器信息的示例来展示.Net框架System.Management 命名空间的相关类和WMI编程,如下图:
二、技术要点
WMI最初是内置在 Windows 2000、Windows XP 和 Windows Server 2003 系列操作系统中核心的管理支持技术,目前WMI 已经是一种规范和基础结构,通过它可以访问、配置、管理和监视几乎所有的 Windows 资源例如磁盘、事件日志、文件、文件夹、文件系统、网络组件、操作系统设置、性能数据、打印机、进程、注册表设置、安全性、服务、共享、用户、组等等。在 WMI 之前,能够以编程方式访问 Windows 资源的惟一方法就是通过 Win32 API,现在我们除了使用WMI 脚本管理任何通过 WMI 公开的 Windows 资源外,还可以通过.Net框架对于WMI封装的System.Management 命名空间来轻松实现。
我们首先使用WMI查询来获取特定类名的SelectQuery实例,可以有两种方法创建该实例,一是可以传递一个已知的类名,譬如本文需要传递的类名为:Win32_LogicalDisk,代码如下:
或者使用wql查询来创建查询类的实例,代码如下:
或者只获取类的部分属性,代码如下:
WQL查询语言是 SQL 的一个子集,查询通过包含以下内容限制返回的数据量1、SELECT 子句,指定只返回某些属性的数据;2、WHERE 子句,指定要返回的实例。Win32_LogicalDisk类在默认的本地MSDN里是无法找到的,只有在联机的MSDN里,Win32 and COM Development下的WMI下才能找到,同样可以使用的类还有很多很多,包含登录用户信息的Win32_Account类、包含本地和共享打印机信息的Win32_PrinterShare类等等。Win32_LogicalDisk里所包含的驱动器属性相当丰富. 然后使用该指定的SelectQuery查询创建ManagementObjectSearcher实例,此类是用于检索管理信息的较为常用的入口点之一,实例创建结束,我们需要调用Get方法执行查询以便检索管理对象的集合,当调用该方法时,ManagementObjectSearcher 在指定的范围内执行给定的查询,并返回与 ManagementObjectCollection 中的查询匹配的管理对象的集合,这是就可以在一个循环中遍历集合中的所有对象,并获取我们所感兴趣的对象的属性,代码如下: …… SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery); int i=0; foreach (ManagementObject disk in searcher.Get()) { //获取驱动器盘符 listView1.Items.Add(disk["Name"].ToString()); } ……
三、 程序实现
我们使用Visual Studio 2005来创建该示例程序,首先创建C#的Windows应用程序空白项目,为解决方案和项目取名为 GetLogicDrives,在默认的Form1窗体上我们各放置一个ListView和一个Button控件,保留控件的默认名称不变,将ListView1的View属性设为Details,双击ListView1的Columns属性,为详细信息视图添加5个列,分别为:盘符、卷标、类型、容量和可用空间,设置Button1的Text属性为Refresh,为该Button1添加单击事件,代码如下: private void button1_Click(object sender, EventArgs e) { listView1.Items.Clear(); SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery); int i=0; foreach (ManagementObject disk in searcher.Get()) { //盘符 listView1.Items.Add(disk["Name"].ToString()); //卷标 try { listView1.Items[i].SubItems.Add(disk["VolumeName"] .ToString()); } catch { listView1.Items[i].SubItems.Add("设备未准备好"); } //驱动器类型 string DriveType; try { DriveType = disk["DriveType"].ToString(); switch (DriveType) { case "0": listView1.Items[i].SubItems.Add("未知设备"); break; case "1": listView1.Items[i].SubItems.Add("未分区"); break; case "2": listView1.Items[i].SubItems.Add("可移动磁盘"); break; case "3": listView1.Items[i].SubItems.Add("硬盘"); break; case "4": listView1.Items[i].SubItems.Add("网络驱动器"); break; case "5": listView1.Items[i].SubItems.Add("光驱"); break; case "6": listView1.Items[i].SubItems.Add("内存磁盘"); break; } } catch { listView1.Items[i].SubItems.Add("未知类型"); } //容量 try { listView1.Items[i].SubItems.Add(GetSizeUseUnit(dis k["Size"].ToString())); } catch { listView1.Items[i].SubItems.Add("设备未准备好"); } //剩余空间 try { listView1.Items[i].SubItems.Add(GetSizeUseUnit(dis k["FreeSpace"].ToString())); } catch { listView1.Items[i].SubItems.Add("设备未准备好"); } i++; } }