// WARNING: Removes ONLY the particular device // instance referenced by 'devInfoSet' public static bool RemoveFromSystem( SetupApi.DeviceInfoSet devInfoSet, string hwID, bool strictSearch) { SetupApi.SP_DEVINFO_DATA devInfoData; devInfoData = FindInSystem( hwID, devInfoSet, strictSearch ); if (devInfoData == null) { return false; } SetupApi.SP_REMOVEDEVICE_PARAMS rparams = new SetupApi.SP_REMOVEDEVICE_PARAMS(); rparams.ClassInstallHeader.cbSize = (uint)Marshal.SizeOf(rparams.ClassInstallHeader); rparams.ClassInstallHeader.InstallFunction = SetupApi.DI_FUNCTION.DIF_REMOVE; rparams.HwProfile = 0; rparams.Scope = SetupApi.DI_REMOVE_DEVICE_GLOBAL; GCHandle handle1 = GCHandle.Alloc(rparams); if (!SetupApi.SetupDiSetClassInstallParams( devInfoSet.Get(), devInfoData, ref rparams, Marshal.SizeOf(rparams))) { Win32Error.Set("SetupDiSetClassInstallParams"); throw new Exception( Win32Error.GetFullErrMsg() ); } Trace.WriteLine( "Removing device \'" + hwID + "\' from system" ); if (!SetupApi.SetupDiCallClassInstaller( SetupApi.DI_FUNCTION.DIF_REMOVE, devInfoSet.Get(), devInfoData)) { Win32Error.Set("SetupDiCallClassInstaller"); throw new Exception( Win32Error.GetFullErrMsg() ); } Trace.WriteLine("Remove should have worked"); return true; }
// Use this function for any 'Device Registry // Property' that returns 'REG_MULTI_SZ', // e.g. SPDRP_HARDWAREID public static string[] GetDevRegPropertyMultiStr( SetupApi.DeviceInfoSet devInfoSet, SetupApi.SP_DEVINFO_DATA devInfoData, SetupApi.SPDRP property) { int propertyRegDataType; int requiredSize; // 'buffer' is 4KB but Unicode chars are 2 bytes, // hence 'buffer' can hold up to 2K chars const int BUFFER_SIZE = 4096; byte[] buffer = new byte[BUFFER_SIZE]; SetupApi.SetupDiGetDeviceRegistryProperty( devInfoSet.Get(), devInfoData, property, out propertyRegDataType, buffer, BUFFER_SIZE, out requiredSize ); return Helpers.StringArrayFromMultiSz(buffer); }
// Use this function for any 'Device Registry // Property' that returns a string, // e.g. SPDRP_CLASSGUID public static string GetDevRegPropertyStr( SetupApi.DeviceInfoSet devInfoSet, SetupApi.SP_DEVINFO_DATA devInfoData, SetupApi.SPDRP property) { int propertyRegDataType; int requiredSize; // 'buffer' is 1KB but Unicode chars are 2 bytes, // hence 'buffer' can hold up to 512 chars const int BUFFER_SIZE = 1024; byte[] buffer = new byte[BUFFER_SIZE]; SetupApi.SetupDiGetDeviceRegistryProperty( devInfoSet.Get(), devInfoData, property, out propertyRegDataType, buffer, BUFFER_SIZE, out requiredSize ); return System.Text.Encoding.Unicode.GetString( buffer, 0, requiredSize ); }
// The function takes as input an initialized 'deviceInfoSet' // object and a hardware ID string we want to search the system // for. If 'strictSearch' is true, the device needs to exactly // match the hwID to be returned. Otherwise, the device's name // needs to start with the supplied hwID string. If the device // is found, a fully initialized 'SP_DEVINFO_DATA' object is // returned. If not, the function returns 'null'. public static SetupApi.SP_DEVINFO_DATA FindInSystem( string hwID, SetupApi.DeviceInfoSet devInfoSet, bool strictSearch) { SetupApi.SP_DEVINFO_DATA devInfoData = new SetupApi.SP_DEVINFO_DATA(); devInfoData.cbSize = (uint)Marshal.SizeOf(devInfoData); // Select which string comparison function // to use, depending on 'strictSearch' Func<string, string, bool> hwIDFound; if (strictSearch) { hwIDFound = (string _enumID, string _hwID) => _enumID.Equals( _hwID, StringComparison.OrdinalIgnoreCase ); } else { hwIDFound = (string _enumID, string _hwID) => _enumID.StartsWith( _hwID, StringComparison.OrdinalIgnoreCase ); } Trace.WriteLine( "Searching system for device: \'" + hwID + "\'; (strict search: \'" + strictSearch + "\')" ); for (uint i = 0; SetupApi.SetupDiEnumDeviceInfo( devInfoSet.Get(), i, devInfoData); ++i) { string [] ids = GetDevRegPropertyMultiStr( devInfoSet, devInfoData, SetupApi.SPDRP.HARDWAREID ); foreach (string id in ids) { if (hwIDFound(id, hwID)) { Trace.WriteLine( "Found: \'" + String.Join(" ", ids) + "\'" ); return devInfoData; } } } Win32Error.Set("SetupDiEnumDeviceInfo"); if (Win32Error.GetErrorNo() == WinError.ERROR_NO_MORE_ITEMS) { Trace.WriteLine("Device not found"); return null; } throw new Exception(Win32Error.GetFullErrMsg()); }