param( [Parameter(Mandatory = $true)] [string]$InstallerPath, [Parameter(Mandatory = $true)] [string]$ConfigurationPath, [Parameter(Mandatory = $true)] [string]$ErrorPath ) $ErrorActionPreference = 'Stop' $logDirectory = Join-Path $env:ProgramData 'Inv_web Client' $LogPath = Join-Path $logDirectory 'rustdesk-install.log' function Write-InstallLog { param([string]$Message) try { if (-not (Test-Path -LiteralPath $logDirectory)) { $null = New-Item -Path $logDirectory -ItemType Directory -Force } Add-Content -LiteralPath $LogPath -Encoding UTF8 -Value ( '{0:yyyy-MM-dd HH:mm:ss} {1}' -f (Get-Date), $Message ) } catch { # A logging failure must not prevent RustDesk installation. } } trap { $message = $_.Exception.Message Write-InstallLog "ОШИБКА: $message" if ($_.ScriptStackTrace) { Write-InstallLog "Стек: $($_.ScriptStackTrace -replace '[\r\n]+', ' ')" } try { [System.IO.File]::WriteAllText( $ErrorPath, "$message Журнал: $LogPath", [System.Text.UTF8Encoding]::new($true) ) } catch { } exit 1 } 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" } Write-InstallLog '------------------------------------------------------------' Write-InstallLog "Запуск установки 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" } Write-InstallLog 'Запускается встроенный установщик RustDesk.' $installProcess = Start-Process -FilePath $InstallerPath -ArgumentList '--silent-install' -Wait -PassThru -WindowStyle Hidden $installExitCode = $installProcess.ExitCode Write-InstallLog "Установщик RustDesk завершён с кодом: $installExitCode" $rustDeskExecutable = $null for ($attempt = 0; $attempt -lt 60; $attempt++) { $rustDeskExecutable = Find-RustDeskExecutable if ($rustDeskExecutable) { break } Start-Sleep -Seconds 2 } if (-not $rustDeskExecutable) { throw "После установки не найден rustdesk.exe. Код установщика RustDesk: $installExitCode." } Write-InstallLog "Найден RustDesk: $rustDeskExecutable" function Invoke-RustDeskCommand { param([string[]]$Arguments) $output = (& $rustDeskExecutable @Arguments 2>&1 | Out-String).Trim() $exitCode = if ($null -eq $LASTEXITCODE) { 0 } else { [int]$LASTEXITCODE } return [PSCustomObject]@{ ExitCode = $exitCode Output = $output } } function Set-RustDeskOption { param( [string]$Name, [string]$Value ) $lastSetExitCode = -1 $lastReadExitCode = -1 $lastReadOutput = '' for ($attempt = 1; $attempt -le 5; $attempt++) { Write-InstallLog "Применение параметра '$Name', попытка $attempt." $setResult = Invoke-RustDeskCommand -Arguments @('--option', $Name, $Value) $lastSetExitCode = $setResult.ExitCode Start-Sleep -Seconds 2 $readResult = Invoke-RustDeskCommand -Arguments @('--option', $Name) $lastReadExitCode = $readResult.ExitCode $lastReadOutput = $readResult.Output if (($lastSetExitCode -eq 0) -and ($lastReadExitCode -eq 0) -and ($lastReadOutput.Trim() -eq $Value.Trim())) { Write-InstallLog "Параметр '$Name' успешно применён." return } Start-Sleep -Seconds 2 } $readState = 'значение отличается от введённого' if ([string]::IsNullOrWhiteSpace($lastReadOutput)) { $readState = 'пустое значение' } throw "Параметр RustDesk '$Name' не был применён после 5 попыток. Код записи: $lastSetExitCode; код чтения: $lastReadExitCode; результат проверки: $readState." } $service = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue if (-not $service) { Write-InstallLog 'Устанавливается служба RustDesk.' $null = Invoke-RustDeskCommand -Arguments @('--install-service') for ($attempt = 0; $attempt -lt 30; $attempt++) { $service = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue if ($service) { break } Start-Sleep -Seconds 2 } } if (-not $service) { throw 'Служба RustDesk не была установлена.' } if ($service.Status -ne 'Running') { Write-InstallLog 'Запускается служба RustDesk.' Start-Service -Name 'RustDesk' $service.WaitForStatus('Running', [TimeSpan]::FromSeconds(30)) } Write-InstallLog 'Служба RustDesk работает.' if ($Mode -eq 'manual') { Set-RustDeskOption -Name 'custom-rendezvous-server' -Value $IdServer Set-RustDeskOption -Name 'relay-server' -Value $RelayServer Set-RustDeskOption -Name 'key' -Value $Key } if ($Password) { $passwordWasSet = $false for ($attempt = 1; $attempt -le 3; $attempt++) { Write-InstallLog "Задание фиксированного пароля, попытка $attempt." $passwordResult = Invoke-RustDeskCommand -Arguments @('--password', $Password) if (($passwordResult.ExitCode -eq 0) -and ($passwordResult.Output -match 'Done!')) { $passwordWasSet = $true break } Start-Sleep -Seconds 2 } if (-not $passwordWasSet) { throw "Не удалось задать фиксированный пароль RustDesk после 3 попыток. Код: $($passwordResult.ExitCode)." } Write-InstallLog 'Фиксированный пароль успешно задан.' } Write-InstallLog 'Перезапускается служба RustDesk для применения настроек.' Restart-Service -Name 'RustDesk' -Force $service = Get-Service -Name 'RustDesk' $service.WaitForStatus('Running', [TimeSpan]::FromSeconds(30)) Write-InstallLog 'Установка и настройка RustDesk успешно завершены.'