Files
DeployCenter/Modules/VNC.psm1
T
2026-10-15 21:15:33 +02:00

128 lines
6.1 KiB
PowerShell

# Module VNC de DeployCenter
# Exécuté uniquement avec -Vnc dans le scope principal pour partager le contexte WinPE.
function Start-DeployCenterVnc {
$parentRoot = Split-Path -Path $script:DeployRoot -Parent
$sourceVnc = Join-Path $parentRoot 'uvnc'
$sourceExe = Join-Path $sourceVnc 'winvnc.exe'
$passwordTool = Join-Path $sourceVnc 'createpassword64.exe'
$sourceIni = Join-Path $sourceVnc 'ultravnc.ini'
$script:DeployIPv4 = Get-DeployNetworkIPv4
if ([string]::IsNullOrWhiteSpace($script:DeployIPv4)) {
Write-Log 'Aucune adresse IPv4 de déploiement détectée.' 'WARNING'
}
if (-not (Test-Path -LiteralPath $sourceExe -PathType Leaf)) {
Write-Log "UltraVNC non démarré : exécutable absent ($sourceExe)." 'WARNING'
Write-DeployInventory
return
}
if (-not (Test-Path -LiteralPath $passwordTool -PathType Leaf)) {
Write-Log "UltraVNC non démarré : createpassword64.exe absent ($passwordTool)." 'WARNING'
Write-DeployInventory
return
}
if (-not (Test-Path -LiteralPath $sourceIni -PathType Leaf)) {
Write-Log "UltraVNC non démarré : fichier absent ($sourceIni)." 'WARNING'
Write-DeployInventory
return
}
try {
if (Test-Path -LiteralPath $script:VncDirectory) {
Remove-Item -LiteralPath $script:VncDirectory -Recurse -Force -ErrorAction Stop
}
New-Item -Path $script:VncDirectory -ItemType Directory -Force | Out-Null
Copy-Item -Path (Join-Path $sourceVnc '*') -Destination $script:VncDirectory -Recurse -Force
# WinPE ne permet pas toujours d'ajouter des règles de pare-feu.
# La désactivation globale n'est effectuée que lorsque VNC est demandé.
$wpeutil = Join-Path $env:WINDIR 'System32\wpeutil.exe'
if (-not (Test-Path -LiteralPath $wpeutil -PathType Leaf)) {
$wpeutil = 'wpeutil.exe'
}
& $wpeutil DisableFirewall
if ($LASTEXITCODE -ne 0) {
throw "wpeutil DisableFirewall a renvoyé le code $LASTEXITCODE."
}
Write-Log 'Pare-feu WinPE désactivé à la demande de -Vnc.' 'WARNING'
# Force le mode portable : l'INI actif est celui placé à côté de winvnc.exe.
$portableFlag = Join-Path $script:VncDirectory 'ultravnc.portable'
Set-Content -LiteralPath $portableFlag -Value '' -Encoding ASCII
if (-not [string]::IsNullOrWhiteSpace([string]$script:Config.VncPassword)) {
$script:VncPassword = [string]$script:Config.VncPassword
$passwordSource = 'configuré dans DeployCenter.ini'
}
else {
$script:VncPassword = -join (1..8 | ForEach-Object {
$alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789'
$alphabet[(Get-Random -Minimum 0 -Maximum $alphabet.Length)]
})
$passwordSource = 'généré automatiquement'
}
# createpassword64 encode le mot de passe choisi dans le champ passwd d'ultravnc.ini.
$tool = Join-Path $script:VncDirectory 'createpassword64.exe'
$script:VncProcess = Start-Process -FilePath $tool -ArgumentList @($script:VncPassword) `
-WorkingDirectory $script:VncDirectory -Wait -PassThru -WindowStyle Hidden
if ($script:VncProcess.ExitCode -ne 0) {
throw "createpassword64.exe a renvoyé le code $($script:VncProcess.ExitCode)."
}
$activeIni = Join-Path $script:VncDirectory 'ultravnc.ini'
if (-not (Test-Path -LiteralPath $activeIni -PathType Leaf) -or
-not (Select-String -LiteralPath $activeIni -Pattern '^passwd\s*=' -Quiet)) {
throw "createpassword64.exe n'a pas créé le champ passwd dans ultravnc.ini."
}
$server = Join-Path $script:VncDirectory 'winvnc.exe'
$script:VncProcess = Start-Process -FilePath $server -ArgumentList @('-run') `
-WorkingDirectory $script:VncDirectory -PassThru -WindowStyle Hidden
Start-Sleep -Milliseconds 800
if ($script:VncProcess.HasExited) {
throw "winvnc.exe s'est arrêté immédiatement (code $($script:VncProcess.ExitCode))."
}
$script:VncStarted = $true
Write-Log "UltraVNC démarré. IP : $($script:DeployIPv4) ; mot de passe $passwordSource." 'SUCCESS'
} catch {
Write-Log "Échec du démarrage UltraVNC : $($_.Exception.Message)" 'ERROR'
$script:VncStarted = $false
$script:VncPassword = $null
}
Write-DeployInventory
}
function Stop-DeployCenterVnc {
try {
if ($null -ne $script:VncProcess) {
$proc = Get-Process -Id $script:VncProcess.Id -ErrorAction SilentlyContinue
if ($null -ne $proc) { Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue }
}
# Au cas où winvnc lance un processus serveur distinct, ne cibler que les
# processus dont le chemin correspond à notre copie temporaire.
foreach ($proc in (Get-CimInstance Win32_Process -Filter "Name='winvnc.exe'" -ErrorAction SilentlyContinue)) {
if ($proc.ExecutablePath -and $proc.ExecutablePath.StartsWith($script:VncDirectory, [StringComparison]::OrdinalIgnoreCase)) {
Stop-Process -Id $proc.ProcessId -Force -ErrorAction SilentlyContinue
}
}
} catch {
Write-Log "Arrêt UltraVNC : $($_.Exception.Message)" 'WARNING'
}
# Le processus winvnc peut conserver brièvement un handle sur son dossier.
# Le dossier VNC est propre à ce processus PowerShell (uvnc_<PID>) : on ne
# supprime pas récursivement le dossier partagé InventoryDir, ce qui évite
# de bloquer le lancement suivant si un handle est encore ouvert.
try {
if (Test-Path -LiteralPath $script:InventoryFile -PathType Leaf) {
Remove-Item -LiteralPath $script:InventoryFile -Force -ErrorAction SilentlyContinue
}
if (Test-Path -LiteralPath $script:VncDirectory -PathType Container) {
Start-Sleep -Milliseconds 500
Remove-Item -LiteralPath $script:VncDirectory -Recurse -Force -ErrorAction SilentlyContinue
}
} catch { }
}