c#中的系统驱动程序列表

时间:2017-11-23 08:07:06

标签: c# wmi

我正在努力列出系统中已安装的驱动程序,如设备管理器中所示。 我从Win32_PnPSignedDriver获得了该列表,但它没有提供图标。有没有办法找到或我必须为列表添加自定义图标。我想生成输出,就像在设备管理器中一样。我在C / C ++中找到了一些引用但在c#中没有。

enter image description here

2 个答案:

答案 0 :(得分:1)

有一个很好的article使用SHGetFileInfo函数来获取相关的图标,我建议你研究一下。

使用纯.Net或C#无法做到这一点,你需要在文章中使用这个dll。

修改

也许这MDSN Device Information会有所帮助

答案 1 :(得分:0)

我认为我们中的许多人对@Simon 的代码有一些错误。 这是他修改后的代码:

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);
    }
}