C# 如何以编程方式禁用系统设备?

C# 如何以编程方式禁用系统设备?,c#,.net,windows,64-bit,device,C#,.net,Windows,64 Bit,Device,我正在寻找在给定PID&VID或设备名称的情况下在C#NET中禁用系统设备(USB或内部)的方法 搜索后,我在CodeProject上找到了 但是我需要一些能在XP、Vista和Windows 7(x86和x64操作系统)上运行的东西。我链接的项目只适用于XP和Vista x86……即使在以管理员权限运行应用程序时。 有人知道一种可以在所有操作系统上运行的解决方案吗?可以在Windows安装API上使用p/Invoke方法来完成。API函数自W2K以来一直在Windows中。API调用可能需要管

我正在寻找在给定PID&VID或设备名称的情况下在C#NET中禁用系统设备(USB或内部)的方法

搜索后,我在CodeProject上找到了

但是我需要一些能在XP、Vista和Windows 7(x86和x64操作系统)上运行的东西。我链接的项目只适用于XP和Vista x86……即使在以管理员权限运行应用程序时。


有人知道一种可以在所有操作系统上运行的解决方案吗?

可以在Windows安装API上使用p/Invoke方法来完成。API函数自W2K以来一直在Windows中。API调用可能需要管理权限。下面是一些使用这些API禁用(以及启用)C#中允许调用的设备的粗略代码:

  DisableDevice(
        n => n.ToUpperInvariant().Contains("VID_3F20&PID_8A1D"),
        true); // true disables the device, false enables it
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);
    }
}
}
公共静态类禁用硬件{
consuint DIF_PROPERTYCHANGE=0x12;
consuint DICS_ENABLE=1;
consuint DICS_DISABLE=2;//禁用设备
const uint DICS\u FLAG\u GLOBAL=1;//不特定于配置文件
consuint DIGCF_ALLCLASSES=4;
存在的常数=2;
consuint ERROR\u NO\u MORE\u ITEMS=259;
常量错误元素未找到=1168;
静态DEVPROPKEY DEVPKEY_设备_设备DESC;
静态DEVPROPKEY DEVPKEY_设备_硬件;
[StructLayout(LayoutKind.Sequential)]
结构SP_CLASSINSTALL_标头
{
公共UInt32 cbSize;
公共UInt32安装功能;
}
[StructLayout(LayoutKind.Sequential)]
结构SP_PROPCHANGE_参数
{
公共SP_CLASSINSTALL_头ClassInstallHeader;
公共UInt32状态更改;
公共UInt32范围;
公共UInt32 HWT配置文件;
}
[StructLayout(LayoutKind.Sequential)]
结构SP_设备信息_数据
{
公共UInt32 cbSize;
公共Guid类Guid;
公共UInt32设备;
公共UInt32保留;
}
[StructLayout(LayoutKind.Sequential)]
结构DEVPROPKEY
{
公共指南fmtid;
公共UInt32 pid;
}
[DllImport(“setupapi.dll”,SetLastError=true)]
静态外部IntPtr SetupDiGetClassDevsW(
[In]参考Guid类Guid,
[Marshallas(UnmanagedType.LPWStr)]
字符串枚举器,
IntPtr父级,
UInt32旗);
[DllImport(“setupapi.dll”,SetLastError=true)]
静态外部布尔设置DiDestroyDeviceInfo列表(IntPtr句柄);
[DllImport(“setupapi.dll”,SetLastError=true)]
静态外部布尔设置DienumDeviceInfo(IntPtr设备信息集,
UInt32成员索引,
[输出]输出SP_设备信息(数据设备信息数据);
[DllImport(“setupapi.dll”,SetLastError=true)]
静态外部布尔设置DisetClassInstallParams(
IntPtr设备信息集,
[In]参考SP_设备信息数据设备信息数据,
[In]参考SP_PROPCHANGE_参数classInstallParams,
UInt32 ClassInstallParamsSize);
[DllImport(“setupapi.dll”,SetLastError=true)]
静态外部布尔设置状态(
IntPtr设备信息集,
[In]参考SP_设备信息(数据设备信息数据);
[DllImport(“setupapi.dll”,SetLastError=true)]
静态外部布尔设置DiGetDevicePropertyW(
IntPtr设备信息集,
[In]参考SP_设备信息数据设备信息数据,
[In]参考DEVPROPKEY propertyKey,
[Out]Out UInt32属性类型,
IntPtr propertyBuffer,
UInt32属性缓冲大小,
out UInt32所需尺寸,
UInt32旗);
静态禁用硬件()
{
DisableHardware.DEVPKEY_Device_DeviceDesc=new DEVPROPKEY();
DEVPKEY\u Device\u DeviceDesc.fmtid=新Guid(
0xa45c254e、0xdf1c、0x4efd、0x80、0x20、0x67、,
0xd1、0x46、0xa8、0x50、0xe0);
DEVPKEY\u Device\u DeviceDesc.pid=2;
DEVPKEY_Device_HardwareIds=新DEVPROPKEY();
DEVPKEY\u Device\u HardwareIds.fmtid=新Guid(
0xa45c254e、0xdf1c、0x4efd、0x80、0x20、0x67、,
0xd1、0x46、0xa8、0x50、0xe0);
DEVPKEY\u Device\u HardwareIds.pid=3;
}
公共静态无效禁用设备(Func筛选器,bool disable=true)
{
IntPtr info=IntPtr.Zero;
Guid NullGuid=Guid.Empty;
尝试
{
info=SetupDiGetClassDevsW(
ref NullGuid,
无效的
IntPtr.Zero,
DIGCF_(所有类别);
检查错误(“SetupDiGetClassDevs”);
SP_DEVINFO_DATA devdata=新SP_DEVINFO_DATA();
devdata.cbSize=(UInt32)Marshal.SizeOf(devdata);
//获取与设备条件匹配的第一个设备。
对于(uint i=0;i++)
{
SetupDiEnumDeviceInfo(信息、,
我
输出数据);
//如果没有与筛选器匹配的项目,则抛出
if(Marshal.GetLastWin32Error()==错误\u无\u更多\u项)
检查错误(“未找到与筛选器匹配的设备。”,0xcffff);
检查错误(“SetupDiEnumDeviceInfo”);
string devicepath=GetStringPropertyForDevice(信息,
devdata、DEVPKEY_设备_硬件);
//取消对打印名称/路径的注释
//Console.WriteLine(GetStringPropertyForDevice)(信息,
//devdata、DEVPKEY_设备_设备(ESC));
//Console.WriteLine(“{0}”,devicepath);
如果(devicepath!=null&&filter(devicepath))中断;
}
SP_CLASSINSTALL_标头=新SP_CLASSINSTALL_标头();
header.cbSize=(UInt32)Marshal.SizeOf(header);
header.InstallFunction=DIF_PROPERTYCHANGE;
SP_PROPCHANGE_PARAMS propchangeparams=新的SP_PROPCHANGE_PARAMS();
propchangeparams.ClassInstallHeader=标题;
propchangeparams.StateChange=禁用?DICS_禁用:DICS_启用;
propchangeparams.Scope=DICS_标志_全局;
propchangeparams.HwProfile=0;
SetupDiSetClassInstallParams(信息,
参考devdata,
参考propchangeparams,
(UInt32)SizeOf元帅(propchangeparams);
检查错误(“SetupDiSetClassInstallParams”);
塞图
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));
        }
    }
}
DisableDevice(
    n => n.ToUpperInvariant().Contains("VID_3F20&PID_8A1D"),
    true); // true disables the device, false enables it
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();
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!");
}