![]() |
VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Hallo ihr Wissenden :),
ich möchte auf möglichst einfache Weise den VTOC (Volume Descriptor) einer CD/DVD auslesen. Konkret geht's mir dabei um PublisherID, PreparerID, ApplicationID und vor allem CreationDate bzw. ModificationDate. Gibt's irgendwo eine (kostenlos verwendbare) Bibliothek, die sowas ermöglicht? Oder muss man sogar auf ASPI/SPTI zurückgreifen und wenn ja, wonach müsste ich suchen? Ich hab sowas bereits vor 3 Jahren für DOS programmiert, aber Windows ist eben doch ein bisschen anders ;). Achso: bitte ohne .NET-Abhängigkeiten, denn das muss auch auf einem nackigen Windows 2000/XP laufen. Ich danke schonmal im Voraus für Ideen, Anregungen usw. MfG Dalai |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Hallo Dalai,
die gesuchten Informationen solltest Du teilweise mittels DeviceIoControl() und dem Control Code IOCTL_CHANGER_GET_PRODUCT_DATA erhalten. Mit den Anwendungsbeispielen hier im Forum und der ![]() Grüße vom marabu |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Das hilft mir leider überhaupt nicht weiter. CHANGER_PRODUCT_DATA enthält Infos über Laufwerke (Vendor, ProductID, SerialNumber usw) und nicht über das Medium, was im Laufwerk liegt. Die Infos über das Laufwerk sind zwar auch ganz schick, aber ich brauche die über's Medium.
Um's evtl. einfacher, in jedem Fall anders, zu schreiben: ich will einen ISO9660-Header bzw. Volume Descriptor auslesen und ausgeben/auswerten. Die im OP genannten Dinge sind Attribute desselben, und zwar die, die für mich in diesem Fall wichtig sind. Meinetwegen kann das Auslesen auch über Joliet erfolgen, so die Infos dort verfügbar sind. Der Weg ist mir ziemlich egal, das Ergebnis ist wichtig. MfG Dalai |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Hilft das hier vielleicht?
![]() Hab es nicht getestet, aber wenn die Lib brennen kann, dann vielleicht ... ? cu Oliver |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Schau mal unter
![]() |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Moin,
Zitat:
![]() Freundliche Grüße |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Ja, über das FreeBurner bin ich im Vorfeld des Themas auch gestoßen, war aber bisher nicht in der Lage, die nötigen Funktionen zu identifizieren, die auf das Medium zugreifen und die gewünschten Infos auslesen.
Die ISO9660PrimaryVolClass.pas hab ich mir angeschaut, aber das sind ja nur Deklarationen - die hätte ich im Zweifel auch selbst hinbekommen. Das ist im Moment eben mein Problem: ich weiß nicht, wie ich auf das Laufwerk bzw. dessen Medium zugreifen kann, um das OS oder die Schnittstelle oder das Laufwerk anzuweisen, bestimmte Bereiche zu lesen. Ich werd mir die anderen Libs von FreeBurner mal anschauen und melde mich wieder. Das isoinfo aus den cdrtools scheint auch ganz vielversprechend zu sein. MfG Dalai |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Am besten liest Du den Sektor 16 der CD/DVD aus.
![]() Ergänzung: ![]() ![]() |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
Liste der Anhänge anzeigen (Anzahl: 1)
Sodele,
der Hinweis von Hobby-Programmierer war gut, denn dadurch bin ich auf die APSI-Lib gekommen, die ein Testprojekt enthält, mit dem man beliebige Sektoren einer CD/DVD auslesen kann. Davon hab ich mir abgeschaut, welche Funktion man verwenden kann/muss, um das Gewünschte zu erreichen. Da die ASPI-Lib aber einige Nachteile hat (abhängig von installiertem ASPI, kein Auslesen der Laufwerksinfos, also Hersteller, Modell usw.), habe ich dann doch die FreeBurner-Lib genommen. Danke an Sir Rufo an dieser Stelle für den passenden Hinweis darauf. Nach einer Einbindungsorgie mit derselben habe ich dann endlich erreicht, was ich will - siehe Bild im Anhang. Ich habe noch nie so viele Units eingebunden wie bei diesem Projekt - insgesamt 19 Units allein aus der FreeBurner-Lib. Einige davon habe ich angepasst und die Einbindung von CDDB-Kram usw. rausgeschmissen, damit das nicht ausartet. Was habe ich benutzt? Recht einfach:
Delphi-Quellcode:
Beim Start wird ein Objekt fDrives erzeugt, das die (optischen) Laufwerke des Rechners enthält, inkl. Infos zu Modell, Hersteller, Firmware usw. Beim Klick auf den Button wird mit der Funktion ReadData der Sektor 16 des Mediums ausgelesen und dann in einen String kopiert.
uses [...], Devices, ScsiTypes, CovertFuncs;
type TMainForm = class(TForm) DriveCombo: TComboBox; ResultMemo: TMemo; ReadBtn: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); procedure ReadBtnClick(Sender: TObject); private fDrives: TDevices; end; //------------------------------------------------ procedure TMainForm.FormCreate(Sender: TObject); begin fDrives:= TDevices.Create; end; //------------------------------------------------ procedure TMainForm.FormDestroy(Sender: TObject); begin if Assigned(fDrives) then FreeAndNil(fDrives); end; //------------------------------------------------ procedure TMainForm.FormShow(Sender: TObject); var i : integer; begin for i:= 0 to Pred(fDrives.Count) do with fDrives.Items[i].DeviceInfo do DriveCombo.Items.Add(Format('%d,%d,%d %s %s (%s)', [HaId, Target, Lun, DriveName, VendorName, Revision])); if DriveCombo.Items.Count > 0 then DriveCombo.ItemIndex:= 0; end; //------------------------------------------------ procedure TMainForm.ReadBtnClick(Sender: TObject); const BufLen = 2048; var Buf : Pointer; s : string; c : char; i : DWORD; liste : TStringList; begin Buf:= nil; ReallocMem(Buf, BufLen); try if fDrives.Items[DriveCombo.ItemIndex].DeviceReader.ReadData(16, 1, Buf, BufLen) then begin for i:=0 to BufLen do begin c:= (PChar(Buf) + i)^; (*if c < ' ' then c := ' ';*) s:= s + c; end; liste:= TStringList.Create; HexStrToPVD(s, liste); ResultMemo.Lines.Assign(liste); liste.Free; end; finally ReallocMem(Buf, 0); end; end; Um die Daten übersichtlich darzustellen, benutze ich die Funktion HexStrToPVD, die ich aus Längengründen mal weggelassen habe; dort passiert im Prinzip nichts weiter, als die Felder an den Indizes in eine StringListe zu kopieren, damit das Memo sie aufnehmen kann. Das Ganze läuft auch ohne installiertes ASPI, zumindest auf Win2k und höher, was aber nicht weiter schlimm ist, denn wen interessiert schon Win9x noch? 8) Was bleibt noch zu tun? Die Umrechnung der numerischen Felder fehlt noch, wie man auch leicht am Screenshot sieht ;). Und eine übersichtlichere Darstellung in Tabellenform steht auch noch an, aber das dürfte beides machbar sein - falls nicht, werde ich das Forum nochmals nerven :mrgreen:. MfG Dalai |
Re: VTOC/Inhaltsverzeichnis einer CD/DVD auslesen
19 Units sind viel. Die Infos zu den CD/DVDs kann man auch so holen:
Delphi-Quellcode:
Das Ergebnis der function ist die Anzahl der CD/DVD-Laufwerke. FDrive ist folgender Record:
function TForm1.ReadDrives: Integer;
{******************************************************************************} {** Laufwerke holen: **} {** DriveLetter, HaID, Target, LUN, Identfier und DeviveName. **} {******************************************************************************} const Root2k = ''; Root98 = 'Enum\Scsi\'; var Reg : TRegistry; Root : String; RegKey : String; OSInfo : TOSVersionInfo; szDrives : array[0..105] of Char; hDevice : THandle; buf : array[0..1023] of Char; pDrive : PChar; pscsiAddr : PSCSI_ADDRESS; returned : Integer; Begin Result := 0; SetLength(FDrive, Result); OSInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); GetVersionEx(OSInfo); ZeroMemory(@szDrives, 106); GetLogicalDriveStrings(105, szDrives); pDrive := szDrives; while pDrive^ <> '' do begin if GetDriveType(pDrive) = DRIVE_CDROM then begin ZeroMemory(@buf, 1024); pscsiAddr := PSCSI_ADDRESS(@buf); pscsiAddr^.Length := sizeof(TSCSI_ADDRESS); hDevice := CreateFile(PChar(Format('\\.\%s:', [pDrive[0]])), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0 ); if hDevice <> INVALID_HANDLE_VALUE then if DeviceIoControl(hDevice, IOCTL_SCSI_GET_ADDRESS, nil, 0, pscsiAddr, sizeof(TSCSI_ADDRESS), Cardinal(returned), nil) then begin SetLength(FDrive, Result + 1); FDrive[Result].HaId := pscsiAddr^.PortNumber; FDrive[Result].Target := pscsiAddr^.TargetId; FDrive[Result].Lun := pscsiAddr^.Lun; FDrive[Result].Letter := pDrive^; // Registry öffnen Reg := TRegistry.Create; Reg.RootKey := HKEY_LOCAL_MACHINE; // OS abhängigen RootKey setzen if OSInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then Root := Root2k else Root := Root98; RegKey := Format('%sHARDWARE\DEVICEMAP\Scsi\Scsi Port %d\Scsi Bus 0\Target Id %d\Logical Unit Id %d', [Root, FDrive[Result].HaId, FDrive[Result].Target, FDrive[Result].Lun]); if Reg.KeyExists(RegKey) then begin if Reg.OpenKeyReadOnly(RegKey) then // Ist es ein CDRom? if Reg.ReadString('Type') = 'CdRomPeripheral' then begin // Name holen FDrive[Result].Identifier := Reg.ReadString('Identifier'); // Device FDrive[Result].DeviceName := Reg.ReadString('DeviceName'); end; // Schlüssel schliessen Reg.CloseKey; end; // Schlüssel schliessen Reg.CloseKey; // Registry schliessen Reg.Free; // anzahl erhöhen inc(Result); end; CloseHandle(hDevice); end; pDrive := pDrive + lstrlen( pDrive ) + 1; end; end;
Delphi-Quellcode:
Dummerweie weiß ich nicht mehr, welche Quellen ich dafür benutzt habe.
FDrive = Record
HaId : Byte; Target : Byte; Lun : Byte; Identifier : String; DeviceName : String; Letter : Char; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz