Как сделать инсталлятор

Одним из компонентов профессионально написанной программы является инсталлятор — утилита, которая позволяет установить программу на диск. Самый простой способ — воспользоваться готовым инсталлятором, например, InstallShield, поставляемым вместе с Delphi, но интереснее создать такую утилиту средствами Delphi, а заодно обсудить многие практические вопросы. В этом задании мы займемся созданием именно такой утилиты.

Давайте посмотрим на начальные условия. Утилита должна работать в Windows, ее основные функции должны состоять из:

запроса каталога для установки программы и ее компонентов;

копирования файлов;

создания группы в Program Manager или Explorer;

создания иконки для запуска программы;

сохранения необходимых параметров в регистраторе.

Расположим все используемые визуальные компоненты в форме и по мере необходимости будем изменять значение их свойства Visible, т.е. делать их видимыми или невидимыми. Также нам потребуются две глобальные переменные: InstPath типа String, в которую занесем имя каталога для копирования файлов, и Step типа Byte, в которой будет храниться текущий шаг работы программы. Переменная Step необходима для того, чтобы при преждевременном завершении работы программы можно было отменить все произведенные действия. Для этого создадим следующий обработчик нажатия кнопки:

procedure Tform1.Button2Click(Sender: TObject);

Begin

If (Sender AS Tbutton).Caption = ‘Cancel’ Then

Begin

{Предупредить пользователя}

If MessageDlg(‘Вы хотите прервать установку?’), mtWarning,

MbOkCancel, 0) = mrOk

Then

Begin

{Отменить произведенные действия}

Case Step of

1: DoDeleteFiles;

2: DoKillGroup;

3: DoCleanReg;

end;

Close; {завершить программу}

End;

End;

Необходимость проверки значения свойства Caption компонента TButton вызвана тем, что по ходу работы программы мы будем часто изменять его.

 

Шаг1. Определение каталога и копирование файлов

Отображаем начальный экран нашего инсталлятора и ждем нажатия клавиши.

Пользователь может нажать кнопку Next и перейти к первому шагу, либо кнопку Cancel и завершить программу.

Первым шагом будет запрос имени каталога для расположения файлов программы и непосредственное копирование этих файлов. Отметим, что мы активно используем динамическое присвоение методов. Имея всего одну кнопку, названную Next, мы на каждом шаге изменяем ее свойство OnClick, вследствие чего можем вызывать различные обработчики нажатия одной и той же клавиши.

После того как имя каталога введено (в качестве упражнения можно выбрать каталог из списка имеющихся — для этого используются компоненты, расположенные в палитре компонентов на странице System), приступаем к непосредственному копированию необходимых файлов. Так как эта задача сильно зависит от конкретного приложения, предлагаю вам следующий код, который можно дополнить по своему усмотрению:

Примечание : переменная From – это глобальная переменная, указывающая источник файлов для копирования

Procedure Tform1.DoCopyFiles;

{Копирование файлов}

var

SearchRec: TseachRec;

Count: Integer;

Result: Integer;

Begin

{Подсчитаем число файлов и установим максимальный размер индикатора}

Count:=1;

Result := FindFirst(From+’*.*’,faArchive, SearchRec);

While Result=0 do

Begin

Result:=FindNext(SearchRec);

Count := Count + 1;

End;

FindClose(SearchRec);

ProgressBar1.Max:= Count;

{Копируем}

ProgressBar1.Position:=1;

Result:= FindFirst(From + ‘*.*’, faArchive, SearchBec);

CopyOneFile(From+ SearchRec.Name, InstPath.Text + SearchRec.name);

While Result=0 do

Begin

Result:=FindNext(SearchRec);

CopyoneFile(From+Searchrec.name, InstPath+SeachRec.Name);

ProgressBar1.Position:=ProgressBar1.position+1;

End;

FindClose(SeachRec);

End;

{Копирование одного файла}

procedure Tform1.CopyOneFile;

var S,T: TfileStream;

begin

S:=TFileStream.Create(Src, fmOpenRead );

Try

T:=TFileStream.Create(Target, fmOpenWrite or fmCreate);

Try

T.CopyFrom(S,S.Size);

Finally

T.Free;

End;

Finally

S.Free;

End;

Шаг 2. Создание группы и иконки

Для создания группы и иконки в ней воспользуемся компонентом TDDEClientConv. Для осуществления связи с проводником через DDE (а именно, этот механизм используется для создания группы и иконки в ней) необходимо установить следующие свойства этого компонента:

DDEService

Explorer

DDETopic

Explorer

Начнём с того, что предложим пользователю выбрать уже существующую группу либо создать новую.

Необходимый для этого код показан ниже. Отметим, что в этом случае мы программно нажимаем кнопку Next для того, чтобы перейти на следующий шаг.

Procedure Tform1.DoGroups(Sender:Tobject);

Var P:Pchar;

Begin

Gauge1.Visible:= False;

Label1. Visible:= False;

Label2. Visible:= True;

ListBox1.Visible:= True;

Edit2. Visible:= true;

P:= DDEClientConv1.RequestData(‘Groups’);

ListBox1.Items.SetText(P);

ListBox1.Items.Insert(0,’MyApp’);

StrDispose(P);

Button1.OnClick:=ChooseGroup;

{“Программно нажать кнопку Next}

Button1.Click;

Имя группы выбрано, можно ее создать (если таковой не существует) и поместить иконку. Небольшой комментарий к приведенному выше тексту. Чтобы убедиться в том, что создаваемая группа уникальна, попробуем удалить ее (макрос DeleteGroup). Этого не произойдет в том случае, если такая группа не существует. То же самое мы делаем с иконкой, т.к. Explorer позволяет поместить в группу более одной одинаковой иконки. Т.к. мы подошли к финальной фазе, изменяем название кнопки Next на Finish.

Procedure Tform1.DoGroups1(Sender:Tobject);

Var

Macro: String;

Name:String;

Cmd: Array [0..255] of Char;

Begin

Button1.Visible:= False;

Button2.Caption:=’Finish’;

{Удалить группу}

Name:= Edit2.Text;

Macro:= Format(‘[DeleteGroup(%s)]’, [Name])+#13#10;

StrPCopy(Cmd, Macro);

DDEClientConv1.ExecuteMacro(Cmd, False);

{Создать группу}

Name:= Edit2.Text;

Macro:= Format(‘[CreateGroup(%s)]’, [Name])+#13#10;

StrPCopy(Cmd, Macro);

DDEClientConv1.ExecuteMacro(Cmd, False);

 

{Удалить иконку}

Macro:= Format(‘[DeleteItem(%s)]’, [‘My Demo App’])+#13#10;

StrPCopy(Cmd, Macro);

DDEClientConv1.ExecuteMacro(Cmd, False);

{Добавить иконку}

Macro:= Format(‘[AddItem(%s, %s, %s, %s)]’,

[InstPath+‘\MyApp.EXE’, ‘My Demo App’,

InstPath+‘\MyApp.EXE’, ‘0’])+#13#10;

StrPCopy(Cmd, Macro);

DDEClientConv1.ExecuteMacro(Cmd, False);

{Показать группу}

Macro:= Format(‘[ShowGroup(%s, %s)]’,

[Name, ‘7]);

StrPCopy(Cmd, Macro);

DDEClientConv1.ExecuteMacro(Cmd, False);

{ Готово !}

DDEClientConvl. CloseLink;

End:

В результате мы получаем группу и иконку в ней.

В Windows рекомендуется хранить параметры программ в регистраторе. Правила пользования регистратором мы рассматривали в предыдущих заданиях.

Покажем пример подпрограммы работы с регистратором:

Procedure TForml.DoReg;

Const

RegID : String = ‘REGEDIT4’+#13#10;

RegPath: String = '[HKEY_LOCAL_MACHINE\SOFTWARE\';

Var

RegFile : TFileStream;

RegItem: String;

RegCmd : String:

Begin

Regfile:= TfileStream.Create(‘MYAPP. REG', fmCreate);

RegItem:=RegPath+’MуComp\MуApp]’+#13#10;

RegFile.Write(RegID[1], Length(RegID));

RegFile.Write(RegItem[1],Length(RegItem));

RegFile. Free;

{Запустим REGEDIT}

Regcmd:= 'REGEDIT /s '+'MYAPP. REG';

WinExec(Pchar(RegCmd), SW_MINIMIZE);

ShowMessage(‘Done’);

{Удалим временный файл}

If FileExists(‘MYAPP.REG’) Then DeleteFlle(‘MYAPP.REG');

End;

Здесь мы тоже «программно» нажимаем кнопку Finish, что в данном случае приводит к завершению работы программы.

В завершение следует сказать несколько слов по поводу отмены действий, выполненных на том или ином шаге.

Для этого используется переменная Step и код, выполняемый по нажатию клавиши Cancel. Рассмотрим этап копирования файлов. Что делать в случае, когда необходимо отменить выполненные действия? Воспользуемся функциями FindFirst и FindNext для нахождения всех файлов, а удалять файл будем функцией DeleteFile. Процедура для удаления файлов может выглядеть так:

Procedure TForml.DoDeleteFiles;

var

SearchRec : TSearchRec;

Result : Integer;

begin

{Удалим все файлы}

Result:= FindFlrst(InstPath+''*.*'', faArchive, SearchRec);

DeleteFlle(InstPath+SearchRec .Nаmе);

while Result = 0 do

begin

DeleteFile(InstPath+SearchRec. Name);

Result := FindNext(SearchRec);

end;

FindClose(SearchRec);

{И caм каталог}

RmDlr(InstPath);

end;

В случае с группами и иконками можно использовать код, приведенный в процедуре DoGroups1.

Осталось посмотреть, как удалить запись в регистраторе. Для этого воспользуемся стандартной функцией RegDeleteKey. В качестве параметров указываются секция и подсекция. Например, если мы создали подсекцию МуСоmр\МуАрр в секции HKEY_LOCAL_MACHINE\SOFTWARE\, то для удаления этой секция следует применить следующий код:

Procedure Tform1.DoCleanReg;

Begin

RegDeleteKey(HKEY_LOCAL_MACHINE, ‘SOFTWARE\MyComp’);

End;

 

Hosted by uCoz