Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > JEDI API, отключение и подключение устройств


Автор: nickolay1979 27.2.2009, 12:01
Здравствуйте!

Требуется программно отключить, а потом подключить USB-устройство (FT245R) подобно пунктам меню Диспетчера устройств "Отключить" и "Задействовать".
Как это проще всего сделать?

Как я понял надо использовать SetupApi.
Скачал. Подключил.
Пробуем вызывать функции...

Код

... 
var Guid : TGUID; 
PnPHandle : HDevInfo; 
... 
const USBGuid : TGUID = '{36FC9E60-C465-11CF-8056-444553540000}'; 
... 
Guid := USBGuid; 
PnPHandle := SetupDiGetClassDevs(@Guid, nil, 0, DIGCF_PRESENT); 
...


При вызове SetupDiGetClassDevs получаем: 'Access Violation at address 00000000. Read of address 0000000.'

С чем это связано?
Что-то с компиляцией модулей?

Автор: Riply 27.2.2009, 14:13
Цитата(nickolay1979 @  27.2.2009,  12:01 Найти цитируемый пост)
Скачал. Подключил


Что скачал и как подключил догадываться самостоятельно ?

По сабжу: LoadSetupApi ?

Автор: nickolay1979 27.2.2009, 19:17
Цитата(Riply @ 27.2.2009,  14:13)
Цитата(nickolay1979 @  27.2.2009,  12:01 Найти цитируемый пост)
Скачал. Подключил


Что скачал и как подключил догадываться самостоятельно ?

По сабжу: LoadSetupApi ?

Извиняюсь за краткость! smile
Скачал JEDI.
Задал пути к папкам.
LoadSetupApi через некоторое время сделал smile
Теперь ошибок нет.

Интересует алгоритм и код программы, с помощью которой можно включать и отключать устройства.

Автор: nickolay1979 5.3.2009, 10:51
Привожу свой код функции (работоспособный), которая выключает/включает устройство по коду экземпляра устройства.
Критика и полезные советы очень приветствуются. Хотелось бы в результате обсуждения получить не только работоспособный, но и простой, красивый и оптимизированный код.

Код
function On_Off_Device(PnPID: PAnsiChar; State: Boolean): Boolean;

var
  DeviceInfoSet_ : HDEVINFO; // Хендл набора информации об устройствах.
  DeviceInfoData_ : TSPDevInfoData; // Структура информации об устройстве.
  SPPropChangeParams_ : TSPPropChangeParams;

begin
  DeviceInfoSet_ := nil;
// Получение хендла набора информации об устройстве по коду экземпляра устройства.
  DeviceInfoSet_ := SetupDiGetClassDevs(nil, PnPID, 0, DIGCF_ALLCLASSES or DIGCF_DEVICEINTERFACE);
  if Integer(DeviceInfoSet_) = INVALID_HANDLE_VALUE then
  begin
// Ошибка.
    Result := False;
    Exit;
  end
  else
  begin
// Хендл набора информации об устройстве получен.
    FillChar(DeviceInfoData_, SizeOf(TSPDevInfoData), 0);
    DeviceInfoData_.cbSize := SizeOf(TSPDevInfoData);
// Заполнение структуры информации об устройстве.
    if not SetupDiEnumDeviceInfo(DeviceInfoSet_, 0, DeviceInfoData_) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;

// Установка полей структуры
    SPPropChangeParams_.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
    SPPropChangeParams_.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
    SPPropChangeParams_.Scope := DICS_FLAG_GLOBAL;

    if State then SPPropChangeParams_.StateChange := DICS_ENABLE
    else SPPropChangeParams_.StateChange := DICS_DISABLE;

// Изменение состояния устройства.
    if not SetupDiSetClassInstallParams(DeviceInfoSet_,
                                        @DeviceInfoData_,
                                        @SPPropChangeParams_,
                                        SizeOf(TSPPropChangeParams)) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;
// Подтверждение изменения состояния устройства
// (повторный вызов функции SetupDiSetClassInstallParams).
    if not SetupDiSetClassInstallParams(DeviceInfoSet_,
                                        @DeviceInfoData_,
                                        @SPPropChangeParams_,
                                        SizeOf(TSPPropChangeParams)) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;

// Вызов установщика классов.
    if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DeviceInfoSet_, @DeviceInfoData_) then
    begin
// Ошибка.
      SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
      Result := False;
      Exit;
    end;

  end; // Integer(DeviceInfoSet_) <> INVALID_HANDLE_VALUE

  Result := True;
// Освобождение хендла набора информации об устройствах.
  SetupDiDestroyDeviceInfoList(DeviceInfoSet_);
end;


Попутно - несколько вопросов.

1. При вызове моей функции с параметром False для отключении устройства N раз подряд, чтобы включить устройство приходится вызывать эту функцию с параметром True тоже N раз подряд. Как будто где-то есть счётчик включения/выключения... Почему и зачем?
2. Хотелось бы прояснить работу SetupDiGetClassDevs. Без флага DIGCF_DEVICEINTERFACE - моя функция не работает. Хотя в других примерах видел вызывы и без этого флага (с параметром Enumerator!). Не понятна связь между параметром Enumerator и флагом DIGCF_DEVICEINTERFACE.
3. Хотелось бы знать как можно назвать по-русски следующие структуры, используемые при вызове функций: HDEVINFO (хендл на структуру ...), TSPDevInfoData (структура ...), TSPPropChangeParams (структура...). Не могу перевести нормально, а название поиметь хочется.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)