本文主要介绍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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。