From 15d5e780ee8bd610e34d6662c9acc8cdcb14190d Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 5 Aug 2026 16:15:35 +0300 Subject: [PATCH] Beta_cartrigesg_bd Beta v0.12 --- .DS_Store | Bin 14340 -> 12292 bytes .gitignore | 1 + CLIENT_AGENT_V2_INSTALLER.md | 21 +- build_client_agent_v2_installer_windows.bat | 14 ++ client_agent_v2_installer.iss | 211 +++++++++++++++++++- installer/.DS_Store | Bin 0 -> 8196 bytes installer/configure_rustdesk.ps1 | 113 +++++++++++ installer/prerequisites/README.md | 13 +- picture/.DS_Store | Bin 14340 -> 14340 bytes picture/Setup/.DS_Store | Bin 6148 -> 6148 bytes 10 files changed, 365 insertions(+), 8 deletions(-) create mode 100644 .gitignore create mode 100644 installer/.DS_Store create mode 100644 installer/configure_rustdesk.ps1 diff --git a/.DS_Store b/.DS_Store index d1bccb2b5892ca5a116f0f2f3d771449b4826562..5477ba9c394c493ff3760700acc95b13fe5817e3 100644 GIT binary patch delta 357 zcmZoEXh~3DU|?W$DortDV9)?EIe-{M3-ADmHUmFGfMyTvC9X^6AW`ws>i54y2$X5(PxVAPwWAu`!Y!+hdoxy}3n^~{rF zgoP*17j0xWHPlfsGB%s6E@m&!$&d*&vzVcTA(0^m2vZq~GLy>+l5+BsfbKdwd5)Me zhp3pigrt;|%;w`_vW#LJB0$F=14iWoDGigEC0u+x8KW4J88a9&8M7b?m>8i7Wsx-i z4K4=qu~=OeT$GoSpO+4lW!&5?tk20PxtT}d8@n7+98icAVu%Jekak55qKyaNGf(C> X3FHA<2MRz2AZ@TY$7C8a6H^=jy5B_u delta 203 zcmZokXem%&U|?W$DortDU@!nOIe-{M3-ADmHUMHs|O}V`gGt2LLwXDP{lw diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4b27b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +installer/prerequisites/*.exe diff --git a/CLIENT_AGENT_V2_INSTALLER.md b/CLIENT_AGENT_V2_INSTALLER.md index a3054e6..1e038ca 100644 --- a/CLIENT_AGENT_V2_INSTALLER.md +++ b/CLIENT_AGENT_V2_INSTALLER.md @@ -1,6 +1,15 @@ # Установщик Inv_web Client v2 для Windows -Установщик перед копированием файлов запрашивает: +Установщик поддерживает три режима: + +1. **Автоматический с RustDesk** — устанавливает клиент и RustDesk без задания + собственного сервера. Фиксированный пароль можно задать или оставить пустым. +2. **Ручной с сервером RustDesk** — устанавливает клиент и RustDesk, запрашивает + `Сервер ID`, `Ретранслятор`, публичный `Key` и необязательный фиксированный пароль. +3. **Без RustDesk** — устанавливает только клиент Inv_web и не изменяет уже + установленный RustDesk. + +Во всех режимах установщик также запрашивает: - адрес сервера; - токен клиента. @@ -16,6 +25,13 @@ - Windows 10/11 x64; - Python; - [Inno Setup 6](https://jrsoftware.org/isdl.php). +- официальный установщик RustDesk для Windows x64. + +Перед сборкой переименуйте установщик RustDesk в `rustdesk.exe` и положите его в: + +```text +installer\prerequisites\rustdesk.exe +``` ## Сборка @@ -31,7 +47,8 @@ build_client_agent_v2_installer_windows.bat dist\Inv_web_Client_Setup.exe ``` -Клиент устанавливается без запроса прав администратора в каталог: +Для тихой установки и настройки службы RustDesk мастер запрашивает права +администратора. Клиент устанавливается в каталог: ```text %LOCALAPPDATA%\Programs\Inv_web Client diff --git a/build_client_agent_v2_installer_windows.bat b/build_client_agent_v2_installer_windows.bat index 0325f0f..4bf9ff7 100644 --- a/build_client_agent_v2_installer_windows.bat +++ b/build_client_agent_v2_installer_windows.bat @@ -5,6 +5,7 @@ cd /d "%~dp0" set "SPEC_FILE=client_agent_v2_windows_onefile.spec" set "CLIENT_EXE=dist\Inv_web Client.exe" set "INSTALLER_SCRIPT=client_agent_v2_installer.iss" +set "RUSTDESK_INSTALLER=installer\prerequisites\rustdesk.exe" set "ISCC=%ProgramFiles(x86)%\Inno Setup 6\ISCC.exe" if not exist "%SPEC_FILE%" ( @@ -17,6 +18,19 @@ if not exist "%INSTALLER_SCRIPT%" ( exit /b 1 ) +if not exist "%RUSTDESK_INSTALLER%" ( + echo. + echo ERROR: RustDesk installer was not found. + echo Download the Windows x64 RustDesk installer, rename it to rustdesk.exe and place it here: + echo %~dp0%RUSTDESK_INSTALLER% + exit /b 1 +) + +if not exist "installer\configure_rustdesk.ps1" ( + echo RustDesk configuration script not found: installer\configure_rustdesk.ps1 + exit /b 1 +) + if not exist "%ISCC%" set "ISCC=%ProgramFiles%\Inno Setup 6\ISCC.exe" if not exist "%ISCC%" set "ISCC=%LocalAppData%\Programs\Inno Setup 6\ISCC.exe" if not exist "%ISCC%" for /f "delims=" %%I in ('where ISCC.exe 2^>nul') do set "ISCC=%%I" diff --git a/client_agent_v2_installer.iss b/client_agent_v2_installer.iss index 2099080..52a5492 100644 --- a/client_agent_v2_installer.iss +++ b/client_agent_v2_installer.iss @@ -2,6 +2,7 @@ #define MyAppVersion "2.0" #define MyAppPublisher "Inv_web" #define MyAppExeName "Inv_web Client.exe" +#define RustDeskInstaller "installer\prerequisites\rustdesk.exe" [Setup] AppId={{6F0D1694-CACE-4F7D-97A2-BB01C240775B} @@ -10,7 +11,7 @@ AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} DefaultDirName={localappdata}\Programs\{#MyAppName} DefaultGroupName={#MyAppName} -PrivilegesRequired=lowest +PrivilegesRequired=admin OutputDir=dist OutputBaseFilename=Inv_web_Client_Setup SetupIconFile=picture\ICON\icon_client.ico @@ -31,6 +32,8 @@ Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl" [Files] Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#RustDeskInstaller}"; DestDir: "{tmp}"; DestName: "rustdesk-installer.exe"; Flags: deleteafterinstall noencryption; Check: ShouldInstallRustDesk +Source: "installer\configure_rustdesk.ps1"; DestDir: "{tmp}"; Flags: deleteafterinstall noencryption; Check: ShouldInstallRustDesk [Icons] Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" @@ -42,12 +45,56 @@ Filename: "{app}\{#MyAppExeName}"; Description: "Запустить {#MyAppName} [Code] var + InstallModePage: TInputOptionWizardPage; + RustDeskServerPage: TInputQueryWizardPage; + RustDeskPasswordPage: TInputQueryWizardPage; ConnectionPage: TInputQueryWizardPage; +function IsManualRustDeskMode: Boolean; +begin + Result := InstallModePage.SelectedValueIndex = 1; +end; + +function ShouldInstallRustDesk: Boolean; +begin + Result := InstallModePage.SelectedValueIndex <> 2; +end; + procedure InitializeWizard; begin - ConnectionPage := CreateInputQueryPage( + InstallModePage := CreateInputOptionPage( wpWelcome, + 'Режим установки', + 'Выберите состав установки', + 'Клиент Inv_web устанавливается во всех режимах.', + True, + False + ); + InstallModePage.Add('Автоматический режим с RustDesk'); + InstallModePage.Add('Ручной режим с сервером RustDesk'); + InstallModePage.Add('Установка без RustDesk (удалённого доступа)'); + InstallModePage.SelectedValueIndex := 0; + + RustDeskServerPage := CreateInputQueryPage( + InstallModePage.ID, + 'Сервер RustDesk', + 'Укажите параметры собственного сервера', + 'Введите адреса серверов RustDesk и публичный ключ сервера.' + ); + RustDeskServerPage.Add('Сервер ID:', False); + RustDeskServerPage.Add('Ретранслятор:', False); + RustDeskServerPage.Add('Key:', False); + + RustDeskPasswordPage := CreateInputQueryPage( + RustDeskServerPage.ID, + 'Фиксированный пароль RustDesk', + 'Настройте постоянный пароль удалённого доступа', + 'Оставьте поле пустым, чтобы пропустить этот шаг и не задавать пароль.' + ); + RustDeskPasswordPage.Add('Фиксированный пароль:', True); + + ConnectionPage := CreateInputQueryPage( + RustDeskPasswordPage.ID, 'Подключение к серверу', 'Укажите параметры подключения клиента', 'Введите адрес сервера и токен. Эти данные будут сохранены в профиле текущего пользователя.' @@ -56,9 +103,77 @@ begin ConnectionPage.Add('Токен:', True); end; +function ShouldSkipPage(PageID: Integer): Boolean; +begin + Result := False; + + if (PageID = RustDeskServerPage.ID) and + (not IsManualRustDeskMode) then + begin + Result := True; + Exit; + end; + + if (PageID = RustDeskPasswordPage.ID) and + (not ShouldInstallRustDesk) then + Result := True; +end; + +function ContainsUnsafeCommandLineCharacters(const Value: String): Boolean; +begin + Result := + (Pos('"', Value) > 0) or + (Pos(#13, Value) > 0) or + (Pos(#10, Value) > 0); +end; + function NextButtonClick(CurPageID: Integer): Boolean; begin Result := True; + + if CurPageID = RustDeskServerPage.ID then + begin + if Trim(RustDeskServerPage.Values[0]) = '' then + begin + MsgBox('Укажите сервер ID RustDesk.', mbError, MB_OK); + Result := False; + Exit; + end; + + if Trim(RustDeskServerPage.Values[1]) = '' then + begin + MsgBox('Укажите ретранслятор RustDesk.', mbError, MB_OK); + Result := False; + Exit; + end; + + if Trim(RustDeskServerPage.Values[2]) = '' then + begin + MsgBox('Укажите публичный Key сервера RustDesk.', mbError, MB_OK); + Result := False; + Exit; + end; + + if ContainsUnsafeCommandLineCharacters(RustDeskServerPage.Values[0]) or + ContainsUnsafeCommandLineCharacters(RustDeskServerPage.Values[1]) or + ContainsUnsafeCommandLineCharacters(RustDeskServerPage.Values[2]) then + begin + MsgBox('Параметры RustDesk не должны содержать кавычки или переносы строк.', mbError, MB_OK); + Result := False; + Exit; + end; + end; + + if CurPageID = RustDeskPasswordPage.ID then + begin + if ContainsUnsafeCommandLineCharacters(RustDeskPasswordPage.Values[0]) then + begin + MsgBox('Пароль RustDesk не должен содержать кавычки или переносы строк.', mbError, MB_OK); + Result := False; + end; + Exit; + end; + if CurPageID <> ConnectionPage.ID then Exit; @@ -76,14 +191,100 @@ begin Exit; end; - if (Pos('"', ConnectionPage.Values[0]) > 0) or - (Pos('"', ConnectionPage.Values[1]) > 0) then + if ContainsUnsafeCommandLineCharacters(ConnectionPage.Values[0]) or + ContainsUnsafeCommandLineCharacters(ConnectionPage.Values[1]) then begin - MsgBox('Адрес сервера и токен не должны содержать двойные кавычки.', mbError, MB_OK); + MsgBox('Адрес сервера и токен не должны содержать кавычки или переносы строк.', mbError, MB_OK); Result := False; end; end; +function GetRustDeskMode(Param: String): String; +begin + if IsManualRustDeskMode then + Result := 'manual' + else + Result := 'automatic'; +end; + +function GetRustDeskIdServer(Param: String): String; +begin + Result := Trim(RustDeskServerPage.Values[0]); +end; + +function GetRustDeskRelayServer(Param: String): String; +begin + Result := Trim(RustDeskServerPage.Values[1]); +end; + +function GetRustDeskKey(Param: String): String; +begin + Result := Trim(RustDeskServerPage.Values[2]); +end; + +function GetRustDeskPassword(Param: String): String; +begin + Result := RustDeskPasswordPage.Values[0]; +end; + +function QuoteArgument(const Value: String): String; +begin + Result := '"' + Value + '"'; +end; + +procedure CurStepChanged(CurStep: TSetupStep); +var + ExitCode: Integer; + ConfigurationPath: String; + ConfigurationText: String; + PowerShellPath: String; + Parameters: String; +begin + if (CurStep <> ssPostInstall) or (not ShouldInstallRustDesk) then + Exit; + + WizardForm.StatusLabel.Caption := 'Установка и настройка RustDesk...'; + PowerShellPath := ExpandConstant( + '{sys}\WindowsPowerShell\v1.0\powershell.exe' + ); + ConfigurationPath := ExpandConstant('{tmp}\rustdesk-options.ini'); + ConfigurationText := + 'Mode=' + GetRustDeskMode('') + #13#10 + + 'IdServer=' + GetRustDeskIdServer('') + #13#10 + + 'RelayServer=' + GetRustDeskRelayServer('') + #13#10 + + 'Key=' + GetRustDeskKey('') + #13#10 + + 'Password=' + GetRustDeskPassword('') + #13#10; + + if not SaveStringToFile(ConfigurationPath, ConfigurationText, False) then + RaiseException('Не удалось подготовить параметры RustDesk.'); + + Parameters := + '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' + + QuoteArgument(ExpandConstant('{tmp}\configure_rustdesk.ps1')) + ' ' + + '-InstallerPath ' + + QuoteArgument(ExpandConstant('{tmp}\rustdesk-installer.exe')) + ' ' + + '-ConfigurationPath ' + QuoteArgument(ConfigurationPath); + + ExitCode := -1; + Exec( + PowerShellPath, + Parameters, + '', + SW_HIDE, + ewWaitUntilTerminated, + ExitCode + ); + DeleteFile(ConfigurationPath); + + if ExitCode <> 0 then + begin + RaiseException( + 'Не удалось установить или настроить RustDesk. Код ошибки: ' + + IntToStr(ExitCode) + ); + end; +end; + function GetServerAddress(Param: String): String; begin Result := Trim(ConnectionPage.Values[0]); diff --git a/installer/.DS_Store b/installer/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4c393e6faddfa3a9365c8082e193cac9df2d77d1 GIT binary patch literal 8196 zcmeHMO>YxP5Unx+#v8IsAPE7181My&h)wvCRx5-ttk}RI5sn~%1T*95IK7#4duPTm z5Fz;t5(kd_0Db@`j(geTUiZL-Kfr+#SGM}Y5F7__TCJcv>UuTR^{Ts{lAPbe3uHS`$IroVcBBGpuTmG(MJHn0SfCzKAi(JC$Lzy*fFT7RMVUu z&{EMJG0@OyJW%O`Ws4nyh7M@xfOclIClu7P6ED!|fMtWuIt82pTNO}e_gxS|Mt`j5 z{I0%A73!xx=%&fXpbioQECYuIv>+u`jeG&?ByIq|uymGqNGYaySJ|x|-Vb zhCt2mvS)^)Up<3baZ2-YVzBnxcP5wg7-<#D_nIy9^<2jdNVKF1wr*pP8EtVzCxK5JK zG}TaclcgEq7S8-an5LmH5G{z4a!0c$Wn99 zf1`u5PJvzpc9_7pI{*K={rmr3n!9!iI0e2T1#sX>^@{qT-+k`(?oItH4XEFvuA0j0 o7}OLpDn-Thah&kuKMcta>{!`i#~_VRb1wq449++O{!<111^zWiD*ylh literal 0 HcmV?d00001 diff --git a/installer/configure_rustdesk.ps1 b/installer/configure_rustdesk.ps1 new file mode 100644 index 0000000..aa7007b --- /dev/null +++ b/installer/configure_rustdesk.ps1 @@ -0,0 +1,113 @@ +param( + [Parameter(Mandatory = $true)] + [string]$InstallerPath, + + [Parameter(Mandatory = $true)] + [string]$ConfigurationPath +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $ConfigurationPath)) { + throw "Файл параметров RustDesk не найден: $ConfigurationPath" +} + +$configuration = @{} +foreach ($line in Get-Content -LiteralPath $ConfigurationPath) { + $separatorIndex = $line.IndexOf('=') + if ($separatorIndex -lt 0) { + continue + } + $name = $line.Substring(0, $separatorIndex) + $value = $line.Substring($separatorIndex + 1) + $configuration[$name] = $value +} + +$Mode = [string]$configuration['Mode'] +$IdServer = [string]$configuration['IdServer'] +$RelayServer = [string]$configuration['RelayServer'] +$Key = [string]$configuration['Key'] +$Password = [string]$configuration['Password'] + +if ($Mode -notin @('automatic', 'manual')) { + throw "Неизвестный режим настройки RustDesk: $Mode" +} + +function Find-RustDeskExecutable { + $candidates = @() + foreach ($basePath in @($env:ProgramFiles, ${env:ProgramFiles(x86)})) { + if ($basePath) { + $candidates += Join-Path $basePath 'RustDesk\rustdesk.exe' + } + } + if ($env:LOCALAPPDATA) { + $candidates += Join-Path $env:LOCALAPPDATA 'RustDesk\rustdesk.exe' + $candidates += Join-Path $env:LOCALAPPDATA 'Programs\RustDesk\rustdesk.exe' + } + + foreach ($candidate in $candidates) { + if ($candidate -and (Test-Path -LiteralPath $candidate)) { + return $candidate + } + } + + return $null +} + +if (-not (Test-Path -LiteralPath $InstallerPath)) { + throw "Установщик RustDesk не найден: $InstallerPath" +} + +$installProcess = Start-Process -FilePath $InstallerPath -ArgumentList '--silent-install' -Wait -PassThru -WindowStyle Hidden + +if ($installProcess.ExitCode -ne 0) { + throw "Установка RustDesk завершилась с кодом $($installProcess.ExitCode)." +} + +$rustDeskExecutable = $null +for ($attempt = 0; $attempt -lt 30; $attempt++) { + $rustDeskExecutable = Find-RustDeskExecutable + if ($rustDeskExecutable) { + break + } + Start-Sleep -Seconds 2 +} + +if (-not $rustDeskExecutable) { + throw 'После установки не найден rustdesk.exe.' +} + +function Invoke-RustDeskCommand { + param([string[]]$Arguments) + + & $rustDeskExecutable @Arguments + if ($LASTEXITCODE -ne 0) { + throw "Команда RustDesk $($Arguments[0]) завершилась с кодом $LASTEXITCODE." + } +} + +$service = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue +if (-not $service) { + Invoke-RustDeskCommand @('--install-service') + Start-Sleep -Seconds 3 + $service = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue +} + +if (-not $service) { + throw 'Служба RustDesk не была установлена.' +} + +if ($service.Status -ne 'Running') { + Start-Service -Name 'RustDesk' + $service.WaitForStatus('Running', [TimeSpan]::FromSeconds(30)) +} + +if ($Mode -eq 'manual') { + Invoke-RustDeskCommand @('--option', 'custom-rendezvous-server', $IdServer) + Invoke-RustDeskCommand @('--option', 'relay-server', $RelayServer) + Invoke-RustDeskCommand @('--option', 'key', $Key) +} + +if ($Password) { + Invoke-RustDeskCommand @('--password', $Password) +} diff --git a/installer/prerequisites/README.md b/installer/prerequisites/README.md index 8b48e90..c29097d 100644 --- a/installer/prerequisites/README.md +++ b/installer/prerequisites/README.md @@ -1,4 +1,4 @@ -# PostgreSQL prerequisite +# Офлайн-компоненты установщиков Перед сборкой вручную положите сюда официальный установщик PostgreSQL для Windows x64 под именем: @@ -7,3 +7,14 @@ postgesql.exe ``` `build_inventera_installer_windows.bat` проверит наличие этого файла и включит его внутрь установщика `dist\Inventera.exe`. Автоматического скачивания больше нет. + +Для сборки установщика клиента также положите сюда официальный установщик +RustDesk для Windows x64 под именем: + +```text +rustdesk.exe +``` + +`build_client_agent_v2_installer_windows.bat` проверит наличие файла и включит +его в `dist\Inv_web_Client_Setup.exe`. В режиме без RustDesk этот компонент не +запускается. diff --git a/picture/.DS_Store b/picture/.DS_Store index 9c28ea2b06fc12eb65a471479c58f4384c573c57..2210b35c1b24e60a32ac08f7e2b86aeed0c390ef 100644 GIT binary patch delta 24 fcmZoEXernbCcRl&(3p|QA!2fXQ1Rw}GHlWSYnBKN delta 141 zcmZoEXernbCe0)yJy}*zTqs_Ezc?em+%q{pFQ6#3EHkxyvaR4Q&WKE)KyYSN>f}IG zQAWvp~?wPaMka;;HKS+v`!I>e0A(bJSA$#%y zCb2XoCZM3+e=q>D7#L&_3SjzybTLB`gD!&+P+Ka48G|W<1(3D`iexf)FeCy+vly~H hbMljua`KaaW&kZ`a023aFmpHaFcq?HX6N|J4*+HfCe;7{ delta 48 zcmZoMXfc@JFUrcmz`)4BAi%&-%#gvL$56nK$B@4HAoFrYM%K;Km