Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Delphi. Как получить "сырые данные" о производителе, MID, типе, емкости, скорости CD/DVD диска (как в NeroDiscSpeed)?

Вячеслав Власов Гуру (3678), на голосовании 6 месяцев назад
Голосование за лучший ответ
Татьяна Просветленный (36401) 7 месяцев назад
Чтобы получить "сырые данные" о CD/DVD диске, такие как производитель, MID, тип, емкость и скорость, в Delphi, можно использовать несколько подходов. Один из них заключается в использовании Windows API и специализированных команд для работы с устройствами чтения/записи оптических дисков. В частности, можно использовать DeviceIoControl и соответствующие команды SCSI.
 uses 
Windows, SysUtils;

const
IOCTL_SCSI_PASS_THROUGH_DIRECT = $4D014;

type
SCSI_PASS_THROUGH_DIRECT = record
Length: USHORT;
ScsiStatus: UCHAR;
PathId: UCHAR;
TargetId: UCHAR;
Lun: UCHAR;
CdbLength: UCHAR;
SenseInfoLength: UCHAR;
DataIn: UCHAR;
DataTransferLength: ULONG;
TimeOutValue: ULONG;
DataBuffer: Pointer;
SenseInfoOffset: ULONG;
Cdb: array[0..15] of UCHAR;
end;

procedure GetDiscInformation;
var
hDevice: THandle;
sptd: SCSI_PASS_THROUGH_DIRECT;
SenseBuffer: array[0..17] of UCHAR;
DataBuffer: array[0..255] of UCHAR;
Returned: DWORD;
i: Integer;
begin
hDevice := CreateFile('\\.\E:', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, 0, 0);
if hDevice = INVALID_HANDLE_VALUE then
begin
RaiseLastOSError;
Exit;
end;

try
ZeroMemory(@sptd, SizeOf(SCSI_PASS_THROUGH_DIRECT));
sptd.Length := SizeOf(SCSI_PASS_THROUGH_DIRECT);
sptd.CdbLength := 12;
sptd.DataIn := 1; // SCSI_IOCTL_DATA_IN
sptd.SenseInfoLength := SizeOf(SenseBuffer);
sptd.DataTransferLength := SizeOf(DataBuffer);
sptd.TimeOutValue := 2;
sptd.DataBuffer := @DataBuffer;
sptd.SenseInfoOffset := DWORD(@SenseBuffer) - DWORD(@sptd);
sptd.Cdb[0] := $46; // GET CONFIGURATION command
sptd.Cdb[7] := $02;
sptd.Cdb[8] := $00;
sptd.Cdb[9] := $00;
sptd.Cdb[10] := $F0;

if not DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT,
@sptd, SizeOf(SCSI_PASS_THROUGH_DIRECT),
@sptd, SizeOf(SCSI_PASS_THROUGH_DIRECT),
@Returned, nil) then
begin
RaiseLastOSError;
Exit;
end;

// Пример вывода данных
for i := 0 to sptd.DataTransferLength - 1 do
begin
Write(IntToHex(DataBuffer[i], 2) + ' ');
if (i + 1) mod 16 = 0 then
WriteLn;
end;
finally
CloseHandle(hDevice);
end;
end;

begin
try
GetDiscInformation;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
Просто так это код вставлять в Delphi его нужно вставлять с умом.
после создания проекта
и вставлять по частям объявлений переменных и типов.

Если ты выберешь выделить весь код и вставишь будут ошибки
имей это ввиду
СКОРОЖАРКА!!! Гуру (3283) 7 месяцев назад
часть данных можно получить через wmi
 # powershell 
Get-WmiObject -Namespace "root\CIMV2" -Class Win32_CDROMDrive | Select-Object Manufacturer, Caption, Description, MediaType, MfrAssignedRevisionLevel
https://learn.microsoft.com/ru-ru/windows/win32/cimwin32prov/win32-cdromdrive

остальное тут
https://learn.microsoft.com/ru-ru/windows-hardware/drivers/ddi/_storage/#ioctls
только осторожней с этим, сидюк может взорваться если что не так напишешь

зы дельфийский код естессно тебе никто писать не будет, поищи готовые модули, наверняка они есть
Вячеслав ВласовГуру (3678) 7 месяцев назад
В принципе, можно остановиться пока и на powershell. Только с Win32_CDROMDrive я, можно сказать, почти не работал. Название привода, тома и объем записанных данных как получить я разобрался. А вот эти IOCTL как правильно вызвать? Как я вижу, в них вроде и кроется ответ.
Вячеслав ВласовГуру (3678) 7 месяцев назад
И насчет дельфийского кода. Я тут нашел вот это:
https://web.archive.org/web/20170101182901/http://delphisite.ru/faq/kak-uznat-proizvoditelya-cddvd
Но он спотыкается на строке
 while (Enum.(1, TempObj, Value) = S_OK) do 
Сам туплю от такой конструкции с точкой.
СКОРОЖАРКА!!! Гуру (3283) Вячеслав Власов, ну я 5 мин погуглил и нашел либу такую https://github.com/NeftaliDelphi/GLibWMI
Роман Данилов Мудрец (10941) 7 месяцев назад
У NERO в комплекте есть консольная утилита, которую можно запускать в режиме командной строки. По идее, она должна уметь в такие вещи. Надо вызвать встроенную справку, посмотреть как опросить носитель, а потом такую же команду запустить из вашей дельфи-программы, перехватив вывод этой команды, после чего извлечь оттуда данные, которые вам нужны.
Вячеслав ВласовГуру (3678) 7 месяцев назад
Нашел, но он жалуется на отсутствие AdvrCntr6.dll. Уже куда только его не закидывал. Может как-то зарегистрировать его надо?
Похожие вопросы