我正在寻找在给定PID和VID或设备名称的情况下在C#.NET中禁用系统设备(USB或内部)的方法。
搜索后,我在CodeProject上找到了用于C#的硬件助手库。
但是我需要在XP,Vista和Windows 7(x86和x64操作系统)上都可以使用的东西… 我链接的项目仅在XP和Vista x86上可以使用…即使以管理员权限运行应用程序也是如此。
有谁知道可以在所有操作系统上使用的解决方案?
看起来drf版本中有两件事给您带来麻烦。您的x64问题是由SP_DEVINFO_DATA的uint需要IntPtr引起的。第二个问题是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); } } }