842 lines
27 KiB
Plaintext
842 lines
27 KiB
Plaintext
#define MyAppName "Inventera"
|
||
#define MyAppVersion "0.1.0-beta"
|
||
#define MyAppPublisher "Inventera"
|
||
#define MyAppExeName "Inventera.Server.exe"
|
||
#define PostgreSqlMajor "18"
|
||
#define PostgreSqlInstaller "installer\prerequisites\postgesql.exe"
|
||
|
||
[Setup]
|
||
AppId={{78BAF0DB-D841-49A7-954C-16DCA688B136}
|
||
AppName={#MyAppName}
|
||
AppVersion={#MyAppVersion}
|
||
AppVerName={#MyAppName} {#MyAppVersion}
|
||
AppPublisher={#MyAppPublisher}
|
||
DefaultDirName={autopf}\{#MyAppName}
|
||
DefaultGroupName={#MyAppName}
|
||
PrivilegesRequired=admin
|
||
OutputDir=dist
|
||
OutputBaseFilename=Inventera
|
||
SetupIconFile=picture\logo\main_logo.ico
|
||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||
Compression=lzma2/ultra64
|
||
SolidCompression=yes
|
||
WizardStyle=modern
|
||
ArchitecturesAllowed=x64
|
||
ArchitecturesInstallIn64BitMode=x64
|
||
CloseApplications=yes
|
||
RestartApplications=no
|
||
DisableProgramGroupPage=yes
|
||
UsePreviousAppDir=yes
|
||
|
||
[Languages]
|
||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||
|
||
[Files]
|
||
Source: "{#PostgreSqlInstaller}"; Flags: dontcopy noencryption nocompression
|
||
Source: "installer\initialize_inventera_database.ps1"; Flags: dontcopy noencryption
|
||
Source: "installer\configure_inventera_autostart.ps1"; Flags: dontcopy noencryption
|
||
Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||
|
||
[INI]
|
||
Filename: "{app}\Inventera.url"; Section: "InternetShortcut"; Key: "URL"; String: "http://127.0.0.1:{code:GetApplicationPort}"
|
||
Filename: "{app}\Inventera.url"; Section: "InternetShortcut"; Key: "IconFile"; String: "{app}\{#MyAppExeName}"
|
||
Filename: "{app}\Inventera.url"; Section: "InternetShortcut"; Key: "IconIndex"; String: "0"
|
||
|
||
[Icons]
|
||
Name: "{group}\Inventera"; Filename: "{app}\Inventera.url"; IconFilename: "{app}\{#MyAppExeName}"; Comment: "Открыть веб-приложение Inventera"
|
||
Name: "{commondesktop}\Inventera"; Filename: "{app}\Inventera.url"; IconFilename: "{app}\{#MyAppExeName}"; Comment: "Открыть веб-приложение Inventera"
|
||
|
||
[InstallDelete]
|
||
Type: files; Name: "{commonstartup}\Inventera Server.lnk"
|
||
|
||
[UninstallDelete]
|
||
Type: files; Name: "{app}\Inventera.url"
|
||
|
||
[Run]
|
||
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall delete rule name=""Inventera Web"""; Flags: runhidden waituntilterminated
|
||
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall add rule name=""Inventera Web"" dir=in action=allow protocol=TCP localport={code:GetApplicationPort}"; Flags: runhidden waituntilterminated
|
||
Filename: "{sys}\schtasks.exe"; Parameters: "/Run /TN ""Inventera Server"""; Flags: runhidden waituntilterminated; StatusMsg: "Запуск сервера Inventera..."
|
||
Filename: "http://127.0.0.1:{code:GetApplicationPort}"; Description: "Открыть Inventera"; Flags: shellexec nowait postinstall skipifsilent
|
||
|
||
[UninstallRun]
|
||
Filename: "{sys}\schtasks.exe"; Parameters: "/Delete /F /TN ""Inventera Server"""; Flags: runhidden waituntilterminated; RunOnceId: "RemoveInventeraAutostart"
|
||
Filename: "{sys}\taskkill.exe"; Parameters: "/F /IM ""{#MyAppExeName}"""; Flags: runhidden waituntilterminated; RunOnceId: "StopInventera"
|
||
Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall delete rule name=""Inventera Web"""; Flags: runhidden waituntilterminated; RunOnceId: "RemoveInventeraFirewallRule"
|
||
|
||
[Code]
|
||
var
|
||
ModePage: TInputOptionWizardPage;
|
||
PostgreSqlInstallPage: TInputOptionWizardPage;
|
||
AdminPage: TInputQueryWizardPage;
|
||
PortsPage: TInputQueryWizardPage;
|
||
DatabasePage: TInputQueryWizardPage;
|
||
ExistingPsqlPage: TInputFileWizardPage;
|
||
AutomaticAdminPassword: String;
|
||
SavedAutomaticStateAvailable: Boolean;
|
||
ExistingInventeraPostgreSql: Boolean;
|
||
ExistingPostgreSqlPort: Integer;
|
||
ExistingPostgreSqlDataDirectory: String;
|
||
ExistingPostgreSqlPsqlPath: String;
|
||
|
||
function IsAutomaticMode: Boolean;
|
||
begin
|
||
Result := ModePage.SelectedValueIndex = 0;
|
||
end;
|
||
|
||
function ShouldInstallPostgreSql: Boolean;
|
||
begin
|
||
Result :=
|
||
(not ExistingInventeraPostgreSql) and
|
||
(IsAutomaticMode or (PostgreSqlInstallPage.SelectedValueIndex = 0));
|
||
end;
|
||
|
||
function GetPostgreSqlPort(Param: String): String;
|
||
begin
|
||
Result := Trim(PortsPage.Values[0]);
|
||
end;
|
||
|
||
function GetApplicationPort(Param: String): String;
|
||
begin
|
||
Result := Trim(PortsPage.Values[1]);
|
||
end;
|
||
|
||
function GetDatabaseName: String;
|
||
begin
|
||
if IsAutomaticMode then
|
||
Result := 'Inv_Web'
|
||
else
|
||
Result := Trim(DatabasePage.Values[0]);
|
||
end;
|
||
|
||
function GetDatabaseUser: String;
|
||
begin
|
||
if IsAutomaticMode then
|
||
Result := 'invwebuser'
|
||
else
|
||
Result := Trim(DatabasePage.Values[1]);
|
||
end;
|
||
|
||
function GetDatabasePassword: String;
|
||
begin
|
||
if IsAutomaticMode then
|
||
Result := 'invwebpassword'
|
||
else
|
||
Result := DatabasePage.Values[2];
|
||
end;
|
||
|
||
function GetAdminUser: String;
|
||
begin
|
||
if IsAutomaticMode then
|
||
Result := 'postgres'
|
||
else
|
||
Result := Trim(AdminPage.Values[0]);
|
||
end;
|
||
|
||
function GetAdminPassword: String;
|
||
begin
|
||
if IsAutomaticMode then
|
||
Result := AutomaticAdminPassword
|
||
else
|
||
Result := AdminPage.Values[1];
|
||
end;
|
||
|
||
function QuoteArgument(const Value: String): String;
|
||
begin
|
||
Result := '"' + Value + '"';
|
||
end;
|
||
|
||
function GenerateAutomaticPassword: String;
|
||
var
|
||
I: Integer;
|
||
Characters: String;
|
||
begin
|
||
Characters := 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#_-';
|
||
Result := 'Iv!';
|
||
for I := 1 to 29 do
|
||
Result := Result + Characters[Random(Length(Characters)) + 1];
|
||
end;
|
||
|
||
function FindExistingPsql: String;
|
||
var
|
||
Candidate: String;
|
||
begin
|
||
Result := '';
|
||
Candidate := ExpandConstant('{autopf}\PostgreSQL\18\bin\psql.exe');
|
||
if FileExists(Candidate) then begin Result := Candidate; Exit; end;
|
||
Candidate := ExpandConstant('{autopf}\PostgreSQL\17\bin\psql.exe');
|
||
if FileExists(Candidate) then begin Result := Candidate; Exit; end;
|
||
Candidate := ExpandConstant('{autopf}\PostgreSQL\16\bin\psql.exe');
|
||
if FileExists(Candidate) then begin Result := Candidate; Exit; end;
|
||
Candidate := ExpandConstant('{autopf}\PostgreSQL\15\bin\psql.exe');
|
||
if FileExists(Candidate) then begin Result := Candidate; Exit; end;
|
||
Candidate := ExpandConstant('{autopf}\PostgreSQL\14\bin\psql.exe');
|
||
if FileExists(Candidate) then begin Result := Candidate; Exit; end;
|
||
Candidate := ExpandConstant('{autopf}\PostgreSQL\13\bin\psql.exe');
|
||
if FileExists(Candidate) then begin Result := Candidate; Exit; end;
|
||
end;
|
||
|
||
function GetPsqlPath: String;
|
||
begin
|
||
if ExistingInventeraPostgreSql then
|
||
Result := ExistingPostgreSqlPsqlPath
|
||
else if ShouldInstallPostgreSql then
|
||
Result := ExpandConstant('{autopf}\PostgreSQL\{#PostgreSqlMajor}\bin\psql.exe')
|
||
else
|
||
Result := Trim(ExistingPsqlPage.Values[0]);
|
||
end;
|
||
|
||
function IsValidPort(const Value: String; var PortNumber: Integer): Boolean;
|
||
begin
|
||
Result := False;
|
||
PortNumber := 0;
|
||
if Trim(Value) = '' then
|
||
Exit;
|
||
|
||
try
|
||
PortNumber := StrToInt(Trim(Value));
|
||
except
|
||
PortNumber := 0;
|
||
Exit;
|
||
end;
|
||
|
||
Result := (PortNumber >= 1) and (PortNumber <= 65535);
|
||
end;
|
||
|
||
function IsValidIdentifier(const Value: String): Boolean;
|
||
var
|
||
I: Integer;
|
||
AllowedFirst: String;
|
||
AllowedRest: String;
|
||
begin
|
||
Result := False;
|
||
if Value = '' then
|
||
Exit;
|
||
|
||
AllowedFirst := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_';
|
||
AllowedRest := AllowedFirst + '0123456789';
|
||
if Pos(Value[1], AllowedFirst) = 0 then
|
||
Exit;
|
||
|
||
for I := 2 to Length(Value) do
|
||
if Pos(Value[I], AllowedRest) = 0 then
|
||
Exit;
|
||
|
||
Result := True;
|
||
end;
|
||
|
||
function IsSafePassword(const Value: String): Boolean;
|
||
begin
|
||
Result := (Value <> '') and
|
||
(Pos('"', Value) = 0) and
|
||
(Pos(#13, Value) = 0) and
|
||
(Pos(#10, Value) = 0);
|
||
end;
|
||
|
||
function IsTcpPortAvailable(PortNumber: Integer): Boolean;
|
||
var
|
||
PowerShellPath: String;
|
||
Parameters: String;
|
||
ExitCode: Integer;
|
||
begin
|
||
PowerShellPath := ExpandConstant('{sys}\WindowsPowerShell\v1.0\powershell.exe');
|
||
Parameters :=
|
||
'-NoProfile -NonInteractive -ExecutionPolicy Bypass -Command ' +
|
||
'"$listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, ' +
|
||
IntToStr(PortNumber) +
|
||
'); try { $listener.Start(); $listener.Stop(); exit 0 } catch { exit 1 }"';
|
||
|
||
Result := Exec(
|
||
PowerShellPath,
|
||
Parameters,
|
||
'',
|
||
SW_HIDE,
|
||
ewWaitUntilTerminated,
|
||
ExitCode
|
||
) and (ExitCode = 0);
|
||
end;
|
||
|
||
function TryReadPostgreSqlPort(
|
||
const DataDirectory: String;
|
||
var PortNumber: Integer
|
||
): Boolean;
|
||
var
|
||
Lines: TArrayOfString;
|
||
I: Integer;
|
||
EqualsPosition: Integer;
|
||
CommentPosition: Integer;
|
||
Line: String;
|
||
Value: String;
|
||
begin
|
||
Result := False;
|
||
PortNumber := 0;
|
||
|
||
if not LoadStringsFromFile(
|
||
AddBackslash(DataDirectory) + 'postgresql.conf',
|
||
Lines
|
||
) then
|
||
Exit;
|
||
|
||
for I := 0 to GetArrayLength(Lines) - 1 do
|
||
begin
|
||
Line := Trim(Lines[I]);
|
||
if (Line <> '') and (Copy(Line, 1, 1) <> '#') and
|
||
(Copy(Lowercase(Line), 1, 4) = 'port') then
|
||
begin
|
||
EqualsPosition := Pos('=', Line);
|
||
if EqualsPosition > 0 then
|
||
begin
|
||
Value := Trim(Copy(Line, EqualsPosition + 1, Length(Line)));
|
||
CommentPosition := Pos('#', Value);
|
||
if CommentPosition > 0 then
|
||
Value := Trim(Copy(Value, 1, CommentPosition - 1));
|
||
Value := RemoveQuotes(Value);
|
||
|
||
if IsValidPort(Value, PortNumber) then
|
||
begin
|
||
Result := True;
|
||
Exit;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function LoadAutomaticInstallerState: Boolean;
|
||
var
|
||
SavedPassword: String;
|
||
SavedPort: String;
|
||
begin
|
||
Result := False;
|
||
SavedPassword := '';
|
||
SavedPort := '';
|
||
|
||
if RegQueryStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlAdminPassword',
|
||
SavedPassword
|
||
) and IsSafePassword(SavedPassword) then
|
||
begin
|
||
AutomaticAdminPassword := SavedPassword;
|
||
Result := True;
|
||
end;
|
||
|
||
if RegQueryStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlPort',
|
||
SavedPort
|
||
) then
|
||
IsValidPort(SavedPort, ExistingPostgreSqlPort);
|
||
end;
|
||
|
||
function SaveAutomaticInstallerState: Boolean;
|
||
begin
|
||
Result := RegWriteStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlAdminUser',
|
||
GetAdminUser
|
||
);
|
||
|
||
if Result then
|
||
Result := RegWriteStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlAdminPassword',
|
||
GetAdminPassword
|
||
);
|
||
|
||
if Result then
|
||
Result := RegWriteStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlPort',
|
||
GetPostgreSqlPort('')
|
||
);
|
||
|
||
if Result then
|
||
Result := RegWriteStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlDataDirectory',
|
||
ExistingPostgreSqlDataDirectory
|
||
);
|
||
|
||
if Result then
|
||
Result := RegWriteStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlPsqlPath',
|
||
ExistingPostgreSqlPsqlPath
|
||
);
|
||
|
||
if Result then
|
||
SavedAutomaticStateAvailable := True
|
||
else
|
||
Log('Не удалось сохранить параметры автоматической установки PostgreSQL.');
|
||
end;
|
||
|
||
procedure DetectExistingInventeraPostgreSql;
|
||
var
|
||
SavedPort: String;
|
||
begin
|
||
ExistingPostgreSqlDataDirectory :=
|
||
ExpandConstant('{autopf}\PostgreSQL\{#PostgreSqlMajor}\data');
|
||
ExistingPostgreSqlPsqlPath :=
|
||
ExpandConstant('{autopf}\PostgreSQL\{#PostgreSqlMajor}\bin\psql.exe');
|
||
|
||
ExistingInventeraPostgreSql :=
|
||
RegKeyExists(
|
||
HKLM,
|
||
'SYSTEM\CurrentControlSet\Services\InventeraPostgreSQL{#PostgreSqlMajor}'
|
||
) and FileExists(ExistingPostgreSqlPsqlPath);
|
||
|
||
if ExistingInventeraPostgreSql then
|
||
begin
|
||
if not TryReadPostgreSqlPort(
|
||
ExistingPostgreSqlDataDirectory,
|
||
ExistingPostgreSqlPort
|
||
) then
|
||
begin
|
||
SavedPort := '';
|
||
if RegQueryStringValue(
|
||
HKLM64,
|
||
'Software\Inventera\Installer',
|
||
'PostgreSqlPort',
|
||
SavedPort
|
||
) then
|
||
IsValidPort(SavedPort, ExistingPostgreSqlPort);
|
||
end;
|
||
|
||
if ExistingPostgreSqlPort = 0 then
|
||
ExistingPostgreSqlPort := 5432;
|
||
|
||
Log(
|
||
'Обнаружена существующая служба PostgreSQL Inventera. Порт: ' +
|
||
IntToStr(ExistingPostgreSqlPort)
|
||
);
|
||
end;
|
||
end;
|
||
|
||
procedure InitializeWizard;
|
||
begin
|
||
ExistingPostgreSqlPort := 0;
|
||
AutomaticAdminPassword := '';
|
||
SavedAutomaticStateAvailable := LoadAutomaticInstallerState;
|
||
if AutomaticAdminPassword = '' then
|
||
AutomaticAdminPassword := GenerateAutomaticPassword;
|
||
DetectExistingInventeraPostgreSql;
|
||
|
||
ModePage := CreateInputOptionPage(
|
||
wpWelcome,
|
||
'Режим установки',
|
||
'Выберите способ настройки Inventera',
|
||
'Автоматический режим использует готовые параметры базы. Ручной режим позволяет изменить их.',
|
||
True,
|
||
False
|
||
);
|
||
ModePage.Add('Автоматический');
|
||
ModePage.Add('Ручной');
|
||
ModePage.SelectedValueIndex := 0;
|
||
|
||
PostgreSqlInstallPage := CreateInputOptionPage(
|
||
ModePage.ID,
|
||
'Установка PostgreSQL',
|
||
'Нужно ли установить PostgreSQL?',
|
||
'Выберите «Нет», только если PostgreSQL уже установлен и доступен на этом компьютере.',
|
||
True,
|
||
False
|
||
);
|
||
PostgreSqlInstallPage.Add('Да, установить PostgreSQL из комплекта Inventera');
|
||
PostgreSqlInstallPage.Add('Нет, использовать существующий PostgreSQL');
|
||
if ExistingInventeraPostgreSql then
|
||
PostgreSqlInstallPage.SelectedValueIndex := 1
|
||
else
|
||
PostgreSqlInstallPage.SelectedValueIndex := 0;
|
||
|
||
AdminPage := CreateInputQueryPage(
|
||
PostgreSqlInstallPage.ID,
|
||
'Администратор PostgreSQL',
|
||
'Укажите учётную запись администратора',
|
||
'Эта учётная запись нужна только для создания базы и пользователя Inventera.'
|
||
);
|
||
AdminPage.Add('Логин администратора PostgreSQL:', False);
|
||
AdminPage.Add('Пароль администратора PostgreSQL:', True);
|
||
AdminPage.Values[0] := 'postgres';
|
||
|
||
PortsPage := CreateInputQueryPage(
|
||
AdminPage.ID,
|
||
'Сетевые порты',
|
||
'Укажите порты PostgreSQL и Inventera',
|
||
'PostgreSQL и веб-приложение используют разные порты. Установщик проверит, что нужные порты свободны.'
|
||
);
|
||
PortsPage.Add('Порт PostgreSQL:', False);
|
||
PortsPage.Add('Порт веб-приложения Inventera:', False);
|
||
if ExistingInventeraPostgreSql then
|
||
begin
|
||
PortsPage.Values[0] := IntToStr(ExistingPostgreSqlPort);
|
||
PortsPage.Edits[0].Enabled := False;
|
||
end
|
||
else if ExistingPostgreSqlPort > 0 then
|
||
PortsPage.Values[0] := IntToStr(ExistingPostgreSqlPort)
|
||
else
|
||
PortsPage.Values[0] := '5432';
|
||
PortsPage.Values[1] := '5050';
|
||
|
||
DatabasePage := CreateInputQueryPage(
|
||
PortsPage.ID,
|
||
'База данных Inventera',
|
||
'Укажите имя базы и учётную запись приложения',
|
||
'Предлагаемые значения уже заполнены и могут быть изменены.'
|
||
);
|
||
DatabasePage.Add('Имя базы данных:', False);
|
||
DatabasePage.Add('Логин пользователя базы:', False);
|
||
DatabasePage.Add('Пароль пользователя базы:', True);
|
||
DatabasePage.Values[0] := 'Inv_Web';
|
||
DatabasePage.Values[1] := 'invwebuser';
|
||
DatabasePage.Values[2] := 'invwebpassword';
|
||
|
||
ExistingPsqlPage := CreateInputFilePage(
|
||
DatabasePage.ID,
|
||
'Расположение PostgreSQL',
|
||
'Укажите psql.exe существующей установки',
|
||
'Файл psql.exe обычно находится в папке C:\Program Files\PostgreSQL\<версия>\bin.'
|
||
);
|
||
ExistingPsqlPage.Add('Путь к psql.exe:', 'Исполняемые файлы|*.exe|Все файлы|*.*', '.exe');
|
||
if ExistingInventeraPostgreSql then
|
||
ExistingPsqlPage.Values[0] := ExistingPostgreSqlPsqlPath
|
||
else
|
||
ExistingPsqlPage.Values[0] := FindExistingPsql;
|
||
end;
|
||
|
||
procedure CurPageChanged(CurPageID: Integer);
|
||
begin
|
||
if CurPageID = PortsPage.ID then
|
||
begin
|
||
if ExistingInventeraPostgreSql then
|
||
begin
|
||
PortsPage.Values[0] := IntToStr(ExistingPostgreSqlPort);
|
||
PortsPage.Edits[0].Enabled := False;
|
||
PortsPage.SubCaptionLabel.Caption :=
|
||
'Обнаружен PostgreSQL Inventera. Его фактический порт определён автоматически ' +
|
||
'и не требует проверки на занятость.';
|
||
end
|
||
else if IsAutomaticMode and SavedAutomaticStateAvailable and
|
||
(ExistingPostgreSqlPort > 0) then
|
||
begin
|
||
PortsPage.Values[0] := IntToStr(ExistingPostgreSqlPort);
|
||
PortsPage.Edits[0].Enabled := False;
|
||
PortsPage.SubCaptionLabel.Caption :=
|
||
'Продолжается предыдущая автоматическая установка. Сохранённый порт PostgreSQL ' +
|
||
'нельзя изменять, чтобы не нарушить подключение к кластеру.';
|
||
end
|
||
else
|
||
begin
|
||
PortsPage.Edits[0].Enabled := True;
|
||
PortsPage.SubCaptionLabel.Caption :=
|
||
'PostgreSQL и веб-приложение используют разные порты. ' +
|
||
'Установщик проверит необходимые свободные порты.';
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
function ShouldSkipPage(PageID: Integer): Boolean;
|
||
begin
|
||
Result := False;
|
||
|
||
if ExistingInventeraPostgreSql and
|
||
((PageID = PostgreSqlInstallPage.ID) or
|
||
(PageID = ExistingPsqlPage.ID)) then
|
||
begin
|
||
Result := True;
|
||
Exit;
|
||
end;
|
||
|
||
if IsAutomaticMode and
|
||
((PageID = PostgreSqlInstallPage.ID) or
|
||
(PageID = AdminPage.ID) or
|
||
(PageID = DatabasePage.ID) or
|
||
(PageID = ExistingPsqlPage.ID)) then
|
||
begin
|
||
Result := True;
|
||
Exit;
|
||
end;
|
||
|
||
if (not IsAutomaticMode) and
|
||
(PageID = ExistingPsqlPage.ID) and
|
||
ShouldInstallPostgreSql then
|
||
begin
|
||
Result := True;
|
||
end;
|
||
end;
|
||
|
||
function NextButtonClick(CurPageID: Integer): Boolean;
|
||
var
|
||
PostgreSqlPort: Integer;
|
||
ApplicationPort: Integer;
|
||
begin
|
||
Result := False;
|
||
|
||
if (CurPageID = ModePage.ID) and IsAutomaticMode and
|
||
ExistingInventeraPostgreSql and
|
||
(not SavedAutomaticStateAvailable) then
|
||
begin
|
||
MsgBox(
|
||
'Обнаружен PostgreSQL Inventera от предыдущей версии установщика, ' +
|
||
'но пароль администратора для него не был сохранён.' + #13#10 + #13#10 +
|
||
'Выберите ручной режим и укажите текущий пароль администратора PostgreSQL ' +
|
||
'либо удалите прежнюю установку PostgreSQL вместе с её каталогом данных ' +
|
||
'перед чистой автоматической установкой.',
|
||
mbError,
|
||
MB_OK
|
||
);
|
||
Exit;
|
||
end;
|
||
|
||
if CurPageID = AdminPage.ID then
|
||
begin
|
||
if not IsValidIdentifier(Trim(AdminPage.Values[0])) then
|
||
begin
|
||
MsgBox('Введите корректный логин администратора PostgreSQL.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
if not IsSafePassword(AdminPage.Values[1]) then
|
||
begin
|
||
MsgBox('Введите пароль администратора. Двойные кавычки и переносы строк недопустимы.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
end;
|
||
|
||
if CurPageID = PortsPage.ID then
|
||
begin
|
||
if not IsValidPort(PortsPage.Values[0], PostgreSqlPort) then
|
||
begin
|
||
MsgBox('Порт PostgreSQL должен быть числом от 1 до 65535.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
if not IsValidPort(PortsPage.Values[1], ApplicationPort) then
|
||
begin
|
||
MsgBox('Порт Inventera должен быть числом от 1 до 65535.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
if PostgreSqlPort = ApplicationPort then
|
||
begin
|
||
MsgBox('PostgreSQL и Inventera не могут использовать один и тот же порт.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
if ShouldInstallPostgreSql and (not IsTcpPortAvailable(PostgreSqlPort)) then
|
||
begin
|
||
MsgBox(
|
||
'Порт PostgreSQL ' + IntToStr(PostgreSqlPort) + ' уже занят. Укажите другой порт.',
|
||
mbError,
|
||
MB_OK
|
||
);
|
||
Exit;
|
||
end;
|
||
if not IsTcpPortAvailable(ApplicationPort) then
|
||
begin
|
||
MsgBox(
|
||
'Порт Inventera ' + IntToStr(ApplicationPort) + ' уже занят. Укажите другой порт.',
|
||
mbError,
|
||
MB_OK
|
||
);
|
||
Exit;
|
||
end;
|
||
end;
|
||
|
||
if CurPageID = DatabasePage.ID then
|
||
begin
|
||
if not IsValidIdentifier(Trim(DatabasePage.Values[0])) then
|
||
begin
|
||
MsgBox('Имя базы может содержать только латинские буквы, цифры и знак подчёркивания.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
if not IsValidIdentifier(Trim(DatabasePage.Values[1])) then
|
||
begin
|
||
MsgBox('Логин базы может содержать только латинские буквы, цифры и знак подчёркивания.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
if not IsSafePassword(DatabasePage.Values[2]) then
|
||
begin
|
||
MsgBox('Введите пароль базы. Двойные кавычки и переносы строк недопустимы.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
end;
|
||
|
||
if CurPageID = ExistingPsqlPage.ID then
|
||
begin
|
||
if not FileExists(Trim(ExistingPsqlPage.Values[0])) then
|
||
begin
|
||
MsgBox('Укажите существующий файл psql.exe.', mbError, MB_OK);
|
||
Exit;
|
||
end;
|
||
end;
|
||
|
||
Result := True;
|
||
end;
|
||
|
||
function PostgreSqlInstallParameters: String;
|
||
var
|
||
Prefix: String;
|
||
begin
|
||
Prefix := ExpandConstant('{autopf}\PostgreSQL\{#PostgreSqlMajor}');
|
||
Result :=
|
||
'--mode unattended --unattendedmodeui minimal ' +
|
||
'--enable-components server,commandlinetools ' +
|
||
'--prefix ' + QuoteArgument(Prefix) + ' ' +
|
||
'--datadir ' + QuoteArgument(Prefix + '\data') + ' ' +
|
||
'--serverport ' + GetPostgreSqlPort('') + ' ' +
|
||
'--servicename InventeraPostgreSQL{#PostgreSqlMajor} ' +
|
||
'--superaccount ' + QuoteArgument(GetAdminUser) + ' ' +
|
||
'--superpassword ' + QuoteArgument(GetAdminPassword) + ' ' +
|
||
'--servicepassword ' + QuoteArgument(GetAdminPassword) + ' ' +
|
||
'--create_shortcuts 0';
|
||
end;
|
||
|
||
function DatabaseInitializationParameters: String;
|
||
begin
|
||
Result :=
|
||
'-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' +
|
||
QuoteArgument(ExpandConstant('{tmp}\initialize_inventera_database.ps1')) + ' ' +
|
||
'-PsqlPath ' + QuoteArgument(GetPsqlPath) + ' ' +
|
||
'-AdminUser ' + QuoteArgument(GetAdminUser) + ' ' +
|
||
'-AdminPassword ' + QuoteArgument(GetAdminPassword) + ' ' +
|
||
'-PostgreSqlPort ' + GetPostgreSqlPort('') + ' ' +
|
||
'-DatabaseName ' + QuoteArgument(GetDatabaseName) + ' ' +
|
||
'-DatabaseUser ' + QuoteArgument(GetDatabaseUser) + ' ' +
|
||
'-DatabasePassword ' + QuoteArgument(GetDatabasePassword) + ' ' +
|
||
'-ApplicationPort ' + GetApplicationPort('') + ' ' +
|
||
'-ConfigPath ' + QuoteArgument(ExpandConstant('{commonappdata}\Inventera\config.json'));
|
||
end;
|
||
|
||
function AutostartConfigurationParameters: String;
|
||
begin
|
||
Result :=
|
||
'-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' +
|
||
QuoteArgument(ExpandConstant('{tmp}\configure_inventera_autostart.ps1')) + ' ' +
|
||
'-ExecutablePath ' + QuoteArgument(ExpandConstant('{app}\{#MyAppExeName}')) + ' ' +
|
||
'-WorkingDirectory ' + QuoteArgument(ExpandConstant('{app}'));
|
||
end;
|
||
|
||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||
var
|
||
ExitCode: Integer;
|
||
IgnoreExitCode: Integer;
|
||
Success: Boolean;
|
||
PowerShellPath: String;
|
||
PostgreSqlPort: Integer;
|
||
ApplicationPort: Integer;
|
||
begin
|
||
Result := '';
|
||
NeedsRestart := False;
|
||
|
||
Exec(
|
||
ExpandConstant('{sys}\taskkill.exe'),
|
||
'/F /IM "{#MyAppExeName}"',
|
||
'',
|
||
SW_HIDE,
|
||
ewWaitUntilTerminated,
|
||
IgnoreExitCode
|
||
);
|
||
|
||
if not IsValidPort(GetPostgreSqlPort(''), PostgreSqlPort) or
|
||
not IsValidPort(GetApplicationPort(''), ApplicationPort) then
|
||
begin
|
||
Result := 'Указаны некорректные сетевые порты.';
|
||
Exit;
|
||
end;
|
||
|
||
if ShouldInstallPostgreSql and (not IsTcpPortAvailable(PostgreSqlPort)) then
|
||
begin
|
||
Result := 'Порт PostgreSQL ' + IntToStr(PostgreSqlPort) + ' уже занят.';
|
||
Exit;
|
||
end;
|
||
|
||
if not IsTcpPortAvailable(ApplicationPort) then
|
||
begin
|
||
Result := 'Порт Inventera ' + IntToStr(ApplicationPort) + ' уже занят.';
|
||
Exit;
|
||
end;
|
||
|
||
if ExistingInventeraPostgreSql then
|
||
begin
|
||
WizardForm.PreparingLabel.Caption :=
|
||
'Запуск существующей службы PostgreSQL Inventera...';
|
||
Exec(
|
||
ExpandConstant('{sys}\sc.exe'),
|
||
'start InventeraPostgreSQL{#PostgreSqlMajor}',
|
||
'',
|
||
SW_HIDE,
|
||
ewWaitUntilTerminated,
|
||
IgnoreExitCode
|
||
);
|
||
end;
|
||
|
||
if IsAutomaticMode and (not SaveAutomaticInstallerState) then
|
||
begin
|
||
Result :=
|
||
'Не удалось сохранить служебные параметры PostgreSQL для повторного запуска установки.';
|
||
Exit;
|
||
end;
|
||
|
||
if ShouldInstallPostgreSql then
|
||
begin
|
||
WizardForm.PreparingLabel.Caption :=
|
||
'Установка PostgreSQL. Это может занять несколько минут, пожалуйста, подождите...';
|
||
ExtractTemporaryFile(ExtractFileName(ExpandConstant('{#PostgreSqlInstaller}')));
|
||
Success := Exec(
|
||
ExpandConstant('{tmp}\postgesql.exe'),
|
||
PostgreSqlInstallParameters,
|
||
'',
|
||
SW_SHOW,
|
||
ewWaitUntilTerminated,
|
||
ExitCode
|
||
);
|
||
if (not Success) or (ExitCode <> 0) then
|
||
begin
|
||
Result := 'Не удалось установить PostgreSQL. Код ошибки: ' + IntToStr(ExitCode);
|
||
Exit;
|
||
end;
|
||
end;
|
||
|
||
WizardForm.PreparingLabel.Caption :=
|
||
'Создание базы данных и сохранение настроек Inventera...';
|
||
ExtractTemporaryFile('initialize_inventera_database.ps1');
|
||
PowerShellPath := ExpandConstant('{sys}\WindowsPowerShell\v1.0\powershell.exe');
|
||
Success := Exec(
|
||
PowerShellPath,
|
||
DatabaseInitializationParameters,
|
||
'',
|
||
SW_HIDE,
|
||
ewWaitUntilTerminated,
|
||
ExitCode
|
||
);
|
||
if (not Success) or (ExitCode <> 0) then
|
||
begin
|
||
Result :=
|
||
'Не удалось создать базу данных или сохранить настройки Inventera. Код ошибки: ' +
|
||
IntToStr(ExitCode);
|
||
Exit;
|
||
end;
|
||
|
||
WizardForm.PreparingLabel.Caption :=
|
||
'Настройка автоматического запуска Inventera при старте Windows...';
|
||
ExtractTemporaryFile('configure_inventera_autostart.ps1');
|
||
Success := Exec(
|
||
PowerShellPath,
|
||
AutostartConfigurationParameters,
|
||
'',
|
||
SW_HIDE,
|
||
ewWaitUntilTerminated,
|
||
ExitCode
|
||
);
|
||
if (not Success) or (ExitCode <> 0) then
|
||
begin
|
||
Result :=
|
||
'Не удалось настроить автозапуск Inventera. Код ошибки: ' +
|
||
IntToStr(ExitCode);
|
||
Exit;
|
||
end;
|
||
end;
|