Optimal Replacement for Windows System Resource Manager (WSRM) in Windows Server 2012 R2: Resource Limitation Techniques for RDP Environments


4 views

Microsoft officially removed WSRM from Windows Server 2012 R2 after deprecating it in the initial 2012 release. This creates challenges for administrators managing shared RDP servers with constrained resources, particularly when multiple users compete for limited RAM (8GB in your case).

For process-level resource control, consider these built-in Windows mechanisms:

# PowerShell example: Setting process affinity
Get-Process -Name "chrome" | ForEach-Object {
    $_.ProcessorAffinity = 0x3 # Limit to CPUs 0 and 1
}

# Memory limit via Job Objects (C++ example)
HANDLE hJob = CreateJobObject(NULL, L"MyRDPLimits");
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
jeli.ProcessMemoryLimit = 500 * 1024 * 1024; // 500MB
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));

For stronger isolation, deploy each user session in separate VMs with constrained resources:

# Create constrained VM
New-VM -Name "UserVM1" -MemoryStartupBytes 2GB -Generation 2
Set-VMProcessor -VMName "UserVM1" -Count 2 -Reserve 10 -Maximum 50
Set-VMMemory -VMName "UserVM1" -DynamicMemoryEnabled $false

Commercial tools provide more granular control:

  • Process Lasso: Real-time CPU priority and affinity management
  • SoftPerfect RAM Disk: For isolating temp file usage
  • Windows System Control Center: Combines multiple resource tools

Modify Terminal Services settings for RDP-specific control:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd]
"MaxMonitors"=dword:00000002
"MaxXResolution"=dword:00000800
"MaxYResolution"=dword:00000600

Implement proactive monitoring with PowerShell:

# Track per-user memory usage
Get-Counter '\Process(*)\Working Set - Private' | 
Where-Object {$_.CookedValue -gt 500MB} | 
Select-Object InstanceName, CookedValue | 
Sort-Object CookedValue -Descending

html

With Windows Server 2012 R2, Microsoft officially removed Windows System Resource Manager (WSRM) as noted in KB 303411. For administrators running RDP servers with limited resources (particularly in scenarios with 8GB RAM or less), this creates genuine challenges in preventing single users from monopolizing system resources.

While WSRM is gone, these built-in options remain:

# PowerShell CPU limiting example
Get-Process -IncludeUserName | Where-Object { $_.UserName -eq "DOMAIN\User" } | ForEach-Object {
    $_.ProcessorAffinity = 1  # Limits to CPU0
    $_.PriorityClass = "BelowNormal"
}

For memory management, consider Job Objects:

// C++ Job Object memory limit example
#include <windows.h>

void SetUserMemoryLimit(DWORDLONG maxMemoryKB) {
    HANDLE hJob = CreateJobObject(NULL, L"RDPUserLimit");
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
    jeli.ProcessMemoryLimit = maxMemoryKB * 1024;
    SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));
    AssignProcessToJobObject(hJob, GetCurrentProcess());
}

Several robust alternatives exist:

  • Process Lasso: Offers per-user CPU prioritization and RAM limiting
  • Windows System Resource Allocation Manager (WSRAM): Community-developed successor
  • Docker Containers: For isolating user sessions with strict resource bounds

For RDP scenarios, consider:

# Create constrained VM for each user
New-VM -Name "UserVM01" -MemoryStartupBytes 2GB -MemoryMaximumBytes 2GB
Set-VMProcessor -VMName "UserVM01" -Maximum 50

Key adjustments for RDP sessions:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"SessionPoolSize"=dword:00000020  ; Limits session memory
"SessionViewSize"=dword:00000010  ; Reduces session view space

Proactive resource tracking:

# PowerShell monitoring script
while($true) {
    Get-WmiObject Win32_PerfFormattedData_PerfProc_Process | 
    Where { $_.Name -notmatch "idle|system" } |
    Select Name, @{N="PrivateMB";E={[math]::Round($_.WorkingSetPrivate/1MB)}}, PercentProcessorTime |
    Sort PrivateMB -Desc | FT -AutoSize
    Start-Sleep -Seconds 5
}