Getting Started
RoyalApps.Community.Rdp.WinForms can now run in two modes:
Embedded: the existing ActiveX-hosted experience insideRdpControl.External: a generated.rdpfile plus an externalmstsc.exeormstscex.exeprocess.
Install the Package
Install the package from NuGet first:
Install-Package RoyalApps.Community.Rdp.WinFormsOr with the .NET CLI:
dotnet add package RoyalApps.Community.Rdp.WinFormsThe package requires Devolutions.MsRdpEx's legacy COM interop because its public API and controls use the legacy MSTSC ActiveX types. Projects that configure MsRdpEx interop explicitly must use:
<PropertyGroup>
<MsRdpExComInterop>Legacy</MsRdpExComInterop>
<MsRdpExGeneratedWinForms>false</MsRdpExGeneratedWinForms>
</PropertyGroup>The build fails with an actionable error if generated or disabled MsRdpEx interop is selected.
Basic Setup
Create the control and configure a basic embedded session:
using RoyalApps.Community.Rdp.WinForms;
using RoyalApps.Community.Rdp.WinForms.Configuration;
using RoyalApps.Community.Rdp.WinForms.Configuration.Connection;
var control = new RdpControl
{
Dock = DockStyle.Fill
};
control.RdpConfiguration.Server = "rdp.example.test";
control.RdpConfiguration.Credentials.Username = "alice";
control.RdpConfiguration.Credentials.Password = new SensitiveString("secret");
control.RdpConfiguration.SessionMode = RdpSessionMode.Embedded;
control.Connect();Use external session mode:
control.RdpConfiguration.SessionMode = RdpSessionMode.External;
control.RdpConfiguration.External.UseCredentialManager = true;
control.RdpConfiguration.External.KillProcessOnHostExit = true;
control.Connect();RemoteApp example:
control.RdpConfiguration.SessionMode = RdpSessionMode.External;
control.RdpConfiguration.RemoteApp.Enabled = true;
control.RdpConfiguration.RemoteApp.Program = "EXCEL";
control.RdpConfiguration.RemoteApp.Name = "Microsoft Excel";
control.RdpConfiguration.RemoteApp.CommandLine = "\"C:\\Docs\\Budget.xlsx\"";
control.Connect();RemoteApp is supported for external sessions. Program remains the alternate-shell model for full desktop sessions.
RD Gateway PAA access-token example:
control.RdpConfiguration.Gateway.GatewayUsageMethod = GatewayUsageMethod.Always;
control.RdpConfiguration.Gateway.GatewayHostname = "gateway.example.test";
control.RdpConfiguration.Gateway.GatewayUsername = "secureaccess";
control.RdpConfiguration.Gateway.GatewayAccessToken = new SensitiveString("secureaccess");A non-empty token automatically uses explicit gateway settings and cookie-based authentication. Embedded mode requires ActiveX client version 9 or later. External mode writes the raw token into the temporary .rdp file.
For a quick overview of which settings are valid in each hosting mode, see Support Matrix.
Validation notes:
RemoteAppandProgramcannot be combined in one connection attempt.External.SelectedMonitorsis rejected in embedded mode instead of being ignored.RemoteAppis rejected in embedded mode because the RemoteApp window is not truly hosted inside the control.- A gateway access token requires an enabled gateway and a gateway hostname.
Security configuration notes:
RemoteCredentialGuardis the higher-level option for redirecting authentication back to the local device.RestrictedAdminModeis the higher-level option for “connect without sending reusable credentials”.DisableCredentialsDelegation,RedirectedAuthentication, andRestrictedLogonare the low-level building blocks behind those modes.AuthenticationServiceClassis mainly for embedded ActiveX sessions that need a non-default SPN service class.
Embedded RD Gateway Isolation
Starting with version 2.0.4, embedded sessions automatically load MsRdpEx hooks whenever Gateway.GatewayUsageMethod is not Never. This includes Always, OnDemand, UseDefaultSettings, and BypassLocalAddresses. Default gateway settings do not require an explicit hostname to activate hooks.
MsRdpEx 2026.9.21.0 enables gateway RPC binding isolation by default to address failures when opening a second simultaneous embedded gateway connection in the same process. Logging and session capture can remain disabled; gateway-only hook activation does not enable the new output presenter.
Isolation is process-wide. To disable it, set MSRDPEX_GATEWAY_UNIQUE_BINDING=0 in the host process environment before MsRdpEx loads. The library honors this startup override without assigning GatewayIsolationEnabled. Existing bindings retain their behavior when the setting changes.
External sessions continue to select hook-based launching through External.UseMsRdpExHooks. See External Mode for launcher selection and deployment details.
MsRdpEx Logging
For embedded sessions, set LogEnabled, LogLevel, and LogFilePath before connecting:
control.RdpConfiguration.LogEnabled = true;
control.RdpConfiguration.LogLevel = "DEBUG";
control.RdpConfiguration.LogFilePath = @"C:\Logs\rdp.log";
control.Connect();Logging is process-wide, so all controls should use the same configuration. A gateway-only connection with logging disabled leaves logging unconfigured, allowing a later connection attempt to enable it. MSRDC or capture initialization can establish the process-wide logging configuration even when logging is disabled.
Use RdpControl.ConfigureProcessWideMsRdpExLogging to change logging after initialization:
RdpControl.ConfigureProcessWideMsRdpExLogging(
enabled: true,
level: "DEBUG",
filePath: @"C:\Logs\rdp.log",
logger: control.Logger);To disable logging, call the same method with enabled: false; level and filePath may be null. An explicit process-wide configuration takes precedence over subsequent connection settings. After explicitly disabling logging, use this method to enable it again.
