我正在寻找在C#.NET中禁用系统设备(USB或内部)的方法,无论是PID还是PID。 VID或设备名称。
搜索后,我在CodeProject上找到Hardware Helper Library for C#。
但是我需要能在XP,Vista和iPad上运行的东西。 Windows 7(x86和x64操作系统)...... 我链接的项目仅适用于XP和Vista x86 ......即使以管理员权限运行应用程序也是如此。
有没有人知道可以在所有操作系统上运行的解决方案?
答案 0 :(得分:24)
看起来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);
}
}
}
答案 1 :(得分:8)
可以使用Windows Setup 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);
}
}
}
答案 2 :(得分:1)
我已经建立了与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));
}
}
}
答案 3 :(得分:0)
可以使用Windows Setup 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
这适用于戴尔Inspi 15上的Windows 10。
答案 4 :(得分:0)
我设法使用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();
答案 5 :(得分:0)
我正在使用devcon.exe解决此问题。 使用以下代码:
public class DevconHelper
{
private readonly ILogger logger;
public DevconHelper(ILogger logger)
{
this.logger = logger;
}
readonly static string devconPath = @"devcon\" + (Environment.Is64BitOperatingSystem ? "x64" : "x86") + @"\devcon.exe";
readonly static Regex parseHwidsOutput = new Regex(@"(?<id>[^\n]+)\n {4}Name: (?<name>[^\n]+)\n {4}Hardware IDs:\n(?<hwids>(?: {8}[^\n]+\n?)+)");
readonly static Regex parseEnableDisableOutput = new Regex(@"(\d+) device\(s\) (are enabled|disabled)\.");
public async Task<IEnumerable<Device>> GetDevicesAsync(string filterString = "*")
{
logger.Trace("GetDevicesAsync");
using (var listDevicesProcess = Process.Start(new ProcessStartInfo(devconPath, "hwids " + filterString) { RedirectStandardOutput = true, UseShellExecute = false }))
{
var content = await listDevicesProcess.StandardOutput.ReadToEndAsync();
var matches = parseHwidsOutput.Matches(content.Replace(Environment.NewLine, "\n")); //Regex is based on \n
logger.Trace("GetDevicesAsync process output: {Content}, parsed {NumberOfMatches}, devconPath: {DevconPath}", content, matches.Count, devconPath);
return matches.OfType<Match>().Select(match =>
{
var id = match.Groups["id"].Value;
var name = match.Groups["name"].Value;
var hwids = match.Groups["hwids"].Value.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(line => line.Trim());
return new Device() { Id = id, Name = name, HardwareIds = hwids.ToArray() };
});
}
}
public async Task<bool> EnableAsync(Device device)
{
logger.Trace("EnableAsync");
using (var disableProcess = Process.Start(new ProcessStartInfo(devconPath, "enable " + device.HardwareIds.First()) { RedirectStandardOutput = true, UseShellExecute = false }))
{
var content = await disableProcess.StandardOutput.ReadToEndAsync();
var lastLine = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Last();
logger.Trace("EnableAsync process output: {Content}, LastLine: {LastLine}", content, lastLine);
return parseEnableDisableOutput.IsMatch(lastLine);
}
}
public async Task<bool> DisableAsync(Device device)
{
logger.Trace("DisableAsync");
using (var disableProcess = Process.Start(new ProcessStartInfo(devconPath, "disable " + device.HardwareIds.First()) { RedirectStandardOutput = true, UseShellExecute = false }))
{
var content = await disableProcess.StandardOutput.ReadToEndAsync();
var lastLine = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Last();
logger.Trace("DisableAsync process output: {Content}, LastLine: {LastLine}", content, lastLine);
return parseEnableDisableOutput.IsMatch(lastLine);
}
}
public class Device
{
public string Id { get; set; }
public string Name { get; set; }
public string[] HardwareIds { get; set; }
}
}
然后您可以像这样使用它。
var devices = await devconHelper.GetDevicesAsync();
var device = devices.FirstOrDefault(x => x.Name == Settings.GPSDeviceName);
if (device != null)
{
logger.Trace("Found the device!");
logger.Info("Disabling the device!");
if (await devconHelper.DisableAsync(device))
{
logger.Info("GPS device has been disabled!");
}
else
{
logger.Warn("Failed to disable the device!");
}
await Task.Delay(1000);
logger.Info("Enabling device!");
if (await devconHelper.EnableAsync(device))
{
logger.Info("Device has been enabled!");
}
else
{
logger.Fatal("Failed to enable the device!");
}
}
else
{
logger.Warn("Could not find the device!");
}
这已在Windows 10和8.1上经过测试,可以正常使用!