C#对硬件的控制。最近在做项目的过程中,涉及到对硬件启用及禁用的功能(在指定时间段内才能启用硬件)。因为C#自身对硬件的操作基本为零,为此,搜索了一下MSDN中与设备相关的API函数。还果然就有。下面一一列举出各函数的原型及相关的说明文档。并将其转为C#代码实现。

解决方案 »

  1.   

    API相关。函数原型具体可参考:http://blog.csdn.net/cocosoft/archive/2008/02/08/2086710.aspx
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;namespace Hardware
    {
        /// <summary>
        /// 下列所需函数可参考MSDN中与驱动程序相关的API函数
        /// </summary>
        public class Externs
        {
            public const int DIGCF_ALLCLASSES = (0x00000004);
            public const int DIGCF_PRESENT = (0x00000002);
            public const int INVALID_HANDLE_VALUE = -1;
            public const int SPDRP_DEVICEDESC = (0x00000000);
            public const int MAX_DEV_LEN = 1000;
            public const int DEVICE_NOTIFY_WINDOW_HANDLE = (0x00000000);
            public const int DEVICE_NOTIFY_SERVICE_HANDLE = (0x00000001);
            public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = (0x00000004);
            public const int DBT_DEVTYP_DEVICEINTERFACE = (0x00000005);
            public const int DBT_DEVNODES_CHANGED = (0x0007);
            public const int WM_DEVICECHANGE = (0x0219);
            public const int DIF_PROPERTYCHANGE = (0x00000012);
            public const int DICS_FLAG_GLOBAL = (0x00000001);
            public const int DICS_FLAG_CONFIGSPECIFIC = (0x00000002);
            public const int DICS_ENABLE = (0x00000001);
            public const int DICS_DISABLE = (0x00000002);        /// <summary>
            /// 注册设备或者设备类型,在指定的窗口返回相关的信息
             /// </summary>
            /// <param name="hRecipient"></param>
            /// <param name="NotificationFilter"></param>
            /// <param name="Flags"></param>
            /// <returns></returns>
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, DEV_BROADCAST_DEVICEINTERFACE NotificationFilter, UInt32 Flags);        /// <summary>
            /// 通过名柄,关闭指定设备的信息。
             /// </summary>
            /// <param name="hHandle"></param>
            /// <returns></returns>
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern uint UnregisterDeviceNotification(IntPtr hHandle);        /// <summary>
            /// 获取一个指定类别或全部类别的所有已安装设备的信息
             /// </summary>
            /// <param name="gClass"></param>
            /// <param name="iEnumerator"></param>
            /// <param name="hParent"></param>
            /// <param name="nFlags"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, UInt32 iEnumerator, IntPtr hParent, UInt32 nFlags);        /// <summary>
            /// 销毁一个设备信息集合,并且释放所有关联的内存
             /// </summary>
            /// <param name="lpInfoSet"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern int SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);        /// <summary>
            /// 枚举指定设备信息集合的成员,并将数据放在SP_DEVINFO_DATA中
             /// </summary>
            /// <param name="lpInfoSet"></param>
            /// <param name="dwIndex"></param>
            /// <param name="devInfoData"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern bool SetupDiEnumDeviceInfo(IntPtr lpInfoSet, UInt32 dwIndex, SP_DEVINFO_DATA devInfoData);        /// <summary>
            /// 获取指定设备的属性
             /// </summary>
            /// <param name="lpInfoSet"></param>
            /// <param name="DeviceInfoData"></param>
            /// <param name="Property"></param>
            /// <param name="PropertyRegDataType"></param>
            /// <param name="PropertyBuffer"></param>
            /// <param name="PropertyBufferSize"></param>
            /// <param name="RequiredSize"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet, SP_DEVINFO_DATA DeviceInfoData, UInt32 Property, UInt32 PropertyRegDataType, StringBuilder PropertyBuffer, UInt32 PropertyBufferSize, IntPtr RequiredSize);        /// <summary>
            /// 停用设备
             /// </summary>
            /// <param name="DeviceInfoSet"></param>
            /// <param name="DeviceInfoData"></param>
            /// <param name="ClassInstallParams"></param>
            /// <param name="ClassInstallParamsSize"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern bool SetupDiSetClassInstallParams(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, IntPtr ClassInstallParams, int ClassInstallParamsSize);        /// <summary>
            /// 启用设备
             /// </summary>
            /// <param name="InstallFunction"></param>
            /// <param name="DeviceInfoSet"></param>
            /// <param name="DeviceInfoData"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiCallClassInstaller(UInt32 InstallFunction, IntPtr DeviceInfoSet, IntPtr DeviceInfoData);        /// <summary>
            /// RegisterDeviceNotification所需参数
             /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            public struct DEV_BROADCAST_HANDLE
            {
                public int dbch_size;
                public int dbch_devicetype;
                public int dbch_reserved;
                public IntPtr dbch_handle;
                public IntPtr dbch_hdevnotify;
                public Guid dbch_eventguid;
                public long dbch_nameoffset;
                public byte dbch_data;
                public byte dbch_data1;
            }        // WM_DEVICECHANGE message
            [StructLayout(LayoutKind.Sequential)]
            public class DEV_BROADCAST_DEVICEINTERFACE
            {
                public int dbcc_size;
                public int dbcc_devicetype;
                public int dbcc_reserved;
            }        /// <summary>
            /// 设备信息数据
            /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            public class SP_DEVINFO_DATA
            {
                public int cbSize;
                public Guid classGuid;
                public int devInst;
                public ulong reserved;
            };        /// <summary>
            /// 属性变更参数
            /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            public class SP_PROPCHANGE_PARAMS
            {
                public SP_CLASSINSTALL_HEADER ClassInstallHeader = new SP_CLASSINSTALL_HEADER();
                public int StateChange;
                public int Scope;
                public int HwProfile;
            };        /// <summary>
            /// 设备安装
            /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            public class SP_DEVINSTALL_PARAMS
            {
                public int cbSize;
                public int Flags;
                public int FlagsEx;
                public IntPtr hwndParent;
                public IntPtr InstallMsgHandler;
                public IntPtr InstallMsgHandlerContext;
                public IntPtr FileQueue;
                public IntPtr ClassInstallReserved;
                public int Reserved;
                [MarshalAs(UnmanagedType.LPTStr)]
                public string DriverPath;
            };        [StructLayout(LayoutKind.Sequential)]
            public class SP_CLASSINSTALL_HEADER
            {
                public int cbSize;
                public int InstallFunction;
            };
        }
    }
      

  2.   

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;namespace Hardware
    {
        public class HardwareClass
        {
            属性#region 属性
             /// <summary>
            /// 返回所有硬件信息列表
             /// </summary>
            /// <returns></returns>
            public string[] List
            {
                get
                {
                    List<string> HWList = new List<string>();
                    try
                    {
                        Guid myGUID = System.Guid.Empty;
                        IntPtr hDevInfo = Externs.SetupDiGetClassDevs(ref myGUID, 0, IntPtr.Zero, Externs.DIGCF_ALLCLASSES | Externs.DIGCF_PRESENT);
                        if (hDevInfo.ToInt32() == Externs.INVALID_HANDLE_VALUE)
                        {
                            throw new Exception("Invalid Handle");
                        }
                        Externs.SP_DEVINFO_DATA DeviceInfoData;
                        DeviceInfoData = new Externs.SP_DEVINFO_DATA();
                        DeviceInfoData.cbSize = 28;
                        DeviceInfoData.devInst = 0;
                        DeviceInfoData.classGuid = System.Guid.Empty;
                        DeviceInfoData.reserved = 0;
                        UInt32 i;
                        StringBuilder DeviceName = new StringBuilder("");
                        DeviceName.Capacity = Externs.MAX_DEV_LEN;
                        for (i = 0; Externs.SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
                        {
                            while (!Externs.SetupDiGetDeviceRegistryProperty(hDevInfo, DeviceInfoData, Externs.SPDRP_DEVICEDESC, 0, DeviceName, Externs.MAX_DEV_LEN, IntPtr.Zero))
                            {
                                //Skip
                            }
                            HWList.Add(DeviceName.ToString());
                        }
                        Externs.SetupDiDestroyDeviceInfoList(hDevInfo);
                    }
                    catch (Exception ex)
                    ...{
                        throw new Exception("枚举设备列表出错", ex);
                    }
                    return HWList.ToArray();
                }
            }        #endregion        公共事件#region 公共事件
             /// <summary>
            /// 清理非托管资源
             /// </summary>
            /// <param name="callback"></param>
            public void Dispose(IntPtr callback)
            {
                try
                {
                    Externs.UnregisterDeviceNotification(callback);
                }
                catch
                {
                }
            }        /// <summary>
            /// 设置指定设备的状态
             /// </summary>
            /// <param name="match">设备名称</param>
            /// <param name="bEnable">是否启用</param>
            /// <returns></returns>
            public bool SetState(string[] match, bool bEnable)
            {
                try
                {
                    Guid myGUID = System.Guid.Empty;
                    IntPtr hDevInfo = Externs.SetupDiGetClassDevs(ref myGUID, 0, IntPtr.Zero, Externs.DIGCF_ALLCLASSES | Externs.DIGCF_PRESENT);
                    if (hDevInfo.ToInt32() == Externs.INVALID_HANDLE_VALUE)
                    {
                        return false;
                    }
                    Externs.SP_DEVINFO_DATA DeviceInfoData;
                    DeviceInfoData = new Externs.SP_DEVINFO_DATA();
                    DeviceInfoData.cbSize = 28;
                    DeviceInfoData.devInst = 0;
                    DeviceInfoData.classGuid = System.Guid.Empty;
                    DeviceInfoData.reserved = 0;
                    UInt32 i;
                    StringBuilder DeviceName = new StringBuilder("");
                    DeviceName.Capacity = Externs.MAX_DEV_LEN;
                    for (i = 0; Externs.SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
                    {
                        while (!Externs.SetupDiGetDeviceRegistryProperty(hDevInfo, DeviceInfoData, Externs.SPDRP_DEVICEDESC, 0, DeviceName, Externs.MAX_DEV_LEN, IntPtr.Zero))
                        {
                        }
                        bool bMatch = true;
                        foreach (string search in match)
                        {
                            if (!DeviceName.ToString().ToLower().Contains(search.ToLower()))
                            {
                                bMatch = false;
                                break;
                            }
                        }
                        if (bMatch)
                        {
                            OpenClose(hDevInfo, DeviceInfoData, bEnable);
                        }
                    }
                    Externs.SetupDiDestroyDeviceInfoList(hDevInfo);
                }
                catch (Exception ex)
                {
                    throw new Exception("枚举设备信息出错!", ex);
                    return false;
                }
                return true;
            }        /// <summary>
            /// 允许一个窗口或者服务接收所有硬件的通知
             /// 注:目前还没有找到一个比较好的方法来处理如果通知服务。
             /// </summary>
            /// <param name="callback"></param>
            /// <param name="UseWindowHandle"></param>
            /// <returns></returns>
            public bool AllowNotifications(IntPtr callback, bool UseWindowHandle)
            {
                try
                {
                    Externs.DEV_BROADCAST_DEVICEINTERFACE dbdi = new Externs.DEV_BROADCAST_DEVICEINTERFACE();
                    dbdi.dbcc_size = Marshal.SizeOf(dbdi);
                    dbdi.dbcc_reserved = 0;
                    dbdi.dbcc_devicetype = Externs.DBT_DEVTYP_DEVICEINTERFACE;
                    if (UseWindowHandle)
                        Externs.RegisterDeviceNotification(callback, dbdi, Externs.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES | Externs.DEVICE_NOTIFY_WINDOW_HANDLE);
                    else
                        Externs.RegisterDeviceNotification(callback, dbdi, Externs.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES | Externs.DEVICE_NOTIFY_SERVICE_HANDLE);
                    return true;
                }
                catch (Exception ex)
                {
                    string err = ex.Message;
                    return false;
                }
            }        #endregion
      

  3.   


            #region 私有事件
             /// <summary>
            /// 开启或者关闭指定的设备驱动
             /// 注意:该方法目前没有检查是否需要重新启动计算机。^.^
            /// </summary>
            /// <param name="hDevInfo"></param>
            /// <param name="devInfoData"></param>
            /// <param name="bEnable"></param>
            /// <returns></returns>
            private bool OpenClose(IntPtr hDevInfo, Externs.SP_DEVINFO_DATA devInfoData, bool bEnable)
            {
                try
                {
                    int szOfPcp;
                    IntPtr ptrToPcp;
                    int szDevInfoData;
                    IntPtr ptrToDevInfoData;
                    Externs.SP_PROPCHANGE_PARAMS SP_PROPCHANGE_PARAMS1 = new Externs.SP_PROPCHANGE_PARAMS();
                    if (bEnable)
                    {
                        SP_PROPCHANGE_PARAMS1.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(Externs.SP_CLASSINSTALL_HEADER));
                        SP_PROPCHANGE_PARAMS1.ClassInstallHeader.InstallFunction = Externs.DIF_PROPERTYCHANGE;
                        SP_PROPCHANGE_PARAMS1.StateChange = Externs.DICS_ENABLE;
                        SP_PROPCHANGE_PARAMS1.Scope = Externs.DICS_FLAG_GLOBAL;
                        SP_PROPCHANGE_PARAMS1.HwProfile = 0;                    szOfPcp = Marshal.SizeOf(SP_PROPCHANGE_PARAMS1);
                        ptrToPcp = Marshal.AllocHGlobal(szOfPcp);
                        Marshal.StructureToPtr(SP_PROPCHANGE_PARAMS1, ptrToPcp, true);
                        szDevInfoData = Marshal.SizeOf(devInfoData);
                        ptrToDevInfoData = Marshal.AllocHGlobal(szDevInfoData);                    if (Externs.SetupDiSetClassInstallParams(hDevInfo, ptrToDevInfoData, ptrToPcp, Marshal.SizeOf(typeof(Externs.SP_PROPCHANGE_PARAMS))))
                        {
                            Externs.SetupDiCallClassInstaller(Externs.DIF_PROPERTYCHANGE, hDevInfo, ptrToDevInfoData);
                        }
                        SP_PROPCHANGE_PARAMS1.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(Externs.SP_CLASSINSTALL_HEADER));
                        SP_PROPCHANGE_PARAMS1.ClassInstallHeader.InstallFunction = Externs.DIF_PROPERTYCHANGE;
                        SP_PROPCHANGE_PARAMS1.StateChange = Externs.DICS_ENABLE;
                        SP_PROPCHANGE_PARAMS1.Scope = Externs.DICS_FLAG_CONFIGSPECIFIC;
                        SP_PROPCHANGE_PARAMS1.HwProfile = 0;
                    }
                    else
                    {
                        SP_PROPCHANGE_PARAMS1.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(Externs.SP_CLASSINSTALL_HEADER));
                        SP_PROPCHANGE_PARAMS1.ClassInstallHeader.InstallFunction = Externs.DIF_PROPERTYCHANGE;
                        SP_PROPCHANGE_PARAMS1.StateChange = Externs.DICS_DISABLE;
                        SP_PROPCHANGE_PARAMS1.Scope = Externs.DICS_FLAG_CONFIGSPECIFIC;
                        SP_PROPCHANGE_PARAMS1.HwProfile = 0;
                    }
                    szOfPcp = Marshal.SizeOf(SP_PROPCHANGE_PARAMS1);
                    ptrToPcp = Marshal.AllocHGlobal(szOfPcp);
                    Marshal.StructureToPtr(SP_PROPCHANGE_PARAMS1, ptrToPcp, true);
                    szDevInfoData = Marshal.SizeOf(devInfoData);
                    ptrToDevInfoData = Marshal.AllocHGlobal(szDevInfoData);
                    Marshal.StructureToPtr(devInfoData, ptrToDevInfoData, true);                bool rslt1 = Externs.SetupDiSetClassInstallParams(hDevInfo, ptrToDevInfoData, ptrToPcp, Marshal.SizeOf(typeof(Externs.SP_PROPCHANGE_PARAMS)));
                    bool rstl2 = Externs.SetupDiCallClassInstaller(Externs.DIF_PROPERTYCHANGE, hDevInfo, ptrToDevInfoData);
                    if ((!rslt1) || (!rstl2))
                    {
                        throw new Exception("不能更改设备状态。");
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                catch (Exception ex)
                {
                    return false;
                }
            }        #endregion
        }
    }
      

  4.   

            private void Form1_Load(object sender, EventArgs e)
            {
                //枚举硬件列表
                string[] HardList = hc.List;
                foreach (string s in HardList)
                {
                    listBox1.Items.Add(s);
                }
                hc.AllowNotifications(Handle, true);
                label1.Text = "计算机内的设备数量为:" + listBox1.Items.Count.ToString();
            }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                //清理非托管资源
                hc.Dispose(Handle);
                hc = null;
            }        private void button1_Click(object sender, EventArgs e)
            {
                //启用硬件
                string[] dev = new string[1];
                hc.Dispose(Handle);
                dev[0] = listBox1.SelectedItem.ToString();
                hc.SetState(dev, true);
                hc.Dispose(Handle);
            }        private void button2_Click(object sender, EventArgs e)
            {
                //停用硬件
                string[] dev = new string[1];
                hc.Dispose(Handle);
                dev[0] = listBox1.SelectedItem.ToString();
                hc.SetState(dev, false);
                hc.Dispose(Handle);
            }
      

  5.   

    相关内容具体可参考:
    http://blog.csdn.net/cocosoft/archive/2008/02/08/2086710.aspx
    http://blog.csdn.net/cocosoft/archive/2008/02/08/2086712.aspx
    http://blog.csdn.net/cocosoft/archive/2008/02/08/2086762.aspx
    全部源码下载:
    http://download.csdn.net/source/351286
      

  6.   

    不清楚,后面重新上传到CSDN上时,说不允许上传相同的。:(放在公司网站上供大家下载吧。http://download.cobainsoft.com/DeviceManager.rar
      

  7.   

    请问cocosoft 如何还能获取某个设备的停用、启用状态?谢谢
      

  8.   

    to:CSharpEx 
    CSharp 
    等 级:
     发表于:2008-02-13 11:19:0563楼 得分:0 
    请问cocosoft   如何还能获取某个设备的停用、启用状态? 谢谢  
     ======================================使用下面的代码取设备的详细信息
            /// <summary>
            /// 取指定设备的明细信息
            /// </summary>
            /// <param name="hDevInfo"></param>
            /// <param name="deviceInterfaceData"></param>
            /// <param name="deviceInterfaceDetailData"></param>
            /// <param name="deviceInterfaceDetailDataSize"></param>
            /// <param name="requiredSize"></param>
            /// <param name="deviceInfoData"></param>
            /// <returns></returns>
            [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern Boolean SetupDiGetDeviceInterfaceDetail(
               IntPtr hDevInfo,
               ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
               ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
               UInt32 deviceInterfaceDetailDataSize,
               out UInt32 requiredSize,
               ref SP_DEVINFO_DATA deviceInfoData
            );        /// <summary>
            /// 设备明细数据
            /// </summary>
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct SP_DEVICE_INTERFACE_DETAIL_DATA
            {
                /// <summary>
                /// 默认值为4+Marshal.SystemDefaultCharSize;
                /// :)
                /// </summary>
                public int cbSize;
                public string DevicePath;
            }        public enum DeviceInterfaceDataFlags : uint
            {
                Active = 0x00000001,
                Default = 0x00000002,
                Removed = 0x00000004
            }        [StructLayout(LayoutKind.Sequential)]
            public struct SP_DEVICE_INTERFACE_DATA
            {
                public UInt32 size;
                public Guid interfaceClassGuid;
                public DeviceInterfaceDataFlags flags;
                public UIntPtr reserved;
            }
      

  9.   

    第一个下载地址无效,变更为:http://download.csdn.net/source/352079
      

  10.   


    可以尝试下WMI的类似实现