2017-09-14 6 views

Répondre

0

Compris moi-même avec une combinaison d'autres codes contributeurs.

Référence: Win32 API function to programmatically enable/disable device

principal codebase ci-dessous:

using Microsoft.Win32.SafeHandles; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Runtime.ConstrainedExecution; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Text; 

namespace WindowsStorageManagementAPI.Devices 
{ 
    public class DeviceInfoData 
    { 
     public int Size { get; set; } 
     public Guid ClassGuid { get; set; } 
     public int DevInst { get; set; } 
     public IntPtr Reserved { get; set; } 
    } 

    public class SetupApiWrapper 
    { 
     private const string SetupAPI = "setupapi.dll"; 
     private const string NewDevLib = "Newdev.dll"; 

     #region NATIVE ENUMS 
     [Flags()] 
     private enum SetupDiGetClassDevsFlags 
     { 
      Default = 1, 
      Present = 2, 
      AllClasses = (int)0x04, 
      Profile = 8, 
      DeviceInterface = (int)0x10 
     } 

     private enum DiFunction 
     { 
      SelectDevice = 1, 
      InstallDevice = 2, 
      AssignResources = 3, 
      Properties = 4, 
      Remove = 5, 
      FirstTimeSetup = 6, 
      FoundDevice = 7, 
      SelectClassDrivers = 8, 
      ValidateClassDrivers = 9, 
      InstallClassDrivers = (int)0xa, 
      CalcDiskSpace = (int)0xb, 
      DestroyPrivateData = (int)0xc, 
      ValidateDriver = (int)0xd, 
      Detect = (int)0xf, 
      InstallWizard = (int)0x10, 
      DestroyWizardData = (int)0x11, 
      PropertyChange = (int)0x12, 
      EnableClass = (int)0x13, 
      DetectVerify = (int)0x14, 
      InstallDeviceFiles = (int)0x15, 
      UnRemove = (int)0x16, 
      SelectBestCompatDrv = (int)0x17, 
      AllowInstall = (int)0x18, 
      RegisterDevice = (int)0x19, 
      NewDeviceWizardPreSelect = (int)0x1a, 
      NewDeviceWizardSelect = (int)0x1b, 
      NewDeviceWizardPreAnalyze = (int)0x1c, 
      NewDeviceWizardPostAnalyze = (int)0x1d, 
      NewDeviceWizardFinishInstall = (int)0x1e, 
      Unused1 = (int)0x1f, 
      InstallInterfaces = (int)0x20, 
      DetectCancel = (int)0x21, 
      RegisterCoInstallers = (int)0x22, 
      AddPropertyPageAdvanced = (int)0x23, 
      AddPropertyPageBasic = (int)0x24, 
      Reserved1 = (int)0x25, 
      Troubleshooter = (int)0x26, 
      PowerMessageWake = (int)0x27, 
      AddRemotePropertyPageAdvanced = (int)0x28, 
      UpdateDriverUI = (int)0x29, 
      Reserved2 = (int)0x30 
     } 

     private enum StateChangeAction 
     { 
      Enable = 1, 
      Disable = 2, 
      PropChange = 3, 
      Start = 4, 
      Stop = 5 
     } 

     [Flags()] 
     private enum Scope 
     { 
      Global = 1, 
      ConfigSpecific = 2, 
      ConfigGeneral = 4 
     } 

     private enum SetupApiError 
     { 
      NoAssociatedClass = unchecked((int)0xe0000200), 
      ClassMismatch = unchecked((int)0xe0000201), 
      DuplicateFound = unchecked((int)0xe0000202), 
      NoDriverSelected = unchecked((int)0xe0000203), 
      KeyDoesNotExist = unchecked((int)0xe0000204), 
      InvalidDevinstName = unchecked((int)0xe0000205), 
      InvalidClass = unchecked((int)0xe0000206), 
      DevinstAlreadyExists = unchecked((int)0xe0000207), 
      DevinfoNotRegistered = unchecked((int)0xe0000208), 
      InvalidRegProperty = unchecked((int)0xe0000209), 
      NoInf = unchecked((int)0xe000020a), 
      NoSuchHDevinst = unchecked((int)0xe000020b), 
      CantLoadClassIcon = unchecked((int)0xe000020c), 
      InvalidClassInstaller = unchecked((int)0xe000020d), 
      DiDoDefault = unchecked((int)0xe000020e), 
      DiNoFileCopy = unchecked((int)0xe000020f), 
      InvalidHwProfile = unchecked((int)0xe0000210), 
      NoDeviceSelected = unchecked((int)0xe0000211), 
      DevinfolistLocked = unchecked((int)0xe0000212), 
      DevinfodataLocked = unchecked((int)0xe0000213), 
      DiBadPath = unchecked((int)0xe0000214), 
      NoClassInstallParams = unchecked((int)0xe0000215), 
      FileQueueLocked = unchecked((int)0xe0000216), 
      BadServiceInstallSect = unchecked((int)0xe0000217), 
      NoClassDriverList = unchecked((int)0xe0000218), 
      NoAssociatedService = unchecked((int)0xe0000219), 
      NoDefaultDeviceInterface = unchecked((int)0xe000021a), 
      DeviceInterfaceActive = unchecked((int)0xe000021b), 
      DeviceInterfaceRemoved = unchecked((int)0xe000021c), 
      BadInterfaceInstallSect = unchecked((int)0xe000021d), 
      NoSuchInterfaceClass = unchecked((int)0xe000021e), 
      InvalidReferenceString = unchecked((int)0xe000021f), 
      InvalidMachineName = unchecked((int)0xe0000220), 
      RemoteCommFailure = unchecked((int)0xe0000221), 
      MachineUnavailable = unchecked((int)0xe0000222), 
      NoConfigMgrServices = unchecked((int)0xe0000223), 
      InvalidPropPageProvider = unchecked((int)0xe0000224), 
      NoSuchDeviceInterface = unchecked((int)0xe0000225), 
      DiPostProcessingRequired = unchecked((int)0xe0000226), 
      InvalidCOInstaller = unchecked((int)0xe0000227), 
      NoCompatDrivers = unchecked((int)0xe0000228), 
      NoDeviceIcon = unchecked((int)0xe0000229), 
      InvalidInfLogConfig = unchecked((int)0xe000022a), 
      DiDontInstall = unchecked((int)0xe000022b), 
      InvalidFilterDriver = unchecked((int)0xe000022c), 
      NonWindowsNTDriver = unchecked((int)0xe000022d), 
      NonWindowsDriver = unchecked((int)0xe000022e), 
      NoCatalogForOemInf = unchecked((int)0xe000022f), 
      DevInstallQueueNonNative = unchecked((int)0xe0000230), 
      NotDisableable = unchecked((int)0xe0000231), 
      CantRemoveDevinst = unchecked((int)0xe0000232), 
      InvalidTarget = unchecked((int)0xe0000233), 
      DriverNonNative = unchecked((int)0xe0000234), 
      InWow64 = unchecked((int)0xe0000235), 
      SetSystemRestorePoint = unchecked((int)0xe0000236), 
      IncorrectlyCopiedInf = unchecked((int)0xe0000237), 
      SceDisabled = unchecked((int)0xe0000238), 
      UnknownException = unchecked((int)0xe0000239), 
      PnpRegistryError = unchecked((int)0xe000023a), 
      RemoteRequestUnsupported = unchecked((int)0xe000023b), 
      NotAnInstalledOemInf = unchecked((int)0xe000023c), 
      InfInUseByDevices = unchecked((int)0xe000023d), 
      DiFunctionObsolete = unchecked((int)0xe000023e), 
      NoAuthenticodeCatalog = unchecked((int)0xe000023f), 
      AuthenticodeDisallowed = unchecked((int)0xe0000240), 
      AuthenticodeTrustedPublisher = unchecked((int)0xe0000241), 
      AuthenticodeTrustNotEstablished = unchecked((int)0xe0000242), 
      AuthenticodePublisherNotTrusted = unchecked((int)0xe0000243), 
      SignatureOSAttributeMismatch = unchecked((int)0xe0000244), 
      OnlyValidateViaAuthenticode = unchecked((int)0xe0000245), 
      NoMoreItems = unchecked((int)0xe0000259), 
      ElementNotFound = unchecked((int)0xe0001168), 
      InvalidData = unchecked((int)0xe0000013), 
     } 
     #endregion 

     #region NATIVE STRUCTS 
     [StructLayout(LayoutKind.Sequential)] 
     private struct DeviceInfoDataNative 
     { 
      public int Size; 
      public Guid ClassGuid; 
      public int DeviceInstance; 
      public IntPtr Reserved; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct ClassInstallHeader 
     { 
      public int Size; 
      public DiFunction InstallFunction; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct PropertyChangeParameters 
     { 
      public ClassInstallHeader ClassInstallHeader; 

      public StateChangeAction StateChange; 
      public Scope Scope; 
      public int HwProfile; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct RemoveDeviceParameters 
     { 
      public ClassInstallHeader ClassInstallHeader; 
      public Scope Scope; 
      public int HwProfile; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct DevicePropertyKey 
     { 
      public Guid fmtId; 
      public int pId; 

      // from devpkey.h 
      public static readonly DevicePropertyKey Device_Parent = new DevicePropertyKey { fmtId = new Guid("{4340A6C5-93FA-4706-972C-7B648008A5A7}"), pId = 8 }; 
      public static readonly DevicePropertyKey Device_Children = new DevicePropertyKey { fmtId = new Guid("{4340A6C5-93FA-4706-972C-7B648008A5A7}"), pId = 9 }; 
     } 
     #endregion 

     #region P/INVOKE 
     [SuppressUnmanagedCodeSecurity()] 
     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
     [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet); 

     [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool SetupDiCallClassInstaller(DiFunction installFunction, SafeDeviceInfoSetHandle deviceInfoSet, [In()] ref DeviceInfoDataNative deviceInfoData); 

     [DllImport(SetupAPI, SetLastError = true)] 
     private static extern bool SetupDiEnumDeviceInfo(SafeDeviceInfoSetHandle DeviceInfoSet, int MemberIndex, ref DeviceInfoDataNative DeviceInfoData); 

     [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)] 
     private static extern SafeDeviceInfoSetHandle SetupDiGetClassDevs(ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr HwndParent, SetupDiGetClassDevsFlags Flags); 

     [DllImport(SetupAPI, SetLastError = true, CharSet = CharSet.Auto)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool SetupDiGetDeviceInstanceId(IntPtr deviceInfoSet, ref DeviceInfoDataNative did, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder DeviceInstanceId, int DeviceInstanceIdSize, out int RequiredSize); 

     [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool SetupDiSetClassInstallParams(SafeDeviceInfoSetHandle deviceInfoSet, [In()] ref DeviceInfoDataNative deviceInfoData, [In()] ref RemoveDeviceParameters classInstallParams, int classInstallParamsSize); 

     [DllImport("Newdev.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool DiUninstallDevice(IntPtr hwnd, [In()] SafeDeviceInfoSetHandle deviceInfoSet, [In()] ref DeviceInfoDataNative deviceInfoData, [In()] int flags, out bool NeedReboot); 

     [DllImport(SetupAPI, SetLastError = true, EntryPoint = "SetupDiGetDevicePropertyW")] 
     private static extern bool SetupDiGetDeviceProperty(SafeDeviceInfoSetHandle deviceInfoSet, ref DeviceInfoDataNative DeviceInfoData, ref DevicePropertyKey propertyKey, out int propertyType, IntPtr propertyBuffer, int propertyBufferSize, out int requiredSize, int flags); 
     #endregion 

     private class SafeDeviceInfoSetHandle : SafeHandleZeroOrMinusOneIsInvalid 
     { 

      private SafeDeviceInfoSetHandle() : base(true) 
      { 
      } 

      protected override bool ReleaseHandle() 
      { 
       return SetupDiDestroyDeviceInfoList(this.handle); 
      } 
     } 

     private static DeviceInfoDataNative GetDeviceInfoData(SafeDeviceInfoSetHandle handle) 
     { 
      DeviceInfoDataNative _data = new DeviceInfoDataNative(); 

      _data.Size = Marshal.SizeOf(_data); 

      if (!SetupDiEnumDeviceInfo(handle, 0, ref _data)) 
      { 
       int error = Marshal.GetLastWin32Error(); 

       if (error == (int)SetupApiError.NoMoreItems)          
        return _data; 

       throw new Win32Exception(error); 
      } 

      return _data; 
     } 

     private static DeviceInfoDataNative[] GetDevicesInfoData(SafeDeviceInfoSetHandle handle) 
     { 
      List<DeviceInfoDataNative> _data = new List<DeviceInfoDataNative>(); 
      DeviceInfoDataNative deviceInfoData = new DeviceInfoDataNative(); 

      int index = 0; 
      int deviceInfoDataSize = Marshal.SizeOf(deviceInfoData); 

      deviceInfoData.Size = deviceInfoDataSize; 

      while (SetupDiEnumDeviceInfo(handle, index, ref deviceInfoData)) 
      { 
       _data.Add(deviceInfoData); 
       index += 1; 
       deviceInfoData = new DeviceInfoDataNative(); 
       deviceInfoData.Size = deviceInfoDataSize; 
      } 

      return _data.ToArray(); 
     } 

     private static int GetIndexOfInstance(SafeDeviceInfoSetHandle handle, DeviceInfoDataNative[] diData, string instanceId) 
     { 
      const int ERROR_INSUFFICIENT_BUFFER = 122; 
      for (int index = 0; index <= diData.Length - 1; index++) 
      { 
       StringBuilder sb = new StringBuilder(1); 
       int requiredSize = 0; 
       bool result = SetupDiGetDeviceInstanceId(handle.DangerousGetHandle(), ref diData[index], sb, sb.Capacity, out requiredSize); 
       if (result == false && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) 
       { 
        sb.Capacity = requiredSize; 
        result = SetupDiGetDeviceInstanceId(handle.DangerousGetHandle(), ref diData[index], sb, sb.Capacity, out requiredSize); 
       } 
       if (result == false) 
        throw new Win32Exception(); 
       if (instanceId.Equals(sb.ToString())) 
       { 
        return index; 
       } 
      } 
      // not found 
      return -1; 
     } 

     public static bool UninstallDevice(Guid classGuid, string instanceId) 
     { 
      SafeDeviceInfoSetHandle handle = null; 
      bool result = false; 

      try 
      { 
       // Get the handle to a device information set for all devices matching classGuid that are present on the system. 
       handle = SetupDiGetClassDevs(ref classGuid, instanceId, IntPtr.Zero, SetupDiGetClassDevsFlags.AllClasses | SetupDiGetClassDevsFlags.DeviceInterface); 

       if (handle.IsInvalid) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       // Get the device information data for each matching device. 
       DeviceInfoDataNative data = GetDeviceInfoData(handle); 

       // Find the index of our instance. i.e. the touchpad mouse - I have 3 mice attached... 
       //int index = GetIndexOfInstance(handle, diData, instanceId); 

       // TODO: Check the data structure first 

       // Uninstall 
       result = StartUninstallDevice(handle, data); 
      } 
      finally 
      { 
       if (handle != null) 
       { 
        if (handle.IsClosed == false) 
        { 
         handle.Close(); 
        } 

        handle.Dispose(); 
       }     
      } 

      return result; 
     } 

     private static bool StartUninstallDevice(SafeDeviceInfoSetHandle handle, DeviceInfoDataNative data) 
     { 
      ClassInstallHeader header = new ClassInstallHeader(); 
      RemoveDeviceParameters removalParameters = new RemoveDeviceParameters(); 

      bool needsReboot; 

      removalParameters.ClassInstallHeader.Size = Marshal.SizeOf(header); 
      removalParameters.ClassInstallHeader.InstallFunction = DiFunction.Remove; 
      removalParameters.Scope = Scope.Global; 
      removalParameters.HwProfile = 0; 

      bool result = SetupDiSetClassInstallParams(handle, ref data, ref removalParameters, Marshal.SizeOf(removalParameters)); 

      if (result == false) 
       throw new Win32Exception(); 

      result = DiUninstallDevice(IntPtr.Zero, handle, ref data, 0, out needsReboot); 

      // TODO: Check if need reboot 

      if (result == false) 
      { 
       int error = Marshal.GetLastWin32Error(); 

       if (error == (int)SetupApiError.NotDisableable) 
        throw new ArgumentException("Device can't be disabled (programmatically or in Device Manager)"); 
       else if (error >= (int)SetupApiError.NoAssociatedClass && error <= (int)SetupApiError.OnlyValidateViaAuthenticode) 
        throw new Win32Exception("SetupAPI Error: " + ((SetupApiError)error).ToString()); 
       else 
        throw new Win32Exception(); 
      } 

      return result; 
     } 

     public static void RemoveDevice(Guid classGuid, string instanceId) 
     { 
      SafeDeviceInfoSetHandle handle = null; 

      try 
      { 
       // Get the handle to a device information set for all devices matching classGuid that are present on the system. 
       handle = SetupDiGetClassDevs(ref classGuid, instanceId, IntPtr.Zero, SetupDiGetClassDevsFlags.AllClasses | SetupDiGetClassDevsFlags.DeviceInterface); 

       if (handle.IsInvalid) 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 

       // Get the device information data for each matching device. 
       DeviceInfoDataNative data = GetDeviceInfoData(handle); 

       // Find the index of our instance. i.e. the touchpad mouse - I have 3 mice attached... 
       //int index = GetIndexOfInstance(handle, diData, instanceId); 

       // Uninstall 
       bool result = StartRemoveDevice(handle, data); 
      } 
      finally 
      { 
       if (handle != null) 
       { 
        if (handle.IsClosed == false) 
        { 
         handle.Close(); 
        } 
        handle.Dispose(); 
       } 
      } 
     } 

     private static bool StartRemoveDevice(SafeDeviceInfoSetHandle handle, DeviceInfoDataNative data) 
     { 
      ClassInstallHeader header = new ClassInstallHeader(); 
      RemoveDeviceParameters removalParameters = new RemoveDeviceParameters(); 

      removalParameters.ClassInstallHeader.Size = Marshal.SizeOf(header); 
      removalParameters.ClassInstallHeader.InstallFunction = DiFunction.Remove; 
      removalParameters.Scope = Scope.Global; 
      removalParameters.HwProfile = 0; 

      bool result = SetupDiSetClassInstallParams(handle, ref data, ref removalParameters, Marshal.SizeOf(removalParameters)); 

      if (result == false) 
       throw new Win32Exception(); 

      result = SetupDiCallClassInstaller(DiFunction.Remove, handle, ref data); 

      if (result == false) 
      { 
       int error = Marshal.GetLastWin32Error(); 

       if (error == (int)SetupApiError.NotDisableable) 
        throw new ArgumentException("Device can't be disabled (programmatically or in Device Manager)."); 
       else if (error >= (int)SetupApiError.NoAssociatedClass && error <= (int)SetupApiError.OnlyValidateViaAuthenticode) 
        throw new Win32Exception("SetupAPI Error: " + ((SetupApiError)error).ToString()); 
       else 
        throw new Win32Exception(); 
      } 

      return result; 
     } 
    } 
} 

Utilisation:

/////* CD-ROM as an example *///// 

// Found in the Device Manager under <Device> -> Properties -> Details -> Class Guid 
Guid cdromClassGuid = new Guid("4d36e965-e325-11ce-bfc1-08002be10318"); 

// Found using WMI calls -> Disk -> Partitions -> LogicalDisks 
// For the CD-ROM example: Device Manager under <Device> -> Properties -> Details -> Device Instance Path 
string cdromInstancePath = @"SCSI\CDROM&VEN_MATSHITA&PROD_BD-RE_UJ260AF\4&315C1285&0&000000"; 

bool success = SetupApiWrapper.UninstallDevice(cdromClassGuid, cdromInstancePath); 
+0

Malheureusement, si vous réénumérer les périphériques (scanner les modifications matérielles, disques rescan) la appareil affiche sauvegarder. Pas exactement le comportement que je veux. – parkerflyz