Frage

GELÖST

Ich bin mit delphi 2009 Mein Programm wartet auf USB-Laufwerke angeschlossen sind und entfernen. Ive verwendet, um einen sehr ähnlichen Code in 10 Apps im vergangenen Jahr. Es war schon immer perfekt funktioniert. Wenn ich migriert hatte ich mit thddinfo aufgeben, um das Laufwerk-Modell zu erhalten. Dies wurde durch die Verwendung von WMI ersetzt. Die WMI-Abfrage erfordert die physische Datenträger-Nummer und ich zufällig schon eine Funktion in der App habe für genau das zu tun.

Wie ich teste ich habe dies in einem Knopf und es lief, und er bestimmt erfolgreich die psp physisches Laufwerk 4 und gibt das Modell (alle im Debugger und in einem anderen Beispiel mit Show-Nachricht markiert):

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;

Es funktioniert perfekt das heißt, bis ich das WMDeviceChange ermöglichen, die für ein Jahr mit ive die getphysicaldisknumber aufzurufen und die WMI-Abfrage-Anweisung. Ive versucht, sie selbst theyre beide ein Problem. GetPhysicalDiskNumber friert wirklich schlecht, wenn sich eine Closehandle auf der logischen Platte zu tun, aber die Zahl schließlich zurückkehrt. Die WMI-Abfrage schlägt mit nur kein Fehler zurückgibt ‚‘ Debugger Punkte in die wbemscripting_tlb, wo die Verbindung nur noch nie passiert ist. Halten Sie die einzige Sa geändert in einem Jahr im Auge ist, was im das Modell zu bekommen Aufruf i wurde mit einem API-Aufruf und jetzt im mit etwas anderem.

Im Folgenden ist der Rest des Codes zu diesem Zeitpunkt sans die ispsp beteiligt, die oben angezeigt wird:

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;

Rob hat gesagt, etwas unter etwa im nicht die geerbte Message-Handler aufrufen, ive lesen Sie das Dokument ich ein paar Dinge sehe ich zurückkehren kann ... aber ich bin nicht wirklich sicher, ob ich verstehen, aber ich werde das prüfen. Ich bin nicht ein sehr guter pascal Programmierer, aber ive viel gelernt. Der Übergang zum Jahr 2009 auch einige raue Flecken hatte.

Die USB-Laufwerk Erkennung und alles, was perfekt funktioniert. Wenn ich die beiden Dinge aus zu entfernen, um den Benutzer PSP ist sofort begrüßt mit wis dies Ihr was auch immer und fügt I: \ auf der Liste. Es ist nur die beiden neuen Dinge, die in der App geändert haben, die, wenn sie von wmdevicechange und wie gesagt genannt fail, bevor sie auf ihre eigene Arbeit.

EDIT - GELöST

In Ordnung auch im ein Timer, wie vorgeschlagen, und das Problem scheint gelöst zu werden. Ein Hinweis ist, dass, wenn durch den Timer sehr kurz nach dem wmdevicechange immer die physische Datenträger-Nummer noch genannt scheint langsam zu sein. Ich führe dies nach wie vor auf das Gerät an das System angeschlossen werden.

In diesem Sinne im P2-450 auf dem regulären verwenden. Ich hakte die PSP und App zu einem 1.8Ghz Dual Core Laptop und das Programm erfasst die psp und benachrichtigt den Benutzer sehr schnell. So ist die App einfrieren gewohnt, es sei denn auf einen sehr, sehr langsamen Computer und auf dieser langsame onw seines nur für eine Sache von Sekunden und tut den Betrieb des Programms allerdings ist nicht sehr cool beeinflussen. Aber ich fühle, dass alle modernen Computer wird die Erkennung schnell vor allem laufen, weil sie das Gerät viel schneller anbringen kann.

War es hilfreich?

Lösung

Es ist möglich, dass die Informationen, die Sie die Abfrage nur verfügbar sind nach der WMDeviceChange Message-Handler ausgeführt wird. Wenn der gleiche Code funktioniert, wenn sie von einer Schaltfläche aufgerufen, versuchen Sie dies:

  1. Refaktorieren WMDeviceChange-Handler-Code in ein oder mehr separaten Verfahren.
  2. Im WMDeviceChange Handler aktiviert, um einen precreated Timer und haben sie eine Sekunde später feuern, oder so ähnlich.
  3. Rufen Sie den ehemaligen WMDeviceChange-Handler-Code aus dem Timer-Handler-Code.

Andere Tipps

Sie haben nicht angegeben, was "Anweisung 1" im Code ist.

Ich habe ein paar Kommentare über Teile des Codes, die Sie haben.

oder auch nicht mit dem Problem in Zusammenhang stehen

Zuerst weisen Sie einen Wert in DriveNum IsPSP, aber Sie es nicht verwenden. Der Compiler sollte einen Hinweis darüber ausgegeben werden; keine Hinweise und Warnungen ignorieren. Sie passieren auch die magische Zahl 4 in MagWmiGetDiskModel; wurde, dass statt zu DriveNum soll?

Sie rufen nicht die Nachrichten-Handler geerbt, und Sie sind nicht ein Ergebnis in Ihren Nachrichten-Handler zurück. Die Dokumentation erzählt, welche Werte Sie sollen zurückzukehren. Um einen Wert aus einem Delphi-Message-Handler zurückkehren, um einen Wert zu dem Msg.Result Feld zuweisen. Für die Fälle, die Behandlungsroutine für Nachrichten nicht, stellen Sie sicher, dass Sie inherited rufen nicht verarbeitet, so dass die nächste Handler die Kette nach oben um sie kümmern kann. Wenn es keinen nächsten Handler ist, dann wird Delphi DefWindowProc nennen das Betriebssystem des Standardverhalten zu erhalten.

Die Änderung, die Sie dargestellt haben heißt Refactoring , und es wird nichts tun, um zu beeinflussen, wie Ihr Code ausgeführt wird. Es macht den Code leichter zu lesen, obwohl, so wenden Sie sich bitte die zweite Version halten. Wie für die Suche nach dem Problem, ist mein bester Rat, den Debugger zu verwenden, um den Code zu dem Schritt, den Punkt zu erkennen, wo die Dinge stat schief gehen und die Teile, die langsamer laufen, als Sie möchten. Sie können auch versuchen, Teile des Codes zu entfernen, um zu bestätigen, dass die anderen Teile in Isolation korrekt funktionieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top