В данной статье будут рассмотрены некоторые моменты, которые позволят установить, обновить, деинсталировать и прописать программу в автозагрузку.
Для создания инсталлятора в Inno Setup используются скрипты, в которых и прописывается весь алгоритм установки и удаления программы. Далее подробно опишем каждый блок кода скрипта, и в итоге получим готовый универсальный скрипт.
1. Определяем директивы
#define MyAppName "Наименование приложения" #define MyAppVersion "0.1" #define MyAppPublisher "Автор" #define MyAppURL "http://www.сайт проекта.org" #define MyAppExeName "Наименование.exe"
Мы определили наименование программы, текущую версию, имя компании или лица, кто разработал программу, сайт и наименование исполняемого файла.
2. Блок кода "Setup"
AppId={{0633B77F-A148-49B9-BF2E-21469B353423} - Значение AppId идентифицирует этого приложения и прописывается при установки в реестр. Нельзя использовать одно и тоже значение AppId для разных приложений.
AppName={#MyAppName} - имя приложения.
AppVersion={#MyAppVersion} - версия программы.
AppPublisher={#MyAppPublisher} - имя собственника программы.
AppPublisherURL={#MyAppURL} - ссылка на сайт собственника программы.
AppSupportURL={#MyAppURL} - ссылка на страницу тех. поддержки.
AppUpdatesURL={#MyAppURL} - ссылка на страницу обновлений.
DefaultDirName={pf}\{#MyAppName} - путь, куда будет установлена программа, {pf} - Program Files.
DefaultGroupName={#MyAppName} - папка с названием программы.
LicenseFile=C:\project\LICENSE - путь к лицензии.
OutputBaseFilename=Имя программы 0.2 - имя инсталлятора.
SetupIconFile=C:\project\Имя программы.ico - иконка для инсталлятора.
Compression=lzma - параметр, указывающий алгоритм сжатия, при создании инсталлятора.
SolidCompression=yes - создавать или нет непрерывный архив.
3. Блок кода "Languages"
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
Inno Setup поддерживает множество языков, которые можно подключить в этом блоке кода, после чего установка будет идти на языке в зависимости от локализации windows.
4. Блок кода "Tasks"
Здесь можно указать, куда дополнительно поместить иконку программы, рабочий стол, панель быстрого запуска. При этом пользователю предоставится выбор, поместить туда иконку или нет.
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
5. Блок кода "Files"
Source: "C:\project\name.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\project\file1.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\project\file2.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\project\src\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Первые три строчки являются ссылками на исполняемый файл и файлы библиотек, последняя строчка является ссылкой на директорию, recursesubdirs и createallsubdirs параметры означают, что будут включены все файлы и папки лежащие уровнем ниже.
6. Блок кода "Icons"
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon Name: "{commonstartup}\Имя приложения"; Filename: "{app}\{#MyAppExeName}"
Назначение блока выходит из названия, указываются места, куда будут прописаны иконки с программой, это список программ на удаление, рабочий стол, панель быстрого запуска, и в последней строке приложение прописывается в автозагрузку.
7. Блок кода "Run"
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, "&", "&&")}}"; Flags: nowait postinstall skipifsilent
Указывается путь и параметры запуска программы после установки.
8. Блок кода "Code"
Это самая интересная часть. Здесь прописываются различные пользовательские скрипты, что делать до установки, например определить установлена ли уже эта программа или нет, и вывести соответствующее сообщение, также можно определить множество других действий, во время установки программы, после установки, перед деинсталяцией.
Мы напишем код, который будет работать перед установкой программы и перед ее удалением.
Определимся, что нам необходимо для нормального функционирования инсталлятора.
- Перед установкой, если уже установлена старая версия программы, то ее необходимо удалить.
- Перед удалением необходимо просмотреть список запущенных программ и если наша в этом списке имеется, то ее надо закрыть.
const WM_CLOSE = 16; function ProcessRunning(): Boolean; var winHwnd: longint; retVal : boolean; strProg: string; begin Result := true; try strProg := 'Vertaler'; winHwnd := FindWindowByWindowName(strProg); Log('winHwnd: ' + inttostr(winHwnd)); if winHwnd <> 0 then retVal:=postmessage(winHwnd,WM_CLOSE,0,0); if retVal then Result := True except end; end;
В этой части прописано, если установлена старая версия программы, то она удаляется.
function InitializeSetup : Boolean; begin Result := ProcessRunning(); end; function InitializeUninstall: Boolean; begin Result := ProcessRunning(); end; function GetUninstallString(): String; var sUnInstPath: String; sUnInstallString: String; begin sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1'); sUnInstallString := ''; if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); Result := sUnInstallString; end; function IsUpgrade(): Boolean; begin Result := (GetUninstallString() <> ''); end; function UnInstallOldVersion(): Integer; var sUnInstallString: String; iResultCode: Integer; begin // Return Values: // 1 - uninstall string is empty // 2 - error executing the UnInstallString // 3 - successfully executed the UnInstallString // default return value Result := 0; // get the uninstall string of the old app sUnInstallString := GetUninstallString(); if sUnInstallString <> '' then begin sUnInstallString := RemoveQuotes(sUnInstallString); if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then Result := 3 else Result := 2; end else Result := 1; end; procedure CurStepChanged(CurStep: TSetupStep); begin if (CurStep=ssInstall) then begin if (IsUpgrade()) then begin UnInstallOldVersion(); end; end; end;
Ну и теперь весь код скрипта.
#define MyAppName "Наименование приложения"
#define MyAppVersion "0.2" #define MyAppPublisher "Автор" #define MyAppURL "http://www.сайт проекта.org" #define MyAppExeName "Наименование.exe"
[Setup]
AppId={{0633B77F-A148-49B9-BF2E-21469B353423}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
LicenseFile=C:\project\LICENSE
OutputBaseFilename=Имя программы 0.2
SetupIconFile=C:\project\Имя программы.ico
Compression=lzma
SolidCompression=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
[Files]
Source: "C:\project\name.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\project\file1.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\project\file2.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\project\src\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: quicklaunchicon Name: "{commonstartup}\Имя приложения"; Filename: "{app}\{#MyAppExeName}"
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, "&", "&&")}}"; Flags: nowait postinstall skipifsilent
[Code]
const WM_CLOSE = 16; function ProcessRunning(): Boolean; var winHwnd: longint; retVal : boolean; strProg: string; begin Result := true; try strProg := 'Vertaler'; winHwnd := FindWindowByWindowName(strProg); Log('winHwnd: ' + inttostr(winHwnd)); if winHwnd <> 0 then retVal:=postmessage(winHwnd,WM_CLOSE,0,0); if retVal then Result := True except end; end;
function InitializeSetup : Boolean; begin Result := ProcessRunning(); end; function InitializeUninstall: Boolean; begin Result := ProcessRunning(); end; function GetUninstallString(): String; var sUnInstPath: String; sUnInstallString: String; begin sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1'); sUnInstallString := ''; if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); Result := sUnInstallString; end; function IsUpgrade(): Boolean; begin Result := (GetUninstallString() <> ''); end; function UnInstallOldVersion(): Integer; var sUnInstallString: String; iResultCode: Integer; begin // Return Values: // 1 - uninstall string is empty // 2 - error executing the UnInstallString // 3 - successfully executed the UnInstallString // default return value Result := 0; // get the uninstall string of the old app sUnInstallString := GetUninstallString(); if sUnInstallString <> '' then begin sUnInstallString := RemoveQuotes(sUnInstallString); if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then Result := 3 else Result := 2; end else Result := 1; end; procedure CurStepChanged(CurStep: TSetupStep); begin if (CurStep=ssInstall) then begin if (IsUpgrade()) then begin UnInstallOldVersion(); end; end; end;
Код нерабочий и неполноценный. Пропущены фигурная скобочка и точка с запятой и ещё что-то очень важное для понимания принципа работы.
ОтветитьУдалитьДля чего нужны процедура CurStepChanged, функции InitializeSetup и InitializeUninstall, если они нигде в тексте не используются?
Самостоятельно InnoSetup указанные функции не цепляет, соответственно не происходят ни деинсталляция предыдущей программы, ни завершение активного процесса, а установщик требует перезагрузку.
Неплохой обзор. Вообще, при создании инсталляторов есть ряд тонкостей. Все очень сильно зависит от того, что должен уметь инсталлятор.
ОтветитьУдалитьЕсли вам интересно, то еще несколько бесплатных аналогов можно найти в обзоре по адресу http://ida-freewares.ru/programming/7-best-free-program-setup-builder.html
Пригодилось, спасибо!
ОтветитьУдалитьСпасибо, пригодилось!
ОтветитьУдалить