2010-11-04 15 views
9

Estoy buscando la forma de desactivar un dispositivo del sistema (ya sea USB o interno) en C# .NET dado el PID & VID o el nombre del dispositivo.¿Cómo desactivo un dispositivo de sistema programáticamente?

Después de buscar encontré Hardware Helper Library for C# en CodeProject.

Pero necesito algo que funcione en XP, Vista & Windows 7 (ambos sistemas operativos x86 y x64) ... el proyecto que he vinculado solo funciona con XP y Vista x86 ... incluso cuando se ejecuta la aplicación con privilegios de administrador.

¿Alguien sabe de una solución que funcionaría en todos los sistemas operativos?

Respuesta

23

Parece que hay dos cosas en la versión de drf que le están causando problemas. Su problema x64 fue causado por SP_DEVINFO_DATA que tenía un error donde se necesitaba un IntPtr. El segundo es que la función SetupDiGetDevicePropertyW es Vista + y no se ejecutará en XP.

Aquí hay una versión con esas dos cuestiones corregidas. Probé como x86 y AnyCPU en XPx86 y Win7X64.

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); 
     } 
    } 

} 
+0

Gracias, esto funciona perfectamente (creo). – Cheetah

+0

+1 impresionante ejemplo de trabajo! – BradleyDotNET

+0

¿SetupDiGetDeviceProperty simplemente no funciona desde .NET? Siempre obtengo el error 87, aunque en C++ haciendo lo mismo, con los mismos parámetros funciona bien. Pensé que tal vez un problema de declaración de DLLImport, ya que una diferencia extraña que vi fue que los parámetros de orden que se enviaron a la pila eran diferentes en .NET que en C++. Pero tenía exactamente la misma declaración para la importación que este código aquí (y probé varios ajustes). – Malaise

8

Se puede hacer utilizando los métodos P/Invoke en la API de instalación de Windows. Las funciones de API han estado en Windows desde W2K. Las llamadas API pueden requerir derechos administrativos. A continuación se muestra un código en bruto para el uso de estas API para desactivar (así como habilitar) dispositivos en C#, que permiten invocando:

DisableDevice(
     n => n.ToUpperInvariant().Contains("VID_3F20&PID_8A1D"), 
     true); // true disables the device, false enables it 

El primer parámetro es un filtro que se pasa el ID de hardware. Esto desactiva o habilita el primer dispositivo que coincide con el filtro provisto. No hay efecto si el dispositivo ya está en el estado objetivo.

El código sigue.

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); 
    } 
} 
} 
+0

Si bien esto funciona, no puedo compilar para 'Cualquier CPU' y debe compilar para x86. Requiere privilegios de administrador. Gracias, si no hay respuestas que solucionen la cuestión de "Cualquier CPU", te daré la recompensa. – Cheetah

+0

Hola drf, estoy tratando de usar este código en .NET 2.0, ¿me puedes ayudar a traducir la función 'Func', supongo que significa 'devicepath.Contains (vid)'? ¿Es esto correcto? Gracias –

+0

@Chibueze El parámetro 'System.Func ' en DisableDevice es un predicado donde el primer dispositivo enumerado con un nombre que coincide con el predicado está deshabilitado. Si conoce el nombre del dispositivo cuando se llama al método, el tipo de parámetro de filtro se puede refactorizar con una cadena (por ejemplo, la firma de la función se convierte en 'void DisableDevice (Func filter, bool disable = true)'), y el segmento 'filter (devicepath)' reemplazado por 'devicepath.ToUpperInvariant() == filter.ToUpperInvariant()'. En .NET 2, también podría usar un 'delegado (cadena)' en lugar de una función lambda para el predicado. – drf

1

He construido sobre la respuesta compatible con XP y mejoró un poco mediante la adición de una clase SafeDeviceInformationSetHandle y la realización de algún código de limpieza/refactorización en general, y estoy añadiendo aquí para la posteridad:

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)); 
     } 
    } 
} 
0

Se puede hacer utilizando los métodos P/Invoke en la API de instalación de Windows. Las funciones de API han estado en Windows desde W2K. Las llamadas API pueden requerir derechos administrativos. A continuación se muestra un poco de código en bruto para el uso de estas API para desactivar (así como habilitar) dispositivos en C#, que permiten la invocación:

DisableDevice(
    n => n.ToUpperInvariant().Contains("VID_3F20&PID_8A1D"), 
    true); // true disables the device, false enables it 

Esto funciona en Windows 10 en Dell inspi 15.

0

logré resolver este problema usando DevManView.exe (freeware):

  1. Descargar DevManView.exe y poner el archivo .exe en alguna parte: http://www.nirsoft.net/utils/device_manager_view.html

  2. Vaya a su Administrador de Dispositivos y busque el Nombre del dispositivo que desea habilitar/deshabilitar.

  3. En C#, cree e inicie un nuevo proceso para deshabilitar el dispositivo (usando el nombre del dispositivo que encontró en el administrador del dispositivo).

    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(); 
    
  4. y habilitarlo de nuevo.

    devManViewProc.StartInfo.Arguments = "/enable \"<name of the device>\""; 
    devManViewProc.Start(); 
    devManViewProc.WaitForExit(); 
    
Cuestiones relacionadas