C#通过API对硬件进行禁用和启用

编程入门 行业动态 更新时间:2024-10-08 08:29:20

C#通过API对<a href=https://www.elefans.com/category/jswz/34/1769850.html style=硬件进行禁用和启用"/>

C#通过API对硬件进行禁用和启用

慢慢的随着年龄的增长,脑子越来越不够用,而自己的收藏栏也越来越杂乱,虽然现在的网上要啥都有,但是没有经过自己亲手实验和整理总结,下次需要的时候一切又要从头开始,而电子星球却正好提供了一个整理的平台,同时因为平台福利也算给了动力,所以遇到问题后又自己亲手解决了,就想记录总结下来,以备自己查阅,也希望能帮助需要的人。同时也感谢电子星球提供这样的平台

最近在做项目的过程中,涉及到对硬件启用及禁用的功能(在指定时间段内才能启用硬件)。因为C#自身对硬件的操作基本为零,但是C#操作底层硬件基本都通过API实现,API可以操作开关机,API也可以操作硬件设备,上网一搜果然可以实现。

为此,我们现在来构建我们自己的外部调用类:Externs

下面直接Externs类代码,并在注释里加入了官方参考链接。以供查阅

   ///〈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〉/// 注册设备或者设备类型,在指定的窗口返回相关的信息/// 参考:.aspx/// 〈/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〉/// 通过名柄,关闭指定设备的信息。/// 参考:(VS.85).aspx/// 〈/summary〉/// 〈param name="hHandle"〉〈/param〉/// 〈returns〉〈/returns〉[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern uint UnregisterDeviceNotification(IntPtr hHandle);/// 〈summary〉/// 获取一个指定类别或全部类别的所有已安装设备的信息/// 参考 :.aspx/// 〈/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, string iEnumerator, IntPtr hParent, UInt32 nFlags);/// 〈summary〉/// 销毁一个设备信息集合,并且释放所有关联的内存 /// 参考:ttp://msdn2.microsoft/en-us/library/ms792991.aspx/// 〈/summary〉/// 〈param name="lpInfoSet"〉〈/param〉/// 〈returns〉〈/returns〉[DllImport("setupapi.dll", SetLastError = true)]public static extern int SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);/// 〈summary〉/// 枚举指定设备信息集合的成员,并将数据放在SP_DEVINFO_DATA中/// 参考:.aspx/// 〈/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〉/// 获取指定设备的属性///参考:.aspx/// 〈/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〉/// 停用设备 参考:.aspx/// 〈/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〉/// 启用设备 参考:.aspx/// 〈/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;};}

完成了该类后,我们还需要写一个对硬件操作与获取的操作类HardwareClass

需要重点说明几个需要注意的地方:

1.if (hDevInfo.ToInt64() == Externs.INVALID_HANDLE_VALUE)中

       hDevInfo.ToInt64()对应64位系统

       hDevInfo.ToInt32()对应32位系统

     如果跟自己的系统不对应就会报错

2.  DeviceInfoData.cbSize 的值,官方文档中DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA)通过这个函数获取,也可以通过不同系统直接复制

  64位系统:sizeof(SP_DEVINFO_DATA)=32

  32位系统:sizeof(SP_DEVINFO_DATA)=28

3.Externs.SetupDiGetClassDevs(ref myGUID, "HID", IntPtr.Zero, Externs.DIGCF_ALLCLASSES | Externs.DIGCF_PRESENT)中第二个参数,如果想获取所有设备管理器硬件信息列表,直接把参数类型改为整数型,参数改为0,

如果要获取usb设备,直接把第二个参数给为“USB”就可以获取所有的USB设备名称列表

如果要获取HID设备,直接把第二个参数给为“HID”就可以获取所有的HID设备名称列表

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;namespace XXXXX.Public
{public class HardwareClass{#region 属性/// <summary>/// 返回所有硬件信息列表/// </summary>public string[] List{get{List<string> HWList = new List<string>();try{Guid myGUID = System.Guid.Empty;IntPtr hDevInfo = Externs.SetupDiGetClassDevs(ref myGUID, "HID", IntPtr.Zero, Externs.DIGCF_ALLCLASSES | Externs.DIGCF_PRESENT);if (hDevInfo.ToInt64() == Externs.INVALID_HANDLE_VALUE){throw new Exception("Invalid Handle");}Externs.SP_DEVINFO_DATA DeviceInfoData;DeviceInfoData = new Externs.SP_DEVINFO_DATA();DeviceInfoData.cbSize = 32;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)){break;}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, "HID", IntPtr.Zero, Externs.DIGCF_ALLCLASSES | Externs.DIGCF_PRESENT);if (hDevInfo.ToInt64() == Externs.INVALID_HANDLE_VALUE){return false;}Externs.SP_DEVINFO_DATA DeviceInfoData;DeviceInfoData = new Externs.SP_DEVINFO_DATA();DeviceInfoData.cbSize = 32;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)){break;}bool bMatch = true;foreach (string search in match){if (!DeviceName.ToString().ToLower().Contains(search.ToLower())){bMatch = false;break;}}if (bMatch){OpenClose(hDevInfo, DeviceInfoData, bEnable);break;}}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);elseExterns.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#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}
}

剩下就是调用了,类实例化后就可以启动禁用硬件设备了,传入需要设置的参数硬件名称,是否禁用还是启用,直接传入true或者false就可以了

hd.SetState(SysInfo.strHid, true);

但是问题来了,必须程序以管理员权限运行才能成功操作,所以不是管理员启动就会失败

更多推荐

C#通过API对硬件进行禁用和启用

本文发布于:2024-02-13 16:42:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1759921.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:硬件   API

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!