我正在寻找的方式来禁用系统设备(无论是USB或内部)在C#.NET给定的PID和VID或设备名称。
search后,我发现CodeProject上的C#硬件助手库 。
但是我需要能够在XP,Vista和Windows 7(包括x86和x64操作系统)上工作的东西… 我链接的项目只能在XP和Vista x86下运行…即使以pipe理员权限运行应用程序。
有谁知道可以在所有操作系统上工作的解决scheme吗?
看起来drf的版本中有两件事给你带来麻烦。 您的x64问题是由SP_DEVINFO_DATA具有一个需要IntPtr的uint引起的。 第二个是SetupDiGetDevicePropertyW函数是Vista +,不能在XP上运行。
这是一个更正了这两个问题的版本。 我测试了XPx86和Win7X64上的x86和AnyCPU。
public static class DisableHardware { const uint DIF_PROPERTYCHANGE = 0x12; const uint DICS_ENABLE = 1; const uint DICS_DISABLE = 2; // disable device const uint DICS_FLAG_GLOBAL = 1; // not profile-specific const uint DIGCF_ALLCLASSES = 4; const uint DIGCF_PRESENT = 2; const uint ERROR_INVALID_DATA = 13; const uint ERROR_NO_MORE_ITEMS = 259; const uint ERROR_ELEMENT_NOT_FOUND = 1168; static DEVPROPKEY DEVPKEY_Device_DeviceDesc; static DEVPROPKEY DEVPKEY_Device_HardwareIds; [StructLayout(LayoutKind.Sequential)] struct SP_CLASSINSTALL_HEADER { public UInt32 cbSize; public UInt32 InstallFunction; } [StructLayout(LayoutKind.Sequential)] struct SP_PROPCHANGE_PARAMS { public SP_CLASSINSTALL_HEADER ClassInstallHeader; public UInt32 StateChange; public UInt32 Scope; public UInt32 HwProfile; } [StructLayout(LayoutKind.Sequential)] struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid classGuid; public UInt32 devInst; public IntPtr reserved; // CHANGE #1 - was UInt32 } [StructLayout(LayoutKind.Sequential)] struct DEVPROPKEY { public Guid fmtid; public UInt32 pid; } [DllImport("setupapi.dll", SetLastError = true)] static extern IntPtr SetupDiGetClassDevsW( [In] ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr parent, UInt32 flags); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiDestroyDeviceInfoList(IntPtr handle); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, UInt32 memberIndex, [Out] out SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiSetClassInstallParams( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA deviceInfoData, [In] ref SP_PROPCHANGE_PARAMS classInstallParams, UInt32 ClassInstallParamsSize); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiChangeState( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiGetDevicePropertyW( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA DeviceInfoData, [In] ref DEVPROPKEY propertyKey, [Out] out UInt32 propertyType, IntPtr propertyBuffer, UInt32 propertyBufferSize, out UInt32 requiredSize, UInt32 flags); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiGetDeviceRegistryPropertyW( IntPtr DeviceInfoSet, [In] ref SP_DEVINFO_DATA DeviceInfoData, UInt32 Property, [Out] out UInt32 PropertyRegDataType, IntPtr PropertyBuffer, UInt32 PropertyBufferSize, [In,Out] ref UInt32 RequiredSize ); static DisableHardware() { DisableHardware.DEVPKEY_Device_DeviceDesc = new DEVPROPKEY(); DEVPKEY_Device_DeviceDesc.fmtid = new Guid( 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0); DEVPKEY_Device_DeviceDesc.pid = 2; DEVPKEY_Device_HardwareIds = new DEVPROPKEY(); DEVPKEY_Device_HardwareIds.fmtid = new Guid( 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0); DEVPKEY_Device_HardwareIds.pid = 3; } public static void DisableDevice(Func<string, bool> filter, bool disable = true) { IntPtr info = IntPtr.Zero; Guid NullGuid = Guid.Empty; try { info = SetupDiGetClassDevsW( ref NullGuid, null, IntPtr.Zero, DIGCF_ALLCLASSES); CheckError("SetupDiGetClassDevs"); SP_DEVINFO_DATA devdata = new SP_DEVINFO_DATA(); devdata.cbSize = (UInt32)Marshal.SizeOf(devdata); // Get first device matching device criterion. for (uint i = 0; ; i++) { SetupDiEnumDeviceInfo(info, i, out devdata); // if no items match filter, throw if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS) CheckError("No device found matching filter.", 0xcffff); CheckError("SetupDiEnumDeviceInfo"); string devicepath = GetStringPropertyForDevice(info, devdata, 1); // SPDRP_HARDWAREID // Uncomment to print name/path //Console.WriteLine(GetStringPropertyForDevice(info, // devdata, DEVPKEY_Device_DeviceDesc)); //Console.WriteLine(" {0}", devicepath); if (devicepath != null && filter(devicepath)) break; } SP_CLASSINSTALL_HEADER header = new SP_CLASSINSTALL_HEADER(); header.cbSize = (UInt32)Marshal.SizeOf(header); header.InstallFunction = DIF_PROPERTYCHANGE; SP_PROPCHANGE_PARAMS propchangeparams = new SP_PROPCHANGE_PARAMS(); propchangeparams.ClassInstallHeader = header; propchangeparams.StateChange = disable ? DICS_DISABLE : DICS_ENABLE; propchangeparams.Scope = DICS_FLAG_GLOBAL; propchangeparams.HwProfile = 0; SetupDiSetClassInstallParams(info, ref devdata, ref propchangeparams, (UInt32)Marshal.SizeOf(propchangeparams)); CheckError("SetupDiSetClassInstallParams"); SetupDiChangeState( info, ref devdata); CheckError("SetupDiChangeState"); } finally { if (info != IntPtr.Zero) SetupDiDestroyDeviceInfoList(info); } } private static void CheckError(string message, int lasterror = -1) { int code = lasterror == -1 ? Marshal.GetLastWin32Error() : lasterror; if (code != 0) throw new ApplicationException( String.Format("Error disabling hardware device (Code {0}): {1}", code, message)); } private static string GetStringPropertyForDevice(IntPtr info, SP_DEVINFO_DATA devdata, uint propId) { uint proptype, outsize; IntPtr buffer = IntPtr.Zero; try { uint buflen = 512; buffer = Marshal.AllocHGlobal((int)buflen); outsize=0; // CHANGE #2 - Use this instead of SetupDiGetDeviceProperty SetupDiGetDeviceRegistryPropertyW( info, ref devdata, propId, out proptype, buffer, buflen, ref outsize); byte[] lbuffer = new byte[outsize]; Marshal.Copy(buffer, lbuffer, 0, (int)outsize); int errcode = Marshal.GetLastWin32Error(); if (errcode == ERROR_INVALID_DATA) return null; CheckError("SetupDiGetDeviceProperty", errcode); return Encoding.Unicode.GetString(lbuffer); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } }
可以在Windows安装程序API上使用P / Invoke方法完成。 自W2K以来,API函数已经在Windows中。 API调用可能需要管理权限。 以下是使用这些API禁用(以及启用)C#中的设备的一些粗略代码,它允许调用:
DisableDevice( n => n.ToUpperInvariant().Contains("VID_3F20&PID_8A1D"), true); // true disables the device, false enables it
第一个参数是通过硬件ID的过滤器。 这会禁用或启用与提供的过滤器匹配的第一个设备。 如果设备已经处于目标状态,则不起作用。
代码如下。
public static class DisableHardware { const uint DIF_PROPERTYCHANGE = 0x12; const uint DICS_ENABLE = 1; const uint DICS_DISABLE = 2; // disable device const uint DICS_FLAG_GLOBAL = 1; // not profile-specific const uint DIGCF_ALLCLASSES = 4; const uint DIGCF_PRESENT = 2; const uint ERROR_NO_MORE_ITEMS = 259; const uint ERROR_ELEMENT_NOT_FOUND = 1168; static DEVPROPKEY DEVPKEY_Device_DeviceDesc; static DEVPROPKEY DEVPKEY_Device_HardwareIds; [StructLayout(LayoutKind.Sequential)] struct SP_CLASSINSTALL_HEADER { public UInt32 cbSize; public UInt32 InstallFunction; } [StructLayout(LayoutKind.Sequential)] struct SP_PROPCHANGE_PARAMS { public SP_CLASSINSTALL_HEADER ClassInstallHeader; public UInt32 StateChange; public UInt32 Scope; public UInt32 HwProfile; } [StructLayout(LayoutKind.Sequential)] struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid classGuid; public UInt32 devInst; public UInt32 reserved; } [StructLayout(LayoutKind.Sequential)] struct DEVPROPKEY { public Guid fmtid; public UInt32 pid; } [DllImport("setupapi.dll", SetLastError = true)] static extern IntPtr SetupDiGetClassDevsW( [In] ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr parent, UInt32 flags); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiDestroyDeviceInfoList(IntPtr handle); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, UInt32 memberIndex, [Out] out SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiSetClassInstallParams( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA deviceInfoData, [In] ref SP_PROPCHANGE_PARAMS classInstallParams, UInt32 ClassInstallParamsSize); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiChangeState( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiGetDevicePropertyW( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA DeviceInfoData, [In] ref DEVPROPKEY propertyKey, [Out] out UInt32 propertyType, IntPtr propertyBuffer, UInt32 propertyBufferSize, out UInt32 requiredSize, UInt32 flags); static DisableHardware() { DisableHardware.DEVPKEY_Device_DeviceDesc = new DEVPROPKEY(); DEVPKEY_Device_DeviceDesc.fmtid = new Guid( 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0); DEVPKEY_Device_DeviceDesc.pid = 2; DEVPKEY_Device_HardwareIds = new DEVPROPKEY(); DEVPKEY_Device_HardwareIds.fmtid = new Guid( 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0); DEVPKEY_Device_HardwareIds.pid = 3; } public static void DisableDevice(Func<string, bool> filter, bool disable = true) { IntPtr info = IntPtr.Zero; Guid NullGuid = Guid.Empty; try { info = SetupDiGetClassDevsW( ref NullGuid, null, IntPtr.Zero, DIGCF_ALLCLASSES); CheckError("SetupDiGetClassDevs"); SP_DEVINFO_DATA devdata = new SP_DEVINFO_DATA(); devdata.cbSize = (UInt32)Marshal.SizeOf(devdata); // Get first device matching device criterion. for (uint i = 0; ; i++) { SetupDiEnumDeviceInfo(info, i, out devdata); // if no items match filter, throw if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS) CheckError("No device found matching filter.", 0xcffff); CheckError("SetupDiEnumDeviceInfo"); string devicepath = GetStringPropertyForDevice(info, devdata, DEVPKEY_Device_HardwareIds); // Uncomment to print name/path //Console.WriteLine(GetStringPropertyForDevice(info, // devdata, DEVPKEY_Device_DeviceDesc)); //Console.WriteLine(" {0}", devicepath); if (devicepath != null && filter(devicepath)) break; } SP_CLASSINSTALL_HEADER header = new SP_CLASSINSTALL_HEADER(); header.cbSize = (UInt32)Marshal.SizeOf(header); header.InstallFunction = DIF_PROPERTYCHANGE; SP_PROPCHANGE_PARAMS propchangeparams = new SP_PROPCHANGE_PARAMS(); propchangeparams.ClassInstallHeader = header; propchangeparams.StateChange = disable ? DICS_DISABLE : DICS_ENABLE; propchangeparams.Scope = DICS_FLAG_GLOBAL; propchangeparams.HwProfile = 0; SetupDiSetClassInstallParams(info, ref devdata, ref propchangeparams, (UInt32)Marshal.SizeOf(propchangeparams)); CheckError("SetupDiSetClassInstallParams"); SetupDiChangeState( info, ref devdata); CheckError("SetupDiChangeState"); } finally { if (info != IntPtr.Zero) SetupDiDestroyDeviceInfoList(info); } } private static void CheckError(string message, int lasterror = -1) { int code = lasterror == -1 ? Marshal.GetLastWin32Error() : lasterror; if (code != 0) throw new ApplicationException( String.Format("Error disabling hardware device (Code {0}): {1}", code, message)); } private static string GetStringPropertyForDevice(IntPtr info, SP_DEVINFO_DATA devdata, DEVPROPKEY key) { uint proptype, outsize; IntPtr buffer = IntPtr.Zero; try { uint buflen = 512; buffer = Marshal.AllocHGlobal((int)buflen); SetupDiGetDevicePropertyW( info, ref devdata, ref key, out proptype, buffer, buflen, out outsize, 0); byte[] lbuffer = new byte[outsize]; Marshal.Copy(buffer, lbuffer, 0, (int)outsize); int errcode = Marshal.GetLastWin32Error(); if (errcode == ERROR_ELEMENT_NOT_FOUND) return null; CheckError("SetupDiGetDeviceProperty", errcode); return Encoding.Unicode.GetString(lbuffer); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } }
我已经构建了XP兼容的答案,并通过添加一个SafeDeviceInformationSetHandle
类并执行一些通用代码清理/重构来进一步改进,并将其添加到这里作为后代:
using System; using System.Text; using System.Security; using System.ComponentModel; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; public static class SetupApi { private const string SETUPAPI = "setupapi.dll"; private const int ERROR_INVALID_DATA = 13; private const int ERROR_INSUFFICIENT_BUFFER = 122; private class SafeDeviceInformationSetHandle : SafeHandleMinusOneIsInvalid { private SafeDeviceInformationSetHandle() : base(true) { } private SafeDeviceInformationSetHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) { SetHandle(preexistingHandle); } [SecurityCritical] protected override bool ReleaseHandle() { return SetupDiDestroyDeviceInfoList(handle); } } #region Enumerations [Flags] private enum DIGCF : uint { DEFAULT = 0x00000001, PRESENT = 0x00000002, ALLCLASSES = 0x00000004, PROFILE = 0x00000008, DEVICEINTERFACE = 0x00000010 } private enum SPDRP : uint { /// <summary> /// DeviceDesc (R/W) /// </summary> DEVICEDESC = 0x00000000, /// <summary> /// HardwareID (R/W) /// </summary> HARDWAREID = 0x00000001, /// <summary> /// CompatibleIDs (R/W) /// </summary> COMPATIBLEIDS = 0x00000002, /// <summary> /// unused /// </summary> UNUSED0 = 0x00000003, /// <summary> /// Service (R/W) /// </summary> SERVICE = 0x00000004, /// <summary> /// unused /// </summary> UNUSED1 = 0x00000005, /// <summary> /// unused /// </summary> UNUSED2 = 0x00000006, /// <summary> /// Class (R--tied to ClassGUID) /// </summary> CLASS = 0x00000007, /// <summary> /// ClassGUID (R/W) /// </summary> CLASSGUID = 0x00000008, /// <summary> /// Driver (R/W) /// </summary> DRIVER = 0x00000009, /// <summary> /// ConfigFlags (R/W) /// </summary> CONFIGFLAGS = 0x0000000A, /// <summary> /// Mfg (R/W) /// </summary> MFG = 0x0000000B, /// <summary> /// FriendlyName (R/W) /// </summary> FRIENDLYNAME = 0x0000000C, /// <summary> /// LocationInformation (R/W) /// </summary> LOCATION_INFORMATION = 0x0000000D, /// <summary> /// PhysicalDeviceObjectName (R) /// </summary> PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E, /// <summary> /// Capabilities (R) /// </summary> CAPABILITIES = 0x0000000F, /// <summary> /// UiNumber (R) /// </summary> UI_NUMBER = 0x00000010, /// <summary> /// UpperFilters (R/W) /// </summary> UPPERFILTERS = 0x00000011, /// <summary> /// LowerFilters (R/W) /// </summary> LOWERFILTERS = 0x00000012, /// <summary> /// BusTypeGUID (R) /// </summary> BUSTYPEGUID = 0x00000013, /// <summary> /// LegacyBusType (R) /// </summary> LEGACYBUSTYPE = 0x00000014, /// <summary> /// BusNumber (R) /// </summary> BUSNUMBER = 0x00000015, /// <summary> /// Enumerator Name (R) /// </summary> ENUMERATOR_NAME = 0x00000016, /// <summary> /// Security (R/W, binary form) /// </summary> SECURITY = 0x00000017, /// <summary> /// Security (W, SDS form) /// </summary> SECURITY_SDS = 0x00000018, /// <summary> /// Device Type (R/W) /// </summary> DEVTYPE = 0x00000019, /// <summary> /// Device is exclusive-access (R/W) /// </summary> EXCLUSIVE = 0x0000001A, /// <summary> /// Device Characteristics (R/W) /// </summary> CHARACTERISTICS = 0x0000001B, /// <summary> /// Device Address (R) /// </summary> ADDRESS = 0x0000001C, /// <summary> /// UiNumberDescFormat (R/W) /// </summary> UI_NUMBER_DESC_FORMAT = 0X0000001D, /// <summary> /// Device Power Data (R) /// </summary> DEVICE_POWER_DATA = 0x0000001E, /// <summary> /// Removal Policy (R) /// </summary> REMOVAL_POLICY = 0x0000001F, /// <summary> /// Hardware Removal Policy (R) /// </summary> REMOVAL_POLICY_HW_DEFAULT = 0x00000020, /// <summary> /// Removal Policy Override (RW) /// </summary> REMOVAL_POLICY_OVERRIDE = 0x00000021, /// <summary> /// Device Install State (R) /// </summary> INSTALL_STATE = 0x00000022, /// <summary> /// Device Location Paths (R) /// </summary> LOCATION_PATHS = 0x00000023, } private enum DIF : uint { SELECTDEVICE = 0x00000001, INSTALLDEVICE = 0x00000002, ASSIGNRESOURCES = 0x00000003, PROPERTIES = 0x00000004, REMOVE = 0x00000005, FIRSTTIMESETUP = 0x00000006, FOUNDDEVICE = 0x00000007, SELECTCLASSDRIVERS = 0x00000008, VALIDATECLASSDRIVERS = 0x00000009, INSTALLCLASSDRIVERS = 0x0000000A, CALCDISKSPACE = 0x0000000B, DESTROYPRIVATEDATA = 0x0000000C, VALIDATEDRIVER = 0x0000000D, DETECT = 0x0000000F, INSTALLWIZARD = 0x00000010, DESTROYWIZARDDATA = 0x00000011, PROPERTYCHANGE = 0x00000012, ENABLECLASS = 0x00000013, DETECTVERIFY = 0x00000014, INSTALLDEVICEFILES = 0x00000015, UNREMOVE = 0x00000016, SELECTBESTCOMPATDRV = 0x00000017, ALLOW_INSTALL = 0x00000018, REGISTERDEVICE = 0x00000019, NEWDEVICEWIZARD_PRESELECT = 0x0000001A, NEWDEVICEWIZARD_SELECT = 0x0000001B, NEWDEVICEWIZARD_PREANALYZE = 0x0000001C, NEWDEVICEWIZARD_POSTANALYZE = 0x0000001D, NEWDEVICEWIZARD_FINISHINSTALL = 0x0000001E, UNUSED1 = 0x0000001F, INSTALLINTERFACES = 0x00000020, DETECTCANCEL = 0x00000021, REGISTER_COINSTALLERS = 0x00000022, ADDPROPERTYPAGE_ADVANCED = 0x00000023, ADDPROPERTYPAGE_BASIC = 0x00000024, RESERVED1 = 0x00000025, TROUBLESHOOTER = 0x00000026, POWERMESSAGEWAKE = 0x00000027, ADDREMOTEPROPERTYPAGE_ADVANCED = 0x00000028, UPDATEDRIVER_UI = 0x00000029, FINISHINSTALL_ACTION = 0x0000002A, RESERVED2 = 0x00000030, } private enum DICS : uint { ENABLE = 0x00000001, DISABLE = 0x00000002, PROPCHANGE = 0x00000003, START = 0x00000004, STOP = 0x00000005, } [Flags] private enum DICS_FLAG : uint { GLOBAL = 0x00000001, CONFIGSPECIFIC = 0x00000002, CONFIGGENERAL = 0x00000004, } #endregion #region Structures [StructLayout(LayoutKind.Sequential)] private struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid ClassGuid; public UInt32 DevInst; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential)] private struct SP_CLASSINSTALL_HEADER { public UInt32 cbSize; public DIF InstallFunction; } [StructLayout(LayoutKind.Sequential)] private struct SP_PROPCHANGE_PARAMS { public SP_CLASSINSTALL_HEADER ClassInstallHeader; public DICS StateChange; public DICS_FLAG Scope; public UInt32 HwProfile; } #endregion #region P/Invoke Functions [DllImport(SETUPAPI, SetLastError = true, CharSet = CharSet.Unicode)] private static extern SafeDeviceInformationSetHandle SetupDiGetClassDevs( [In] ref Guid ClassGuid, [In] string Enumerator, IntPtr hwndParent, DIGCF Flags ); [DllImport(SETUPAPI, SetLastError = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); [DllImport(SETUPAPI, SetLastError = true)] private static extern bool SetupDiEnumDeviceInfo( SafeDeviceInformationSetHandle DeviceInfoSet, UInt32 MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData ); [DllImport(SETUPAPI, SetLastError = true)] private static extern bool SetupDiSetClassInstallParams( SafeDeviceInformationSetHandle DeviceInfoSet, [In] ref SP_DEVINFO_DATA deviceInfoData, [In] ref SP_PROPCHANGE_PARAMS classInstallParams, UInt32 ClassInstallParamsSize ); [DllImport(SETUPAPI, SetLastError = true)] private static extern bool SetupDiChangeState( SafeDeviceInformationSetHandle DeviceInfoSet, [In, Out] ref SP_DEVINFO_DATA DeviceInfoData ); [DllImport(SETUPAPI, SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool SetupDiGetDeviceRegistryProperty( SafeDeviceInformationSetHandle DeviceInfoSet, [In] ref SP_DEVINFO_DATA DeviceInfoData, SPDRP Property, out RegistryValueKind PropertyRegDataType, [Out] byte[] PropertyBuffer, UInt32 PropertyBufferSize, out UInt32 RequiredSize ); #endregion private static void CheckWin32CallSuccess(bool success) { if (!success) { throw new Win32Exception(); } } private static string GetStringPropertyForDevice(SafeDeviceInformationSetHandle infoSet, ref SP_DEVINFO_DATA devInfo, SPDRP property) { RegistryValueKind regType; UInt32 requiredSize; if (!SetupDiGetDeviceRegistryProperty(infoSet, ref devInfo, property, out regType, null, 0, out requiredSize)) { switch (Marshal.GetLastWin32Error()) { case ERROR_INSUFFICIENT_BUFFER: break; case ERROR_INVALID_DATA: return string.Empty; default: throw new Win32Exception(); } } byte[] propertyBuffer = new byte[requiredSize]; CheckWin32CallSuccess(SetupDiGetDeviceRegistryProperty(infoSet, ref devInfo, property, out regType, propertyBuffer, (uint)propertyBuffer.Length, out requiredSize)); return Encoding.Unicode.GetString(propertyBuffer); } public static void EnableDevice(Func<string, bool> hardwareIdFilter, bool enable) { Guid nullGuid = Guid.Empty; using (SafeDeviceInformationSetHandle infoSet = SetupDiGetClassDevs(ref nullGuid, null, IntPtr.Zero, DIGCF.ALLCLASSES)) { CheckWin32CallSuccess(!infoSet.IsInvalid); SP_DEVINFO_DATA devInfo = new SP_DEVINFO_DATA(); devInfo.cbSize = (UInt32) Marshal.SizeOf(devInfo); for (uint index = 0; ; ++index) { CheckWin32CallSuccess(SetupDiEnumDeviceInfo(infoSet, index, ref devInfo)); string hardwareId = GetStringPropertyForDevice(infoSet, ref devInfo, SPDRP.HARDWAREID); if ((!string.IsNullOrEmpty(hardwareId)) && (hardwareIdFilter(hardwareId))) { break; } } SP_CLASSINSTALL_HEADER classinstallHeader = new SP_CLASSINSTALL_HEADER(); classinstallHeader.cbSize = (UInt32) Marshal.SizeOf(classinstallHeader); classinstallHeader.InstallFunction = DIF.PROPERTYCHANGE; SP_PROPCHANGE_PARAMS propchangeParams = new SP_PROPCHANGE_PARAMS { ClassInstallHeader = classinstallHeader, StateChange = enable ? DICS.ENABLE : DICS.DISABLE, Scope = DICS_FLAG.GLOBAL, HwProfile = 0, }; CheckWin32CallSuccess(SetupDiSetClassInstallParams(infoSet, ref devInfo, ref propchangeParams, (UInt32)Marshal.SizeOf(propchangeParams))); CheckWin32CallSuccess(SetupDiChangeState(infoSet, ref devInfo)); } } }
可以在Windows安装程序API上使用P / Invoke方法完成。 自W2K以来,API函数已经在Windows中。 API调用可能需要管理权限。 以下是使用这些API禁用(以及启用)C#中的设备的一些粗略代码,它允许调用:
DisableDevice( n => n.ToUpperInvariant().Contains("VID_3F20&PID_8A1D"), true); // true disables the device, false enables it
这适用于Dell Inspi 15上的Windows 10。
我设法解决这个问题使用DevManView.exe(免费):
下载DevManView.exe并将.exe文件放在某处: http ://www.nirsoft.net/utils/device_manager_view.html
转到设备管理器并搜索要启用/禁用的设备的名称。
在C#中,创建并启动一个用于禁用设备的新进程(使用在设备管理器中找到的设备的名称)。
Process devManViewProc = new Process(); devManViewProc.StartInfo.FileName = @"<path to DevManView.exe>\DevManView.exe"; devManViewProc.StartInfo.Arguments = "/disable \"<name of the device>\""; devManViewProc.Start(); devManViewProc.WaitForExit();
并再次启用它。
devManViewProc.StartInfo.Arguments = "/enable \"<name of the device>\""; devManViewProc.Start(); devManViewProc.WaitForExit();