|
|
3 weeks ago | |
|---|---|---|
| .. | ||
| modules | 3 weeks ago | |
| .gitignore | 3 weeks ago | |
| README.md | 3 weeks ago | |
| RdpCoexist.cmd | 3 weeks ago | |
| RdpCoexist.ps1 | 3 weeks ago | |
| config.psd1 | 3 weeks ago | |
README.md
RdpCoexist
A small, portable governance/ops shell that lets AnyDesk and RDP run side by
side (concurrent RDP sessions + local console) on modern Windows — without
modifying System32\termsrv.dll on disk.
It does not reimplement the wrapper. It drives
sergiye/rdpWrapper (a portable, .NET
Framework 4.7.2, single-file rewrite of RDP Wrapper that redirects the
TermService ServiceDll to a non-destructive proxy — TermWrap — with a
built-in offset engine) and wraps it with the operational pieces it lacks.
Approach: stop RDP service → point
TermServiceServiceDllat a wrapper in a portable folder → setfDenyTSConnections=0,fSingleSessionPerUser=0,EnableConcurrentSessions=1→ start service. The originaltermsrv.dllis never touched, so SFC / WRP / Windows Update leave it alone.
Why a shell (the 5 gaps this closes)
| # | Gap in the bare engine | What this shell adds |
|---|---|---|
| 1 | No license grant → cannot repackage/redistribute the engine binary | Engine is fetched from its official release and SHA256-pinned; nothing is bundled here (.gitignore blocks *.exe/*.dll) |
| 2 | No self-heal after Windows Update replaces termsrv.dll |
-Heal + a SYSTEM startup scheduled task: verify, and only re-install if the listener dropped |
| 3 | Verification is GUI-only | -Verify returns a machine-checkable verdict (COEXIST-OK requires a real listener and ≥2 active sessions, not just registry values) |
| 4 | Engine phones home for updates → version drift | Engine is always invoked with -offline; version is pinned in config.psd1 |
| 5 | Engine DLL is commonly flagged HackTool:Win32/RDPWrap |
Idempotent Defender exclusion for the engine folder (skipped gracefully if exclusions are policy-locked) |
Layout
RdpCoexist/
├─ RdpCoexist.cmd self-elevating launcher (UAC)
├─ RdpCoexist.ps1 -Apply | -Revert | -Verify | -Heal | -Status
├─ config.psd1 version pin, SHA256 pin, paths, options
└─ modules/
├─ Common.psm1 logging, admin check, GPO-override warning
├─ Engine.psm1 download + hash-verify + drive the engine
├─ Defender.psm1 idempotent exclusion add/remove
├─ Verify.psm1 listener + active-session verdict
├─ Heal.psm1 scheduled-task register/unregister
└─ LocalUser.psm1 optional dedicated RDP account
Engine binary, logs, and state live under %ProgramData%\RdpCoexist\ — never in this repo.
Usage
- Edit
config.psd1. At minimum setEngineSha256to the hash of the engine release you vetted (or run the first-Applywith-TrustOnFirstUse, which prints the observed hash for you to paste back and lock). - Run:
RdpCoexist.cmd -Apply :: fetch+verify engine, install, register heal task, verify
RdpCoexist.cmd -Verify :: print current verdict
RdpCoexist.cmd -Revert :: uninstall engine, remove task + exclusion
COEXIST-OK only appears once two sessions are actually active (e.g. console +
one RDP), because a listener alone does not prove coexistence.
Requirements & caveats
- Admin required (the launcher elevates).
- .NET Framework 4.7.2 — built into supported Windows 10/11; no install needed.
- Domain GPO: if
fSingleSessionPerUser/fDenyTSConnectionsare enforced by policy, they revert on GP refresh. The shell warns; resolve with IT. - Same-user dual session trips license locks in OneDrive/Outlook/Office. Prefer
the optional dedicated RDP account (
CreateRdpUser), keeping the console user for AnyDesk. - Portability vs. resilience: the engine is copied under
%ProgramData%by default. PointingServiceDllat removable media means RDP dies if the media is pulled — don't. - Concurrent-session enablement changes the effective RDP session limit; confirm your own licensing position before use.
Configuration keys
See config.psd1 for the annotated list. Values shipped here are neutral
placeholders — set the version pin, hash pin, and (if used) the RDP user name to
your own before running.