Entwickler-Ecke

Windows API - Ist ein CD-Laufwerk geöffnet?


LonghornUser - Di 06.10.09 18:02
Titel: Ist ein CD-Laufwerk geöffnet?
Hallo,

wie kann ich herausfinden, ob ein CD-Laufwerk gerade offen oder geschlossen ist?

Danke schon mal!

Ciao LHUser


Dunkel - Di 06.10.09 19:04

Hallo!

Und was machst Du bei einem Slot-In-Laufwerk? Ist das ständig offen oder ständig zu?


FinnO - Di 06.10.09 19:16

du kannst immerhin überprüfen ob eine gewisse datei in dem CD-Laufwerk ist.

Delphi-Quelltext
1:
if fileexists('E:\DeineDatei.txt'then...                    


Boldar - Di 06.10.09 19:41

Gingen Laufwerksabfragen nicht über WMI??


LonghornUser - Di 06.10.09 21:10

Bei Notebook-Laufwerken ist so eine Überprüfung natürlich nicht möglich, aber ich will folgendes machen:

Per Button soll ein Laufwerk, je nach dessen aktuellem Zustad geöffnet oder geschlossen werden. Geht das aus irgendeinem Grund nicht (Slot-Laufwerk oder Fehler), soll einfach nichts getan werden.

Geht das irgendwie?


elundril - Di 06.10.09 21:58

vielleicht hilft dir ja das hier weiter:

http://www.swissdelphicenter.ch/de/showcode.php?id=124

lg elundril


LonghornUser - Mi 07.10.09 14:55

@elundril: Ich habe das ganze mal probiert. Und zwar so:

Delphi-Quelltext
1:
2:
Button1 (Open):
if OpenCD('E') = False then showmessage('Fehler');


Leider ohne Erfolg. Wenn das Laufwerk (was ein ganz normales 5,25" ist) durch den Befehl geöffnet wird, gibt die Funktion trotzdem False zurück. Dadurch ist auch mein zweiter gedanklicher Schritt leider unbrauchbar:

Delphi-Quelltext
1:
2:
3:
if OpenCD('E') = False then 
  if CloseCD('E') = False then 
    showmessage('Fehler');


Kann da jemand weiterhelfen?


Tryer - Mi 07.10.09 18:51

Das die Funktion False liefert liegt daran das sie fehlerhaft ist. "if res = 0 then Exit;" macht keinen Sinn da bei Erfolg 0 zurückgegeben wird -> einfach nur "Result := res = 0;"
Leider gibt mciSendString auch 0 ("Fehlerfrei") zurück wenn ein Laufwerk was nur manuell zu schliessen ist geschlossen werden soll, die Auswertung hilft also nicht weiter.
Zuverlässiger wären zwei getrennte Buttons zum öffnen/schliessen, oder Du versuchst es so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
...
  FLastCmdWasOpenDoor: Boolean;
...
  FLastCmdWasOpenDoor := False;
...
procedure ToggleDoor(Drive: Char);
var
  OpenError: Cardinal;

  procedure OpenDrive(ADriveChar: Char; AOpen: Boolean);
  // http://www.delphi-treff.de/tipps/system/wiki/CD-Laufwerk%20%C3%B6ffnen_schlie%C3%9Fen/
  const
    OpenStr: array[False..True] of string = ('closed''open');
  begin
    if mciSendString(PChar('open ' + ADriveChar + ': type cdaudio alias cdlw'), nil00) = 0 then
    begin
      mciSendString(PChar('set cdlw door ' + OpenStr[AOpen] + ' wait'), nil00);
      mciSendString('close cdlw'nil00);
    end;
  end;

  function GetOpenRootError(D: Char): Cardinal;
  var
    Handle: THandle;
  begin
    {$I-}
    Handle := CreateFile(
      PChar(D + ':\'),
      GENERIC_READ,
      FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
      nil,
      OPEN_EXISTING,
      FILE_FLAG_BACKUP_SEMANTICS,
      0);
    Result := GetLastError;
    if Handle <> INVALID_HANDLE_VALUE then
      CloseHandle(Handle);
    {$I+}
  end;

begin
  if GetOpenRootError(Drive) = ERROR_NOT_READY then
  begin
    if FLastCmdWasOpenDoor then
      OpenDrive(Drive, False)
    else
      OpenDrive(Drive, True);
    FLastCmdWasOpenDoor := not FLastCmdWasOpenDoor;
  end else
  begin
    OpenDrive(Drive, True); 
    FLastCmdWasOpenDoor := True;
  end;
end;

Wenn der Zugriff auf die CD klappt bzw. wenn der Fehler ein anderer als "nicht bereit" ist, dann war die Schublade zu und wird geöffnet. Ansonsten kann nicht zwischen leer und offen unterschieden werden, daher wird hin und her gewechselt. Im Fall das das Laufwerk also leer ist muss man ggf. zweimal klicken um zum gewünschten Ergebnis zu kommen.

Grüsse, Dirk


LonghornUser - Mi 07.10.09 19:18

Wow, danke für deine Arbeit! Ich schaue morgen dann mal drüber unnd berichte ;)

Edit: Konnte es nicht mehr abwarten und habe es heute noch getestet. Funktioniert bestens, vielen Dank! Nur, wenn der User selbst eingreift und das Laufwerk selbst bedient, kommt es zu Unregelmäßigkeiten. Echt spitze!


Garf - Do 08.10.09 19:34

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
Und was machst Du bei einem Slot-In-Laufwerk? Ist das ständig offen oder ständig zu?

Besitzt ein Slot-In eine Schublade, welche geöffnet werden kann?

user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
Funktioniert bestens, vielen Dank! Nur, wenn der User selbst eingreift und das Laufwerk selbst bedient, kommt es zu Unregelmäßigkeiten. Echt spitze!

Dann ging es wohl nicht darum, ob das Laufwerk geöffnet ist oder nicht? Denn mit obigen Source dürfte doch nur getestet werden, ob auf ein Medium zugegriffen werden kann.

http://www.delphipraxis.net/topic97214_cdlaufwerkslade+offen.html


LonghornUser - Do 08.10.09 19:39

@Garf: Das reicht mir so. Ist so dann doch in Ordnung ;)


Delete - Fr 09.10.09 01:09

Um was ging es dir jetzt eigentlich?


LonghornUser - Fr 09.10.09 13:13

Darum, eine zufriedenstellende Lösung zu finden.


Garf - Sa 10.10.09 16:09

Ist aber nicht die Lösung für die gestellte Frage. ;)


Tryer - Sa 10.10.09 17:48

Da mein Versuch dem Anliegen von LHUser im Rahmen meiner Kenntnisse mgl. nahe zu kommen Dir nicht zusagt darfst Du meinen Vorschlag gerne ignorieren und eine bessere Lösung bereitstellen (die deine bisherigen Links ja auch nicht bieten). Gelesen hast Du seine Frage zwar, verstanden was er möchte wohl weniger. Dumme Kommentare zu den Ideen anderer kannst Du Dir sparen, damit ist niemandem geholfen.

Grüsse, Dirk


Garf - Mo 12.10.09 12:54

Ich verstehe nicht, warum Du mich hier anfeindest. Dein Beispiel habe ich nicht kommentiert und für LonghornUser stellt es eine "zufriedenstellende" Lösung dar. Da es aber nur unter Beachtung der Bedingungen
zuverlässig funktioniert, ist nach meiner Meinung die Frage

user profile iconLonghornUser hat folgendes geschrieben Zum zitierten Posting springen:
wie kann ich herausfinden, ob ein CD-Laufwerk gerade offen oder geschlossen ist?

nicht beantwortet.

Oben habe ich auf meine Frage in der Delphi-PRAXIS verlinkt. Dort gibt es in #5 eine Lösung über den Changer Mechanismus, welche lediglich "Schreibrechte" benötigt. Im Text ist zwar kein Beispielcode angegeben, aber es gibt einen Anhang mit einem Demoprojekt.

Gruß Garf


Delete - Mo 12.10.09 13:36

Ich verfolge den Thread hier schon einige Tage und wundere mich, warum "krampfhaft" versucht wird, eine Antwort auf die Frage im Titel zu finden.
Für das BS ist es doch völlig uninteressant, ob eine vorhandene Schublade offen oder geschlossen ist:
Wenn auf ein Laufwerk zugegriffen wird, wird das Laufwerk automatisch den CDROMCLOSETRAY-Befehl ausführen.
Für das BS ist es dann nur interessant, ob gelesen oder geschrieben werden kann...

In der folgenden Audio Components Suite ist untenstehende Funktion enthalten.
http://acs.ullihome.de/acs/downloads/acs23.zip


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
 function GetCDStatus(cd_fd : Integer) : TCDStatus;
  var
    sci : cdrom_subchnl;
    res :Integer;
  begin
    res := ioctl(cd_fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
    case res of
      CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READY:
      begin
        Result := cdsNotReady;
        Exit;
      end;
    end;
.
.
.

.
Anmerkungen:
Der Test mit dem Changer Mechanismus, welcher funktioniert.
http://www.delphipraxis.net/download.php?id=23890

Slot in-Laufwerk:
kein Medium: Meldung= geöffnet
mit Medium: Meldung= geschlossen

Der Test mit IOCTL, welcher leider (bei mir) nicht funktioniert.
http://www.delphipraxis.net/download.php?id=23891

Slot in-Laufwerk:
kein Medium: Meldung= [21] Das Gerät ist nicht bereit.
mit Medium: Meldung= [0] Der Vorgang wurde erfolgreich beendet.


Garf - Mo 12.10.09 14:52

Die Funktion aus der Audio Components Suite ist für Linux. Den ioctl-Aufruf habe ich bei meiner Frage auf Delphi-PRAXIS in #1 auch genannt.

Die Downloads funktionieren so nicht ("You are not authorized to view, download or link to this Site.") Man muss über die Seite http://www.delphipraxis.net/topic97214_cdlaufwerkslade+offen.html gehen.

user profile iconhathor hat folgendes geschrieben Zum zitierten Posting springen:
Slot in-Laufwerk:
kein Medium: Meldung= geöffnet
mit Medium: Meldung= geschlossen

...

Slot in-Laufwerk:
kein Medium: Meldung= [21] Das Gerät ist nicht bereit.
mit Medium: Meldung= [0] Der Vorgang wurde erfolgreich beendet.

Interessant. Wusste ich bisher nicht. Danke.

Gruß Garf


Delete - Mo 12.10.09 16:55

user profile iconGarf hat folgendes geschrieben Zum zitierten Posting springen:
Die Funktion aus der Audio Components Suite ist für Linux. Den ioctl-Aufruf habe ich bei meiner Frage auf Delphi-PRAXIS in #1 auch genannt.
Gruß Garf


Die WINDOWS-Version ist auch enthalten.
Ich habe es auf
CodeGear™ Delphi® für Microsoft® Windows™ Version 11,2007
installiert.


Garf - Mo 12.10.09 22:14

Dann muss ich mir den Source noch einmal ansehen. Danke für den Hinweis.

Gruß Garf