You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rdpwrap/RdpCoexist/RdpCoexist.ps1

95 lines
4.3 KiB

<#
.SYNOPSIS
Portable AnyDesk + RDP coexistence orchestrator (governance shell around
sergiye/rdpWrapper). Enables concurrent RDP sessions without touching
System32\termsrv.dll on disk (ServiceDll redirection + TermWrap backend).
.DESCRIPTION
This shell adds the operational pieces the engine does not provide:
1. Engine is fetched from its official release and SHA256-pinned (no
redistribution here; upstream has no license grant).
2. Post-Windows-Update self-heal via a SYSTEM startup scheduled task.
3. A machine-checkable verdict (listener + >=2 active sessions), not GUI.
4. The engine is always run with -offline (no phone-home / version drift).
5. Windows Defender exclusion handled idempotently.
.EXAMPLE
RdpCoexist.cmd -Apply
RdpCoexist.cmd -Verify
RdpCoexist.cmd -Revert
#>
[CmdletBinding(DefaultParameterSetName = 'Verify')]
param(
[Parameter(ParameterSetName = 'Apply')] [switch]$Apply,
[Parameter(ParameterSetName = 'Revert')] [switch]$Revert,
[Parameter(ParameterSetName = 'Verify')] [switch]$Verify,
[Parameter(ParameterSetName = 'Heal')] [switch]$Heal,
[Parameter(ParameterSetName = 'Status')] [switch]$Status,
[switch]$TrustOnFirstUse
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
Import-Module (Join-Path $here 'modules\Common.psm1') -Force
Import-Module (Join-Path $here 'modules\Engine.psm1') -Force
Import-Module (Join-Path $here 'modules\Defender.psm1') -Force
Import-Module (Join-Path $here 'modules\Verify.psm1') -Force
Import-Module (Join-Path $here 'modules\Heal.psm1') -Force
Import-Module (Join-Path $here 'modules\LocalUser.psm1') -Force
$cfg = Import-PowerShellDataFile (Join-Path $here 'config.psd1')
New-Item -ItemType Directory -Path $cfg.InstallRoot -Force | Out-Null
Initialize-Log -Root $cfg.InstallRoot
function Do-Apply {
Assert-Admin
Test-DomainPolicyOverride
if ($cfg.AddDefenderExclusion) { Add-DefenderExclusion -Path (Join-Path $cfg.InstallRoot 'engine') }
$exe = Resolve-Engine -Config $cfg -TrustOnFirstUse:$TrustOnFirstUse
Set-PreferredWrapper -Wrapper $cfg.PreferredWrapper
$rc = Invoke-Engine -Exe $exe -EngineArgs @('-install') -Offline:$cfg.AlwaysOffline
if ($rc -ne 0) { throw "Engine install failed (exit=$rc)." }
if ($cfg.CreateRdpUser) { New-RdpLocalUser -UserName $cfg.RdpUserName }
if ($cfg.RegisterHealTask) { Register-HealTask -Config $cfg -ScriptPath $PSCommandPath }
$v = Test-Coexist -ActiveSessionPattern $cfg.ActiveSessionPattern
$v | Format-List | Out-String | Write-Host
if ($v.Verdict -eq 'FAIL') { Write-Log 'Apply finished but listener is down.' 'Error' }
elseif ($v.Verdict -eq 'LISTENING-UNVERIFIED') {
Write-Log 'Listener up. Open a second concurrent session to confirm COEXIST-OK.' 'Warn'
}
else { Write-Log 'COEXIST-OK.' 'Ok' }
}
function Do-Revert {
Assert-Admin
$exe = Join-Path (Join-Path $cfg.InstallRoot 'engine') $cfg.EngineAsset
if (Test-Path $exe) { Invoke-Engine -Exe $exe -EngineArgs @('-uninstall') -Offline:$cfg.AlwaysOffline | Out-Null }
Unregister-HealTask -Config $cfg
if ($cfg.AddDefenderExclusion) { Remove-DefenderExclusion -Path (Join-Path $cfg.InstallRoot 'engine') }
if ($cfg.CreateRdpUser) { Write-Log "Local user '$($cfg.RdpUserName)' left intact; remove manually if desired." 'Warn' }
Write-Log 'Revert complete.' 'Ok'
}
function Do-Heal {
Assert-Admin
$v = Test-Coexist -ActiveSessionPattern $cfg.ActiveSessionPattern
if ($v.Verdict -ne 'FAIL') { Write-Log "Heal: healthy ($($v.Verdict)); nothing to do." 'Ok'; return }
Write-Log 'Heal: listener down (likely post-update). Re-installing engine.' 'Warn'
$exe = Resolve-Engine -Config $cfg -TrustOnFirstUse:$TrustOnFirstUse
Set-PreferredWrapper -Wrapper $cfg.PreferredWrapper
Invoke-Engine -Exe $exe -EngineArgs @('-install') -Offline:$cfg.AlwaysOffline | Out-Null
(Test-Coexist -ActiveSessionPattern $cfg.ActiveSessionPattern) | Format-List | Out-String | Write-Host
}
switch ($PSCmdlet.ParameterSetName) {
'Apply' { Do-Apply }
'Revert' { Do-Revert }
'Heal' { Do-Heal }
default { (Test-Coexist -ActiveSessionPattern $cfg.ActiveSessionPattern) | Format-List }
}