Recently in the work needs according to the equipment HardwareID to obtain the device the driver information, like the driver version and so on. After groping, got two kinds of different solutions, two ways, write to share.
1 using the Win32_pnpsigneddriver class in WMI
Win32_pnpsigneddriver For more information: http://msdn2.microsoft.com/en-us/library/aa394354.aspx
Using WMI (Windows Management instrumentation) is the most convenient method. We can get the driverversion we need according to the following program fragment.
private string Getdriverversion (string HardwareID)
{
String querystring = ' Select HardwareID, driverversion FRO M Win32_pnpsigneddriver ";
SelectQuery selectquery = new SelectQuery (querystring);
ManagementObjectSearcher searcher = new ManagementObjectSearcher (selectquery);
foreach (ManagementObject mo in searcher. Get ())
{
Object tempid = mo["HardwareID"];
if (Tempid!=null && tempid.tostring (). ToUpper () = = Hardwareid.trim (). ToUpper ())
{return
mo["DriverVersion"]. ToString ();
}
}
return "Unknownversion";
}
The way to get the driver is very concise, but there is a very serious problem is the efficiency problem. On average, it takes about 3 seconds to get a driverversion every time a query is executed. This time is not acceptable for our applications. You might say, why not use more qualifying notation to further reduce the number of queries?
If we change the connection string to:
String querystring = "Select HardwareID, driverversion from Win32_pnpsigneddriver WHERE hardwareid= ' Somehardware '";
There is no noticeable improvement in the efficiency of the program. And also found a problem, if we somehardware contains a ' \ ' (that is, hardwareid= ' Some\\hardware '), then there will be a "Invalid Query" exception. But in the wmitools inside the query is normal, I hope the talent out pointing. Finally, according to the MSDN description, only Windows Vista,windows XP and Windows 2003 support this class. Since our program needs to run at 2000, this method is not workable.
2 Using PInvoke
Because WMI is not available, it is thought of invoking the Windows API using PInvoke. By querying MSDN, you know that you can use the SETUPDIXXXX function to implement our functionality. The basic ideas are as follows:
(1) using the Setupdigetclassdevs function to get a class containing all the device information.
(2) using Setupdienumdeviceinfo to obtain the information of a specific device, stored in a structure called Sp_devinfo_data.
(3) using Setupdigetdeviceregistryproperty to obtain the hardwareid of the equipment, and the input HardwareID comparison
(4) If two HardwareID are the same, use Setupdibuilddriverinfolist to get a list of driver information for this device
(5) using Setupdienumdriverinfo to traverse the list of driver information, get all the information needed, and save it in a structure named Sp_drvinfo_data
(6) The version of the driver can be obtained from the sp_drvinfo_data. is a dwordlong type of number that needs to be converted into a x.x.x.x structure
It is important to note that the above functions are encapsulated in Setupapi.dll, and to use these functions, you need to install Windows DDK.
In C #, when we invoke the Windows API using the PInvoke approach, we need to be aware of the corresponding and structural alignment of the types. For example, the above sp_devinfo_data structure needs to be declared as follows
[StructLayout (layoutkind.sequential, Pack = 4, CharSet = CharSet.Auto)]
public struct Sp_devinfo_data
{public
int cbsize;
Public Guid Classguid;
Public IntPtr Devinst;
Public IntPtr Reserved;
}
Note that layoutkind.sequential, Pack = 4 and public IntPtr Reserved. If you do not follow this declaration, you cannot invoke success.
Sp_drvinfo_data can also be declared in the same way.
[StructLayout (layoutkind.sequential, Pack = 4, CharSet = CharSet.Auto)]
public struct Sp_drvinfo_data
{public
int cbsize;
public int drivertype;
Public IntPtr Reserved;
[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 256)]
public string mfgname;
[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 256)]
public string providername;
Public filetime DriverDate;
public ulong driverversion;
}
For the final version to be converted from Dwordlong to x.x.x.x, you can do so in the following way. Dwordlong is a 8-byte unsigned integer, and the X in x.x.x.x is an unsigned integer from 0 to 65536, accounting for 2 bytes. So you can divide the 8-byte integer directly into 4 2-byte integers, and finally the version number is combined. Suppose version versions = 1407379348914176, convert version to 2 number as:
101 00000000 00000001 00001010 00101000 00000000 00000000
--- --------------------- ---------------------- ---------------------
5 1 2600 0
Therefore, the version that can be obtained is 5.1.2600.0.
You can use the following example function to get the version information
Version = 1407379348914176, converted to 5.1.2600.0
private string Getversionfromlong (ULONG version)
{
ulong Basenumber = 0xFFFF;
StringBuilder sb = new StringBuilder ();
ULONG temp = 0L;
for (int offset = + offset >= 0; offset =)
{
temp = (version >> offset) & Basenumber;
Sb. Append (temp. ToString () + ".");
Return SB. ToString ();
}
By invoking the API this way, the speed is greatly improved, within 1 seconds to complete the query. It is also suitable for Win2000,win xp,win2003 and Vista.