i am working on listing installed drivers in system as in Device manager. I got that list from Win32_PnPSignedDriver but it does not provide icons. Is there any way to find that or i have to add custom icons for the list. I want to generate output Like same as in Device manager.I found some reference in C/C++ but not in c#.
-
any suggestion please... – Anoop Mishra Nov 23 '17 at 09:00
-
What did you find in C/C++? – Simon Mourier Nov 27 '17 at 08:28
-
https://www.codeproject.com/Articles/14412/Enumerating-windows-device , this i found but in c++. – Anoop Mishra Nov 27 '17 at 10:00
3 Answers
Here are two utility classes DeviceClass
and Device
that demonstrate how to do it. They don't use WMI, but the setupapi
with p/invoke (and the System.Drawing's Icon class). I think this API is the only supported way to get the icon. You could then use WMI (using ids, and class ids to get more information this time using WMI).
Here is a comparison using these classes, in a Windows Form, and the Device Manager, as you see it's pretty close, but the class icon is not exactly the same, I don't know why, I've not investigated.
Last note: as expected, some devices have an icon that is different from their class and different from other icons in the same class. We can observe that in the first Audio class, the two devices don't have the same icon.
Here is the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// This is a standard Form. I have added a TreeView control and an ImageList to the Form.
// The image list is bound to the treeview, with ColorDepth set to Depth32Bit
var classes = DeviceClass.Load(DeviceFiter.AllClasses | DeviceFiter.Present);
foreach (var cls in classes)
{
var classNode = treeView1.Nodes.Add(cls.Description);
imageList1.Images.Add(cls.Icon);
classNode.ImageIndex = imageList1.Images.Count - 1;
classNode.SelectedImageIndex = classNode.ImageIndex;
foreach (var device in cls.Devices)
{
var deviceNode = classNode.Nodes.Add(device.Name);
imageList1.Images.Add(device.Icon);
deviceNode.ImageIndex = imageList1.Images.Count - 1;
deviceNode.SelectedImageIndex = deviceNode.ImageIndex;
}
classNode.Expand();
}
// dispose (icons)
foreach (var cls in classes)
{
foreach (var device in cls.Devices)
{
device.Dispose();
}
cls.Dispose();
}
}
}
public class DeviceClass : IDisposable, IComparable, IComparable<DeviceClass>
{
private List<Device> _devices = new List<Device>();
private Icon _icon;
internal DeviceClass(Guid classId, string description)
{
ClassId = classId;
Description = description;
}
public Guid ClassId { get; }
public string Description { get; }
public Icon Icon => _icon;
public IReadOnlyList<Device> Devices => _devices;
public static IReadOnlyList<DeviceClass> Load(DeviceFiter fiter)
{
var list = new List<DeviceClass>();
var hdevinfo = SetupDiGetClassDevs(IntPtr.Zero, null, IntPtr.Zero, fiter);
try
{
var data = new SP_DEVINFO_DATA();
data.cbSize = Marshal.SizeOf<SP_DEVINFO_DATA>();
int index = 0;
while (SetupDiEnumDeviceInfo(hdevinfo, index, ref data))
{
index++;
var classId = GetGuidProperty(hdevinfo, ref data, DEVPKEY_Device_ClassGuid);
if (classId == Guid.Empty)
continue;
string classDescription = GetClassDescription(classId);
var cls = list.FirstOrDefault(c => c.ClassId == classId);
if (cls == null)
{
cls = new DeviceClass(classId, classDescription);
list.Add(cls);
SetupDiLoadClassIcon(ref classId, out IntPtr clsIcon, out int mini);
if (clsIcon != IntPtr.Zero)
{
cls._icon = Icon.FromHandle(clsIcon);
}
}
string name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_FriendlyName);
if (string.IsNullOrWhiteSpace(name))
{
name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_DeviceDesc);
}
Icon icon = null;
SetupDiLoadDeviceIcon(hdevinfo, ref data, 16, 16, 0, out IntPtr devIcon);
if (devIcon != IntPtr.Zero)
{
icon = Icon.FromHandle(devIcon);
}
var dev = new Device(cls, name, icon);
cls._devices.Add(dev);
}
}
finally
{
if (hdevinfo != IntPtr.Zero)
{
SetupDiDestroyDeviceInfoList(hdevinfo);
}
}
foreach (var cls in list)
{
cls._devices.Sort();
}
list.Sort();
return list;
}
int IComparable.CompareTo(object obj) => CompareTo(obj as DeviceClass);
public int CompareTo(DeviceClass other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Description.CompareTo(other.Description);
}
public void Dispose()
{
if (_icon != null)
{
_icon.Dispose();
_icon = null;
}
}
private static string GetClassDescription(Guid classId)
{
SetupDiGetClassDescription(ref classId, IntPtr.Zero, 0, out int size);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size * 2);
try
{
if (!SetupDiGetClassDescription(ref classId, ptr, size, out size))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, size - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static string GetStringProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out int propertyType, IntPtr.Zero, 0, out int size, 0);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size);
try
{
if (!SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, ptr, size, out size, 0))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, (size / 2) - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static Guid GetGuidProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out int propertyType, out Guid guid, 16, out int size, 0);
return guid;
}
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public int DevInst;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
private struct DEVPROPKEY
{
public Guid fmtid;
public int pid;
}
private const int ERROR_NOT_FOUND = 118;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private static readonly DEVPROPKEY DEVPKEY_Device_DeviceDesc = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 2 };
private static readonly DEVPROPKEY DEVPKEY_Device_FriendlyName = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 14 };
private static readonly DEVPROPKEY DEVPKEY_Device_Class = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 9 };
private static readonly DEVPROPKEY DEVPKEY_Device_ClassGuid = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 10 };
[DllImport("setupapi", CharSet = CharSet.Unicode)]
private static extern IntPtr SetupDiGetClassDevs(IntPtr ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr hwndParent, DeviceFiter Flags);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, int MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetClassDescription(ref Guid ClassGuid, IntPtr ClassDescription, int ClassDescriptionSize, out int RequiredSize);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiLoadClassIcon(ref Guid ClassGuid, out IntPtr LargeIcon, out int MiniIconIndex);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiLoadDeviceIcon(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData,
int cxIcon, int cyIcon, int Flags, out IntPtr hIcon);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
IntPtr PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
out Guid PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
}
[Flags]
public enum DeviceFiter // DIGCF_* flags
{
Default = 1,
Present = 2,
AllClasses = 4,
Profile = 8,
DeviceInterface = 16
}
public class Device : IDisposable, IComparable, IComparable<Device>
{
internal Device(DeviceClass cls, string name, Icon icon)
{
Class = cls;
Name = name;
Icon = icon;
}
public string Name { get; }
public DeviceClass Class { get; }
public Icon Icon { get; private set; }
public override string ToString() => Name;
public void Dispose()
{
if (Icon != null)
{
Icon.Dispose();
Icon = null;
}
}
int IComparable.CompareTo(object obj) => CompareTo(obj as Device);
public int CompareTo(Device other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Name.CompareTo(other.Name);
}
}

- 132,049
- 21
- 248
- 298
-
-
the output you have shown in image i want same also. But in your code some of the syntax are not supported do i have to add some dll or you used some other IDE – Anoop Mishra Nov 28 '17 at 10:17
-
1Read the comments. In Visual Studio 2017, create a winform app, add a treeview, an imagelist, bind the treeview and the image list, change imagelist colordepth to 32b and resolve missing namespaces, it needs `using System.Runtime.InteropServices` at least. – Simon Mourier Nov 28 '17 at 12:32
-
ahh got that framework issue mine is 4.5 and yours is in 4.5.2 that is why the issue is created. – Anoop Mishra Nov 28 '17 at 13:18
-
**Requirement**: .NET Framework 4.5+. Also, set the `ImageList` property of the `TreeView` control in the Properties window. – Chiramisu Feb 01 '21 at 22:51
-
@Chiramisu - read the comments "The image list is bound to the treeview"... – Simon Mourier Feb 01 '21 at 22:55
-
Yes, but it doesn't say where or how to do that, so I offered a bit of guidance for the uninitiated. – Chiramisu Feb 02 '21 at 00:19
There is a nice article using SHGetFileInfo function to get associated icons, i'd recommend looking into that.
You cannot do it using pure .Net or C# you will need this dll in the article.
EDIT
Maybe this MDSN Device Information will be of help

- 10,636
- 1
- 28
- 46
-
So technically it is not possible to create a device manager utility in pure c# ? – Anoop Mishra Nov 27 '17 at 11:52
-
Unfortunately no.. not that I know of and I developed more then a single application like this. You will have to use this third party dll – Barr J Nov 27 '17 at 11:53
-
so i have to get details of drivers using pnpsigned drivers and after that add images with their names in treeview to create same view as in device manager. – Anoop Mishra Nov 27 '17 at 11:56
-
I think many of us having some errors with @Simon's codes. Here are his revised codes:
public class DeviceClass : IDisposable, IComparable, IComparable<DeviceClass>
{
private List<Device> _devices = new List<Device>();
private Icon _icon;
internal DeviceClass(Guid classId, string description)
{
ClassId = classId;
Description = description;
}
public Guid ClassId { get; }
public string Description { get; }
public Icon Icon => _icon;
public IReadOnlyList<Device> Devices => _devices;
public static IReadOnlyList<DeviceClass> Load(DeviceFiter fiter)
{
var list = new List<DeviceClass>();
var hdevinfo = SetupDiGetClassDevs(IntPtr.Zero, null, IntPtr.Zero, fiter);
try
{
var data = new SP_DEVINFO_DATA();
data.cbSize = System.Runtime.InteropServices.Marshal.SizeOf<SP_DEVINFO_DATA>();
int index = 0;
while (SetupDiEnumDeviceInfo(hdevinfo, index, ref data))
{
index++;
var classId = GetGuidProperty(hdevinfo, ref data, DEVPKEY_Device_ClassGuid);
if (classId == Guid.Empty)
continue;
string classDescription = GetClassDescription(classId);
var cls = list.FirstOrDefault(c => c.ClassId == classId);
if (cls == null)
{
cls = new DeviceClass(classId, classDescription);
list.Add(cls);
IntPtr clsIcon;
int mini;
SetupDiLoadClassIcon(ref classId, out clsIcon, out mini);
if (clsIcon != IntPtr.Zero)
{
cls._icon = Icon.FromHandle(clsIcon);
}
}
string name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_FriendlyName);
if (string.IsNullOrWhiteSpace(name))
{
name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_DeviceDesc);
}
Icon icon = null;
IntPtr devIcon;
SetupDiLoadDeviceIcon(hdevinfo, ref data, 16, 16, 0, out devIcon);
if (devIcon != IntPtr.Zero)
{
icon = Icon.FromHandle(devIcon);
}
var dev = new Device(cls, name, icon);
cls._devices.Add(dev);
}
}
finally
{
if (hdevinfo != IntPtr.Zero)
{
SetupDiDestroyDeviceInfoList(hdevinfo);
}
}
foreach (var cls in list)
{
cls._devices.Sort();
}
list.Sort();
return list;
}
int IComparable.CompareTo(object obj) => CompareTo(obj as DeviceClass);
public int CompareTo(DeviceClass other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Description.CompareTo(other.Description);
}
public void Dispose()
{
if (_icon != null)
{
_icon.Dispose();
_icon = null;
}
}
private static string GetClassDescription(Guid classId)
{
int size = 0;
SetupDiGetClassDescription(ref classId, IntPtr.Zero, 0, out size);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size * 2);
try
{
if (!SetupDiGetClassDescription(ref classId, ptr, size, out size))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, size - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static string GetStringProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
int propertyType;
int size;
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, IntPtr.Zero, 0, out size, 0);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size);
try
{
if (!SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, ptr, size, out size, 0))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, (size / 2) - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static Guid GetGuidProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
int propertyType, size;
Guid guid;
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, out guid, 16, out size, 0);
return guid;
}
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public int DevInst;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
private struct DEVPROPKEY
{
public Guid fmtid;
public int pid;
}
private const int ERROR_NOT_FOUND = 118;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private static readonly DEVPROPKEY DEVPKEY_Device_DeviceDesc = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 2 };
private static readonly DEVPROPKEY DEVPKEY_Device_FriendlyName = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 14 };
private static readonly DEVPROPKEY DEVPKEY_Device_Class = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 9 };
private static readonly DEVPROPKEY DEVPKEY_Device_ClassGuid = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 10 };
[DllImport("setupapi", CharSet = CharSet.Unicode)]
private static extern IntPtr SetupDiGetClassDevs(IntPtr ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr hwndParent, DeviceFiter Flags);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, int MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetClassDescription(ref Guid ClassGuid, IntPtr ClassDescription, int ClassDescriptionSize, out int RequiredSize);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiLoadClassIcon(ref Guid ClassGuid, out IntPtr LargeIcon, out int MiniIconIndex);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiLoadDeviceIcon(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData,
int cxIcon, int cyIcon, int Flags, out IntPtr hIcon);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
IntPtr PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
out Guid PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
}
[Flags]
public enum DeviceFiter // DIGCF_* flags
{
Default = 1,
Present = 2,
AllClasses = 4,
Profile = 8,
DeviceInterface = 16
}
public class Device : IDisposable, IComparable, IComparable<Device>
{
internal Device(DeviceClass cls, string name, Icon icon)
{
Class = cls;
Name = name;
Icon = icon;
}
public string Name { get; }
public DeviceClass Class { get; }
public Icon Icon { get; private set; }
public override string ToString() => Name;
public void Dispose()
{
if (Icon != null)
{
Icon.Dispose();
Icon = null;
}
}
int IComparable.CompareTo(object obj) => CompareTo(obj as Device);
public int CompareTo(Device other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Name.CompareTo(other.Name);
}
}

- 1
- 1