A Windows server that feels slow, freezes in Remote Desktop or shows constant 100% CPU is usually overloaded by one process, a full memory or a busy disk. This guide shows how to find the cause on Windows Server 2016, 2019, 2022 and 2025 with Task Manager, Resource Monitor and PowerShell, how to tell normal system activity apart from a real problem, and how to spot unwanted programs such as cryptominers.
Press Ctrl+Shift+Esc (inside Remote Desktop use Ctrl+Alt+End and choose Task Manager). Click More details, then sort the Processes or Details tab by CPU, Memory or Disk. On the Details tab, right-click a column header, choose Select columns and add Command line to see exactly what each process runs.
For more depth, open Resource Monitor (resmon). Its CPU tab shows which services run inside each svchost.exe, the Disk tab shows which files are being read and written, and the Network tab shows which process talks to which remote address.
PowerShell works even when the desktop is too slow to use comfortably. Run it as Administrator.
# Overall CPU usage, 5 samples 2 seconds apart
Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 2 -MaxSamples 5
# Processes using the most CPU right now (percentage of total CPU)
Get-Counter '\Process(*)\% Processor Time' -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty CounterSamples |
Where-Object { $_.InstanceName -notin '_total','idle' } |
Sort-Object CookedValue -Descending | Select-Object -First 10 InstanceName,
@{n='CPU%';e={[math]::Round($_.CookedValue / $env:NUMBER_OF_PROCESSORS, 1)}}
# Processes using the most memory
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 10 Name, Id,
@{n='RAM(MB)';e={[math]::Round($_.WorkingSet64 / 1MB)}}
# Which services run inside a busy svchost.exe (replace 1234 with its PID)
tasklist /svc /fi "PID eq 1234"
# Free physical memory and committed memory
Get-CimInstance Win32_OperatingSystem |
Select-Object @{n='TotalGB';e={[math]::Round($_.TotalVisibleMemorySize/1MB,1)}},
@{n='FreeGB';e={[math]::Round($_.FreePhysicalMemory/1MB,1)}}
# Disk activity per drive (sustained % Idle Time near 0 means the disk is the bottleneck)
Get-Counter '\LogicalDisk(*)\% Idle Time','\LogicalDisk(*)\Avg. Disk sec/Transfer' -SampleInterval 2 -MaxSamples 3
# Free space per drive
Get-PSDrive -PSProvider FileSystem | Select-Object Name,
@{n='FreeGB';e={[math]::Round($_.Free/1GB,1)}}, @{n='UsedGB';e={[math]::Round($_.Used/1GB,1)}}
"In use" memory near 100% with constant disk activity means the server is paging to disk: add RAM or reduce what runs on it. A nearly full system drive also slows Windows down and can stop updates; see extending the C drive.
A process with a random name, one running from C:\Users\Public, C:\ProgramData or a temp folder, or an unsigned executable using all CPU deserves a closer look. Cryptominers often hide as svchost.exe in the wrong folder; the real one only runs from C:\Windows\System32.
# Path, command line and digital signature of a suspicious process (replace 1234)
Get-CimInstance Win32_Process -Filter "ProcessId=1234" | Select-Object Name, ExecutablePath, CommandLine
Get-AuthenticodeSignature (Get-Process -Id 1234).Path | Select-Object Status, SignerCertificate
# svchost.exe copies running from anywhere other than System32 or SysWOW64
Get-CimInstance Win32_Process -Filter "Name='svchost.exe'" |
Where-Object { $_.ExecutablePath -notmatch 'C:\\Windows\\(System32|SysWOW64)\\' } |
Select-Object ProcessId, ExecutablePath
# Network connections per process
Get-NetTCPConnection -State Established | Group-Object OwningProcess |
Sort-Object Count -Descending | Select-Object -First 10 Count, Name
# Persistence: scheduled tasks, auto-start services and startup entries
Get-ScheduledTask | Where-Object { $_.State -ne 'Disabled' -and $_.TaskPath -notlike '\Microsoft\*' } |
Select-Object TaskName, TaskPath, @{n='Action';e={$_.Actions.Execute}}
Get-CimInstance Win32_Service | Where-Object { $_.StartMode -eq 'Auto' -and $_.PathName -notmatch 'Windows' } |
Select-Object Name, State, PathName
Get-CimInstance Win32_StartupCommand | Select-Object Name, Command, Location
# Update signatures and run a full Microsoft Defender scan
Update-MpSignature
Start-MpScan -ScanType FullScan
Get-MpThreatDetection
If you find malware, remove the scheduled task or service first, then end the process and delete its files, change every password and close the way in, most often a weak Remote Desktop password: see Windows VPS security hardening and changing the RDP port. When in doubt, back up your data and reinstall.
Problems that come and go are easier to catch with a recording. Run perfmon, open Data Collector Sets → System, right-click System Performance and choose Start. After it finishes (about one minute) the report under Reports → System lists the top processes for CPU, disk and network.
Turn on Show processes from all users and check the Details tab, where system services and other users' processes appear. Some malware also stops when Task Manager opens; use the PowerShell commands above, or the resource graphs in the IMIDC client area where your product offers them.
If CPU, memory and disk look normal, the cause is usually the network path between you and the server. See Remote Desktop troubleshooting and test the route with ping and tracert.
If your own applications legitimately use most of the CPU or RAM during normal traffic, tuning will not help for long. Upgrade the plan or move the database to a second server.
Still stuck after following these steps? Open a support ticket and the IMIDC 24/7 technical team will help. Include the server IP, the Windows Server version, the busy process name and a screenshot of Task Manager or the PowerShell output so we can pinpoint the issue faster.