Все привет, в диспетчере устройств Windows на любом из устройств можно в контекстном меню выбрать "Удалить устройство" а затем в контекстном меню выбрать "Обновить конфигурацию оборудования" после чего удаленное устройство снова появиться. Прошу знающих людей подсказать направление в решении данной задачи 1.Какими Winapi методами можно удалить устройство 2. И какими API методами можно обновить конфигурацию оборудования. Понятно что нужно с помощью GUID нужного класса устройств методом SetupDiGetClassDevs получить HDEVINFO, затем методом SetupDiEnumDeviceInterfaces перечислить все устройства данного класса, а вот дальше пока не знаю, кто знает буду благодарен за подсказку.
Спасибо.
Здравствуйте, _agg, Вы писали:
_>Все привет, в диспетчере устройств Windows на любом из устройств можно в контекстном меню выбрать "Удалить устройство" а затем в контекстном меню выбрать "Обновить конфигурацию оборудования" после чего удаленное устройство снова появиться. Прошу знающих людей подсказать направление в решении данной задачи
_> 1.Какими Winapi методами можно удалить устройство
_> 2. И какими API методами можно обновить конфигурацию оборудования.
_>
_> Понятно что нужно с помощью GUID нужного класса устройств методом SetupDiGetClassDevs получить HDEVINFO, затем методом
_> SetupDiEnumDeviceInterfaces перечислить все устройства данного класса, а вот дальше пока не знаю, кто знает буду благодарен за подсказку.
Рецепт для пункта 1:
Удаляем INF-файл драйвера из системы (если он есть) — SetupUninstallOEMInfW.
Далее заполняем структуру SP_REMOVEDEVICE_PARAMS (код DIF_REMOVE) и вызываем SetupDiSetClassInstallParams,
затем SetupDiCallClassInstaller. Этого достаточно, чтобы устройство исчезло из дерева устройств.
Несколько нюансов, как обычно:
* слышал не раз (хотя сам не сталкивался), да и в документации где-то было написано, что функция SetupUninstallOEMInfW
может отсутствовать на целевой системе. Т.е. лучше не линковаться с ней статически, а искать ее через GetProcAddress.
* у процесса должны быть права администратора (elevated) и он должен быть "нативной" разрядности (не WOW64).
С установкой и удалением устройства на старых версиях Windows (уровня Windows XP) есть один странный косяк,
проявляется он только для некоторых типов устройств и в каких-то специфических условиях.
Если во время установки, когда появляется окно "разрешить установку такого-то драйвера от такой-то организации"
нажать "нет", то установка обламывается, но узел оборудования застревает в системе с желтым значком и удалить
его оттуда нормальными способами не получается. Я для обхода этой ситуации всегда при удалении устройства
на старых системах дополнительно чищу реестр, т.е. те ветки, куда это устройство прописывается.
На реестр там обычно висят строгие разрешения (нельзя писать никому, кроме SYSTEM), так что предварительно
приходится их снимать (включаем привилегию "take ownership" или "restore", меняем владельца с WRITE_OWNER,
затем переоткрываем ключ реестра с WRITE_DAC, меняем разрешения на нужные и только после этого можем удалять).
На Windows Vista и выше такую ситуацию никогда не встречал (видимо, пофиксили).
По поводу пункта 2 точно не скажу, но опять отправлю смотреть исходники утилиты devcon, они в открытом доступе:
Device Console (DevCon) Tool
https://github.com/Microsoft/Windows-driver-samples/tree/master/setup/devcon
См., например, команду cmdRescan:
This command shows the correct way to rescan for all Plug & Play devices that may have previously
been removed, or that otherwise require a rescan to detect them.
Спасибо большое, буду пробовать
С пунктом номер 1 все оказалось просто
...
if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, pDeviceInterfaceDetailData, dwRequiredSize, 0, &devinfo_data)){
if (SetupDiRemoveDevice(hDevInfo, &devinfo_data)){
ret_val = true;
}
}
...
Вот в винде где-то есть метод который срабатывает на пункт меню "Обновить конфигурацию оборудования" в диспетчере устройств, как бы его найти ).
Все оказалось проще чем я думал, обновление конфигурации оборудования получилось довольно простое:
bool RescanDevicesPlugAndPlayUpdate(CString &err_msg){
bool ret_val(false);
HMACHINE machineHandle(NULL);
DEVINST devRoot;
CONFIGRET ret(NULL);
if ((ret = CM_Connect_Machine(NULL, &machineHandle)) == CR_SUCCESS) {
if ((ret = CM_Locate_DevNode_Ex(&devRoot, NULL, CM_LOCATE_DEVNODE_NORMAL, machineHandle)) == CR_SUCCESS) {
if ((ret = CM_Reenumerate_DevNode_Ex(devRoot, 0, machineHandle)) != CR_SUCCESS){
err_msg.Format(_T("CM_Reenumerate_DevNode_Ex error:0x%x"), ret);
}
}else
err_msg.Format(_T("CM_Locate_DevNode_Ex error:0x%x"), ret);
if (ret == CR_SUCCESS)
ret_val = true;
CM_Disconnect_Machine(machineHandle);
}
else err_msg.Format(_T("CM_Connect_Machine error:0x%x"),ret);
return ret_val;
}