решаемые
Я использую delphi 2009. Моя программа прослушивает подключенные USB-накопители и удаляет их. За последний год я использовал очень похожий код в 10 приложениях. Это всегда работало отлично. Когда я мигрировал, мне пришлось отказаться от использования thddinfo, чтобы получить модель накопителя. Это было заменено с помощью WMI. Для запроса WMI требуется номер физического диска, и в приложении уже есть функция для этого.
Во время тестирования я помещаю это в кнопку и запускаю, и он успешно определяет, что psp - это физический диск 4, и возвращает модель (все проверено в отладчике и в другом примере с использованием сообщения show):
function IsPSP(Drive: String):Boolean;
var
Model: String;
DriveNum: Byte;
begin
Result := False;
Delete(Drive, 2, MaxInt);
DriveNum := GetPhysicalDiskNumber(Drive[1]);
Model := (MagWmiGetDiskModel(DriveNum));
if Pos('PSP',Model) > 0 then Result := True;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
var DriveNum: Byte;
begin
IsPSP('I');
end;
Это прекрасно работает, пока я не позволю WMDeviceChange, который я использовал в течение года, вызвать getphysicaldisknumber и оператор запроса wmi. Я попробовал их самостоятельно, они оба проблема. GetPhysicalDiskNumber очень сильно зависает, когда выполняет CloseHandle на логическом диске, но в конце концов возвращает число. Запрос WMI завершается неудачно, без ошибок просто возвращает '' точки отладчика в wbemscripting_tlb, где соединение никогда не было. Имейте в виду, единственное, что изменилось за год, это то, что я звонил, чтобы получить модель, которую я использовал с помощью API, а теперь я использую что-то другое.
Ниже приведен остальной код, используемый в это время без отображаемого выше ispsp:
procedure TfrmMain.WMDeviceChange(var Msg: TMessage);
var Drive: String;
begin
case Msg.wParam of
DBT_DeviceArrival: if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then
begin
Drive := GetDrive(PDevBroadcastVolume(Msg.lParam)) + '\';
OnDeviceInsert(Drive);
end;
DBT_DeviceRemoveComplete: if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then
begin
Drive := GetDrive(PDevBroadcastVolume(Msg.lParam)) + '\';
OnDeviceRemove(Drive);
end;
end;
end;
Procedure TfrmMain.OnDeviceInsert(Drive: String);
var PreviousIndex: Integer;
begin
if (getdrivetype(Pchar(Drive))=DRIVE_REMOVABLE) then
begin
PreviousIndex := cbxDriveList.Items.IndexOf(cbxDriveList.Text);
cbxDriveList.Items.Append(Drive);
if PreviousIndex = -1 then //If there was no drive to begin with then set index to 0
begin
PreviousIndex := 0;
cbxDriveList.ItemIndex := 0;
end;
if isPSP(Drive) then
begin
if MessageDlg('A PSP was detect @ ' + Drive + #10#13 + 'Would you like to select this drive?',mtWarning,[mbYes,mbNo], 0) = mrYes then
cbxDriveList.ItemIndex := cbxDriveList.Items.IndexOf(Drive)
else cbxDriveList.ItemIndex := PreviousIndex;
end
else if MessageDlg('USB Drive ' + Drive + ' Detected' + #10#13 + 'Is this your target drive?',mtWarning,[mbYes,mbNo], 0) = mrYes then
cbxDriveList.ItemIndex := cbxDriveList.Items.IndexOf(Drive)
else cbxDriveList.ItemIndex := PreviousIndex;
end;
end;
Procedure TfrmMain.OnDeviceRemove(Drive: String);
begin
if not (getdrivetype(Pchar(Drive)) = DRIVE_CDROM) then
begin
if cbxDriveList.Text = (Drive) then ShowMessage('The selected drive (' + Drive + ') has been removed');
cbxDriveList.Items.Delete(cbxDriveList.Items.IndexOf(Drive));
if cbxDriveList.Text = '' then cbxDriveList.ItemIndex := 0;
if Drive = PSPDrive then //Check Detect PSP and remove reference if its been removed
begin
PSPDrive := '';
end;
end;
end;
Роб сказал что-то ниже о том, что я не вызываю унаследованный обработчик сообщений, я прочитал документ и вижу пару вещей, которые могу вернуть ... но я не совсем уверен, что понимаю, но я посмотрю на это. Я не очень хороший программист на Паскале, но я много учился. Переход к 2009 году также имел некоторые грубые изменения.
Обнаружение USB-накопителя и все, что работает отлично. Если я удаляю две вещи из psp, пользователя сразу же приветствуют с помощью wis this и добавляет I: \ в список. Это просто две новые вещи, которые изменились в приложении, которые перестают работать при вызове wmdevicechange и, как уже было сказано, работают самостоятельно.
РЕДАКТИРОВАТЬ - РЕШЕНО
Хорошо, я использую таймер, как предложено, и проблема, кажется, решена. Следует отметить, что при вызове таймером очень скоро после wmdevicechange получение номера физического диска все еще кажется медленным. Я приписываю это устройству, все еще подключенному к системе.
На этой ноте я использую P2 450 на обычном. Я подключил PSP и приложение к 1,8-ГГц двухъядерному ноутбуку, и программа обнаружила psp и очень быстро уведомила пользователя. Таким образом, приложение не будет зависать, если оно находится на очень очень медленном компьютере и на этом медленном включении только в течение нескольких секунд и не влияет на работу программы, хотя и не очень круто. Но я чувствую, что все современные компьютеры будут выполнять обнаружение быстро, особенно потому, что они могут подключить устройство намного быстрее.