Devicecleanup.exe 〈2025-2027〉
else if (arg == L"/remove") g_action = ACTION_REMOVE_ONE; if (i + 1 < argc) g_targetId = argv[++i];
SP_DEVINFO_DATA devInfoData; devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); DWORD idx = 0; int removed = 0;
enum Action ACTION_LIST, ACTION_REMOVE_ONE, ACTION_REMOVE_ALL ; Action g_action = ACTION_LIST; std::wstring g_targetId; bool g_force = false; bool g_verbose = false; DeviceCleanup.exe
if (g_verbose) // Get hardware IDs DWORD hwIdSize = 0; SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID, NULL, NULL, 0, &hwIdSize); if (hwIdSize > 0) std::vector<BYTE> buffer(hwIdSize); SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID, NULL, buffer.data(), hwIdSize, &hwIdSize); WCHAR* hwid = (WCHAR*)buffer.data(); std::wcout << L" Hardware IDs: "; while (*hwid) std::wcout << hwid << L" "; hwid += wcslen(hwid) + 1; std::wcout << std::endl; std::wcout << std::endl;
switch (g_action) case ACTION_LIST: ListDevices(); break; case ACTION_REMOVE_ONE: if (g_targetId.empty()) std::wcerr << L"Error: /remove requires an ID.\n"; return 1; return RemoveById(g_targetId); case ACTION_REMOVE_ALL: return RemoveAllNonPresent(); else if (arg == L"/remove") g_action = ACTION_REMOVE_ONE;
else PrintUsage(); return 1;
if (matches && IsNonPresentDevice(devInst)) std::wcout << L"Removing: " << instanceId << std::endl; if (RemoveDevice(devInst)) removed++; if (i + 1 <
std::wcout << L"Total non-present devices found: " << count << std::endl; SetupDiDestroyDeviceInfoList(hDevInfo);
bool IsNonPresentDevice(DEVINST devInst) ULONG status = 0, problem = 0; if (CM_Get_DevNode_Status(&status, &problem, devInst, 0) != CR_SUCCESS) return true; // Cannot query status -> treat as problematic
void PrintUsage() std::wcout << L"DeviceCleanup.exe - Remove non-present (ghost) devices\n\n"; std::wcout << L"Usage:\n"; std::wcout << L" DeviceCleanup.exe [/list] - List all non-present devices\n"; std::wcout << L" DeviceCleanup.exe /remove <id> - Remove device by instance ID or hardware ID\n"; std::wcout << L" DeviceCleanup.exe /remove-all - Remove all non-present devices\n"; std::wcout << L" DeviceCleanup.exe /force - Bypass pending restart flag (use with /remove or /remove-all)\n"; std::wcout << L" DeviceCleanup.exe /verbose - Show detailed info\n"; std::wcout << L"\nExample:\n"; std::wcout << L" DeviceCleanup.exe /list\n"; std::wcout << L" DeviceCleanup.exe /remove "USB\VID_1234" /force\n"; std::wcout << L" DeviceCleanup.exe /remove-all /verbose\n";