Files
Inv_web/installer/configure_rustdesk.ps1
2026-08-14 10:20:44 +03:00

381 lines
13 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
param(
[Parameter(Mandatory = $true)]
[string]$InstallerPath,
[Parameter(Mandatory = $true)]
[string]$ConfigurationPath,
[Parameter(Mandatory = $true)]
[string]$ErrorPath
)
$ErrorActionPreference = 'Stop'
$logDirectory = Join-Path $env:ProgramData 'Inventera 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-SystemRustDeskExecutable {
$candidates = @()
foreach ($basePath in @($env:ProgramFiles, ${env:ProgramFiles(x86)})) {
if ($basePath) {
$candidates += Join-Path $basePath 'RustDesk\rustdesk.exe'
}
}
foreach ($candidate in $candidates) {
if ($candidate -and (Test-Path -LiteralPath $candidate)) {
return $candidate
}
}
return $null
}
function Stop-RustDeskDesktopProcesses {
$serviceProcessId = 0
try {
$serviceInstance = Get-CimInstance `
-ClassName Win32_Service `
-Filter "Name = 'RustDesk'" `
-ErrorAction SilentlyContinue
if ($serviceInstance) {
$serviceProcessId = [int]$serviceInstance.ProcessId
}
}
catch {
Write-InstallLog "Не удалось определить PID службы RustDesk: $($_.Exception.Message)"
}
try {
$rustDeskProcesses = @(
Get-CimInstance `
-ClassName Win32_Process `
-Filter "Name = 'rustdesk.exe'" `
-ErrorAction SilentlyContinue
)
foreach ($process in $rustDeskProcesses) {
if ([int]$process.SessionId -eq 0) {
continue
}
if (($serviceProcessId -gt 0) -and
([int]$process.ProcessId -eq $serviceProcessId)) {
continue
}
$commandLine = [string]$process.CommandLine
if ($commandLine -match '(?i)--[^\s"]*install[^\s"]*|--(?:option|password)') {
continue
}
Write-InstallLog "Закрывается пользовательский процесс RustDesk, PID: $($process.ProcessId)."
Stop-Process -Id $process.ProcessId -Force -ErrorAction SilentlyContinue
}
}
catch {
Write-InstallLog "Не удалось закрыть пользовательское окно RustDesk: $($_.Exception.Message)"
}
}
if (-not (Test-Path -LiteralPath $InstallerPath)) {
throw "Установщик RustDesk не найден: $InstallerPath"
}
Stop-RustDeskDesktopProcesses
Write-InstallLog 'Запускается встроенный установщик RustDesk.'
$installJob = Start-Job -ScriptBlock {
param([string]$Path)
$process = Start-Process `
-FilePath $Path `
-ArgumentList '--silent-install' `
-Wait `
-PassThru `
-WindowStyle Hidden
[int]$process.ExitCode
} -ArgumentList $InstallerPath
try {
for ($attempt = 0; $attempt -lt 120; $attempt++) {
$installJob = Get-Job -Id $installJob.Id
if ($installJob.State -ne 'Running') {
break
}
# RustDesk opens its desktop window as a child of the installer.
# Start-Process -Wait also waits for that window, so close it here.
Stop-RustDeskDesktopProcesses
Start-Sleep -Seconds 1
}
$installJob = Get-Job -Id $installJob.Id
if ($installJob.State -eq 'Running') {
throw 'Тихая установка RustDesk не завершилась за 120 секунд.'
}
if ($installJob.State -ne 'Completed') {
$jobError = ($installJob.ChildJobs[0].JobStateInfo.Reason | Out-String).Trim()
throw "Процесс установки RustDesk завершился с ошибкой: $jobError"
}
$installJobOutput = @(Receive-Job -Job $installJob -ErrorAction Stop)
if ($installJobOutput.Count -eq 0) {
throw 'Установщик RustDesk завершился без кода возврата.'
}
$installExitCode = [int]$installJobOutput[-1]
}
finally {
if ($installJob) {
if ($installJob.State -eq 'Running') {
Stop-Job -Job $installJob -ErrorAction SilentlyContinue
}
Remove-Job -Job $installJob -Force -ErrorAction SilentlyContinue
}
}
Write-InstallLog "Установщик RustDesk завершён с кодом: $installExitCode"
if ($installExitCode -ne 0) {
throw "Установщик RustDesk завершился с кодом ошибки: $installExitCode."
}
$rustDeskExecutable = $null
for ($attempt = 0; $attempt -lt 60; $attempt++) {
$rustDeskExecutable = Find-SystemRustDeskExecutable
if ($rustDeskExecutable) {
break
}
Start-Sleep -Seconds 1
}
if (-not $rustDeskExecutable) {
throw "После установки не найден системный rustdesk.exe в Program Files. Код установщика 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."
}
function Remove-RustDeskService {
$existingService = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue
if (-not $existingService) {
return
}
if ($existingService.Status -ne 'Stopped') {
Stop-Service -Name 'RustDesk' -Force -ErrorAction SilentlyContinue
try {
$existingService.WaitForStatus('Stopped', [TimeSpan]::FromSeconds(20))
}
catch {
Write-InstallLog 'Служба RustDesk не остановилась штатно; выполняется её пересоздание.'
}
}
$existingService.Dispose()
$null = & sc.exe delete 'RustDesk' 2>&1
for ($attempt = 0; $attempt -lt 30; $attempt++) {
if (-not (Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue)) {
return
}
Start-Sleep -Seconds 1
}
throw 'Не удалось удалить некорректную службу RustDesk.'
}
function Install-RustDeskService {
Write-InstallLog 'Устанавливается служба RustDesk.'
$installServiceResult = Invoke-RustDeskCommand -Arguments @('--install-service')
Write-InstallLog "Команда установки службы завершена с кодом: $($installServiceResult.ExitCode)"
for ($attempt = 0; $attempt -lt 30; $attempt++) {
$installedService = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue
if ($installedService) {
return $installedService
}
Start-Sleep -Seconds 1
}
throw 'Служба RustDesk не была установлена.'
}
$serviceInstance = Get-CimInstance `
-ClassName Win32_Service `
-Filter "Name = 'RustDesk'" `
-ErrorAction SilentlyContinue
if ($serviceInstance) {
$servicePath = [Environment]::ExpandEnvironmentVariables(
[string]$serviceInstance.PathName
)
if ($servicePath.IndexOf(
$rustDeskExecutable,
[StringComparison]::OrdinalIgnoreCase
) -lt 0) {
Write-InstallLog "Обнаружена служба RustDesk с некорректным путём: $servicePath"
Remove-RustDeskService
}
}
$service = Get-Service -Name 'RustDesk' -ErrorAction SilentlyContinue
if (-not $service) {
$service = Install-RustDeskService
}
if ($service.Status -ne 'Running') {
Write-InstallLog 'Запускается служба RustDesk.'
try {
Start-Service -Name 'RustDesk'
}
catch {
Write-InstallLog "Первый запуск службы завершился ошибкой: $($_.Exception.Message)"
Write-InstallLog 'Служба RustDesk будет пересоздана из системного rustdesk.exe.'
$service.Dispose()
Remove-RustDeskService
$service = Install-RustDeskService
Start-Service -Name 'RustDesk'
}
$service = Get-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 успешно завершены.'