Здравствуйте друзья! Призываю коллективный разум к помощи.
Как обычно наспех решаю небольшую задачу, в частности массовая запись подпапок из выбранной папки на диски (CD).
Тема в интернетах освещена довольно скудно, но удалось найти статейку по imapi2 от MS, которая и была взята за основу.
В целом получается всё, за одним небольшим исключением. После старта записи, мне нужно проверить что всё подходит для записи и если нет, то запросить смену диска и т.п. и сделать то же самое в цикле который пишет диски из массива папок, при этом нужно чтобы всё это дело ожидало вставки диска, проверяло его и соответственно либо продолжало итерацию, либо снова выплёвывало диск и ждало по новой.
Первоначальную проверку сделал на onClick кнопки записи, через exception,
а вот что делать в цикле ума не приложу, вроде как и исключение там не в тему, вроде и в библиотечках нету ничего что бы возвращало всё ОК или неОК. В общем вот код, думаю всё станет понятно.
Импортированы библиотеки типов:
Microsoft IMAPI2 Base Functionality
Microsoft IMAPI2 File System Image Creator
Из них использованы компоненты:
TMsftDiscMaster2
TMsftDiscRecorder2
TMsftFileSystemImage
TMsftDiscFormat2Data
Код:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, Winapi.ActiveX, System.SysUtils,
System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Vcl.OleServer, Vcl.StdCtrls, Vcl.FileCtrl, Vcl.Menus,
Vcl.ComCtrls, IMAPI2_TLB, IMAPI2FS_TLB, System.Win.ComObj;
type
Compare_Media_State = TOleEnum;
const
Compare_Media_State_UNKNOWN = $00000000;
Compare_Media_State_INFORMATIONAL_MASK = $0000000F;
Compare_Media_State_UNSUPPORTED_MASK = $0000FC00;
Compare_Media_State_OVERWRITE_ONLY = $00000001;
Compare_Media_State_STATE_RANDOMLY_WRITABLE = $00000001;
Compare_Media_State_BLANK = $00000002;
Compare_Media_State_APPENDABLE = $00000004;
Compare_Media_State_FINAL_SESSION = $00000008;
Compare_Media_State_DAMAGED = $00000400;
Compare_Media_State_ERASE_REQUIRED = $00000800;
Compare_Media_State_NON_EMPTY_SESSION = $00001000;
Compare_Media_State_WRITE_PROTECTED = $00002000;
Compare_Media_State_FINALIZED = $00004000;
Compare_Media_State_UNSUPPORTED_MEDIA = $00008000;
type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
Button1: TButton;
RecorderComboBox: TComboBox;
Button2: TButton;
Edit1: TEdit;
Memo1: TMemo;
GroupBox2: TGroupBox;
MainMenu1: TMainMenu;
Vty1: TMenuItem;
N1: TMenuItem;
StatusBar1: TStatusBar;
Label1: TLabel;
TrackBar1: TTrackBar;
Label2: TLabel;
Button3: TButton;
MsftDiscMaster: TMsftDiscMaster2;
MsftDiscRecorder: TMsftDiscRecorder2;
MsftFileSystemImage: TMsftFileSystemImage;
MsftDiscFormat2Data: TMsftDiscFormat2Data;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure N1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
//Count copies of each folder.
countCopy : integer;
//Arrays is a folder-trees to write and to naming in log.
treeToWrite, treeToName : array of string;
const
cap = 10;
implementation
{$R *.dfm}
//Update recorder-list button.
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
RecorderComboBox.Clear;
for i := 0 to MsftDiscMaster.Count-1 do
begin
try
MsftDiscRecorder.InitializeDiscRecorder(MsftDiscMaster.Item[i]);
RecorderComboBox.Items.Add(MsftDiscRecorder.VendorId+' '+
MsftDiscRecorder.ProductId);
MsftDiscRecorder.Disconnect;
except
RecorderComboBox.Items.Add('---');
end;
end;
RecorderComboBox.ItemIndex:=0;
end;
//Choose-directory button.
//If folder choosen, then writing subfolders to array used 4 writing & naming.
procedure TForm1.Button2Click(Sender: TObject);
var
choosenDirectory:string;
sr: TSearchRec;
i : integer;
begin
Edit1.Clear;
i := 0;
if SelectDirectory('Выберите каталог', '', choosenDirectory) then
begin
Edit1.Text := choosenDirectory;
memo1.Lines.Add('Следующие папки будут записаны:');
if Edit1.Text[Length(Edit1.Text)] <> '\' then
Edit1.Text := Edit1.Text + '\';
if FindFirst(Edit1.Text + '*.*', faAnyFile, sr) = 0 then
repeat
if (sr.Attr and faDirectory) <> 0 then
if (sr.Name <> '.') and (sr.Name <> '..') then
begin
//Setting lenght of arrays
if i = Length(treeToWrite) then SetLength(treeToWrite, i + cap);
if i = Length(treeToName) then SetLength(treeToName, i + cap);
//writing to trees
treeToWrite[i] := Edit1.Text+sr.Name;
treeToName[i] := sr.Name;
//writing to log
memo1.Lines.Add(treeToWrite[i]);
i := i+1;
end;
until (FindNext(sr) <> 0);
FindClose(sr);
end
else ShowMessage('Ошибка каталога! Пожалуйста выберите папку.');
end;
//Writing button.
//Create image 4 record, & writing according copycount.
procedure TForm1.Button3Click(Sender: TObject);
var
DiscRoot : IFsiDirectoryItem;
resimage : IFileSystemImageResult;
DiscStream : IMAPI2_TLB.IStream;
DR : IDiscRecorder2;
i, j : integer;
begin
if RecorderComboBox.Items[RecorderComboBox.ItemIndex]='---' then exit;
if Length(treeToWrite) = 0 then exit;
try
for i := 0 to Length(treeToWrite) do
begin
MsftDiscRecorder.InitializeDiscRecorder(MsftDiscMaster.
Item[RecorderComboBox.ItemIndex]);
DiscRoot:=MsftFileSystemImage.Root;
if DirectoryExists(treeToWrite[i]) then DiscRoot.AddTree(treeToWrite[i],
true);
MsftDiscFormat2Data.Recorder:=MsftDiscRecorder.DefaultInterface;
MsftDiscFormat2Data.ClientName:='IMAPI';
DR:=IDiscRecorder2(MsftDiscRecorder.DefaultInterface);
MsftFileSystemImage.ChooseImageDefaults(DR);
//Setup volume name
MsftFileSystemImage.VolumeName:= treeToName[i];
//Writing volume name to log
memo1.Lines.Add('Имя диска: ' + treeToName[i]);
//Create result image to write
resimage:=MsftFileSystemImage.CreateResultImage;
//Create result stream
DiscStream:=IMAPI2_TLB.IStream(resimage.ImageStream);
memo1.Lines.Add('Подготовка диска завершена.');
for j := 1 to countCopy do
begin
try
memo1.Lines.Add('Запись копии '+IntToStr(j)+' из '+
IntToStr(countCopy));
MsftDiscFormat2Data.Write(DiscStream);
MsftDiscRecorder.EjectMedia;
except on Err : EOleException do
begin
MsftDiscRecorder.EjectMedia;
ShowMessage('Пожалуйста вставьте чистый диск!');
memo1.Lines.Add('Ожидание диска');
repeat
sleep(1000);
until ;
memo1.Lines.Add('Диск вставлен');
j := j-1;
end;
end;
end;
MsftDiscRecorder.Disconnect;
end;
except on Err : EOleException do
begin
ShowMessage('Пожалуйста вставьте корректный диск!');
memo1.Lines.Add('Ошибка диска!');
MsftDiscRecorder.EjectMedia;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i : integer;
begin
//Setup copycount to default value.
countCopy := TrackBar1.Position + 1;
//Initialize recorders on start application
RecorderComboBox.Clear;
for i := 0 to MsftDiscMaster.Count-1 do
begin
try
MsftDiscRecorder.InitializeDiscRecorder(MsftDiscMaster.Item[i]);
RecorderComboBox.Items.Add(MsftDiscRecorder.VendorId+' '
+MsftDiscRecorder.ProductId);
MsftDiscRecorder.Disconnect;
except
RecorderComboBox.Items.Add('---');
end;
end;
RecorderComboBox.ItemIndex:=0;
end;
procedure TForm1.N1Click(Sender: TObject);
begin
Form1.Close;
end;
//Setup copycount manually by changing trackbar position
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
countCopy := TrackBar1.Position + 1;
memo1.Lines.Add('Количество копий каждой папки: ' + IntToStr(countCopy));
end;
end.
ps. Заранее прошу прощения, не знаю как его закатать под спойлер.
Также буду благодарен за любые советы в части улучшения кода/производительности.