,,在C#中根据HardwareID获取驱动程序信息的实现代码

,,在C#中根据HardwareID获取驱动程序信息的实现代码

本文主要介绍C#中根据HardwareID获取驱动信息的实现代码,有需要的朋友可以参考一下。

最近我们需要根据设备的HardwareID来获取设备的驱动信息,比如驱动版本。经过摸索,我们得到了两种不同的解决方案,各有千秋。把它们写出来和大家分享。

1 使用WMI中的Win32_PnPSignedDriver类

Win32_PnPSignedDriver的详细信息:http://msdn2.microsoft.com/en-us/library/aa394354.aspx

wmi(windows management instrumentation)是最方便的方法。我们可以根据下面的程序片段得到我们需要的DriverVersion。

私有字符串GetDriverVersion(字符串hardwareID)

{

string query string=' SELECT hardware id,driver version FROM Win32 _ PnPSignedDriver ';

select query select query=new select query(query string);

management object searcher searcher=new management object searcher(select query);

foreach(搜索器中的管理对象维护对象。Get())

{

object tempID=mo[' hardware id '];

if( tempID!=空临时ID。ToString()。ToUpper()==hardwareID。修剪()。ToUpper())

{

返回mo['DriverVersion']。ToString();

}

}

返回“unknown version”;

}

这种获取司机的方式很简单,但是有一个很严重的问题就是效率。平均而言,每次执行查询时,大约需要3秒钟来获取DriverVersion。对于我们的应用程序,这个时间是不可接受的。您可能会说,为什么不使用更多的限定符来进一步减少查询的数量呢?

如果我们将连接字符串更改为:

string query string=' SELECT hardware id,driver version FROM Win32 _ PnPSignedDriver WHERE hardware id=' some hardware ';

程序的效率并没有明显提高。我们还发现了一个问题。如果我们在somehardware中有一个' \ '(也就是HardwareID='some\\hardware '),我们肯定会得到一个“无效查询”异常。不过WMITOOLS中的查询是正常的,希望专家给点意见。最后,根据MSDN的描述,只有Windows Vista、Windows XP和Windows 2003支持这个类。因为我们的程序需要在2000以下运行,所以这种方法不可行。

2 使用PInvoke

因为不能用WMI,所以想到用PInvoke调用Windows API。通过查询MSDN,我们知道可以使用SetupDixxxx的函数来实现我们的功能。基本想法如下:

(1)使用SetupDiGetClassDevs的函数获取一个包含所有设备信息的类。

(2)使用SetupDiEnumDeviceInfo获取特定设备的信息,保存在一个名为SP_DEVINFO_DATA的结构中。

(3)使用setupdigetdevicesregistryproperty获取设备的HardwareID,并与输入的HardwareID进行比较。

(4)如果两个硬件id相同,则使用SetupDiBuildDriverInfoList获取该设备的驱动程序信息列表。

(5)使用SetupDiEnumDriverInfo遍历驱动信息列表,获取所有需要的信息,保存在一个名为SP_DRVINFO_DATA的结构中。

(6)驱动程序的版本可以从SP_DRVINFO_DATA中获取。是一个DWORDLONG类型的数字,需要转换成x.x.x.x的结构

值得注意的是,上述功能都封装在setupapi.dll中。要使用这些功能,您需要安装Windows DDK。

在C#中,我们使用pInvoke调用Windows API时,需要注意类型对应和结构对齐。例如,上面的SP_DEVINFO_DATA结构需要声明如下

[StructLayout(LayoutKind。顺序,Pack=4,CharSet=CharSet。自动)]

公共结构SP_DEVINFO_DATA

{

public int cbSize

公共Guid ClassGuid

public IntPtr DevInst

public IntPtr保留;

}

注意LayoutKind。Sequential,Pack=4,public IntPtr保留。如果没有这样声明,调用就不会成功。

SP_DRVINFO_DATA也可以用同样的方式声明。

[StructLayout(LayoutKind。顺序,Pack=4,CharSet=CharSet。自动)]

公共结构SP_DRVINFO_DATA

{

public int cbSize

public int DriverType

公共保护机构保留;

[沼泽(未受污染的类型)。ByValTStr,sizeconst=256

公共字符串说明;

[沼泽(未受污染的类型)。ByValTStr,sizeconst=256

公共字符串mfgname

[沼泽(未受污染的类型)。ByValTStr,sizeconst=256

公共字符串提供程序名称;

公共线程驱动程序日期(公用螺纹驱动程式日期):

公共ulong驱动程序版本(公用乌龙驱动程式版本);

}

对于最后的从德沃龙转换成的版本,可以按照下面的方式转换。德沃龙是8字节的无符号整数,x.x.x。中中的x个是从0到65536的无符号整数,占2个字节。因此可以直接把8字节的整数分成四个2字节的整数,最后合起来就是版本号了。假设版本版本=1407379348914176,将版本转换成2进制数为:

101 00000000 00000001 00001010 00101000 00000000 00000000

- -

5 1 2600 0

因此,可以得到版本是5.1.2600.0 .

可以用下面这个示例函数来得到版本信息

//版本=1407379348914176,转换后的版本为5.1.2600.0版

私有字符串GetVersionFromLong( ulong版本)

{

ulong基数=0 xffff

字符串生成器sb=new string builder();

ulong temp=0l

对于(int offset=48);偏移=0:偏移-=16)

{

温度=(偏移版本)基数

S7-1200可编程控制器。附录(临时)。ToString()“.”);

}

返回某人.tostring();

}

通过调用美国石油学会这种方式,速度得到了很大的提高,1秒之内就可以完成一次查询。而且适合于Win2000、Win XP、Win2003和Vista(查看)。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 设计一个简单的C#控制台应用程序,C#控制台程序,C# 创建控制台应用程序
  • 深入解析windows第8版,深入解析C#(第4版)
  • 数组代码,c# 数组操作,C# 数组实例介绍(图文)
  • 学会C#要多久,学会c#要多久,c#学习之30分钟学会XAML
  • 回溯法01背包问题c,回溯法求解01背包问题伪代码,C#使用回溯法解决背包问题实例分析
  • xml文件转义字符,xml转意字符,C# XML中的转义字符操作
  • winform 进度条控件,c# 进度条使用
  • winform 进度条控件,c# 进度条使用,C#使用winform实现进度条效果
  • winform backgroundworker,c# isbackground
  • winform backgroundworker,c# isbackground,C# BackgroundWorker用法详解
  • lua与c#交互,lua c#
  • lua与c#交互,lua c#,ToLua框架下C#与Lua代码的互调操作
  • linq c#,linq原理 c#
  • linq c#,linq原理 c#,c#中LINQ的基本用法实例
  • java decimal保留两位小数,sql中decimal函数保留2位小数,C#中decimal保留2位有效小数的实现方法
  • 留言与评论(共有 条评论)
       
    验证码: