【问题标题】:Windows Storage Management API - VDS (Virtual Disk Service) Uninstall Disk Equivalent methodWindows Storage Management API - VDS(虚拟磁盘服务)卸载磁盘等效方法
【发布时间】:2018-02-23 20:03:48
【问题描述】:

由于 VDS 已被弃用并且 Windows 存储管理 API 正在取代它 - 是否有任何 WMI、IOCTL、DeviceIoControl 或 Windows 存储管理 API 方法等效于 VDS 方法“UninstallDisks”?

我找不到任何其他方法来执行 VDS 方法“UninstallDisks”所做的工作。

任何帮助将不胜感激。

【问题讨论】:

    标签: winapi ioctl deviceiocontrol vds


    【解决方案1】:

    结合其他贡献者的代码,我自己想出来了。

    参考: Win32 API function to programmatically enable/disable device

    下面的主要代码库:

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

    用法:

    /////* 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);
    

    【讨论】:

    • 不幸的是,如果您重新枚举设备(扫描硬件更改、重新扫描磁盘),设备会显示备份。不完全是我想要的行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多