RDS (Remote Desktop Services) allows publishing remote applications and desktops from Windows Server to thin clients or computers.
📦 Module Preparation
| 📌 Action | 🧠 PowerShell Command |
|---|---|
| 📦 Import RDS module | Import-Module RemoteDesktop |
| ✅ Verify module | Get-Module RemoteDesktop |
| 🔍 List RDS cmdlets | Get-Command -Module RemoteDesktop |
| 📋 Cmdlet help | Get-Help Get-RDRemoteApp -Examples |
📱 RemoteApps Management
| 📌 Action | 🧠 PowerShell Command |
|---|---|
| 📋 List collection RemoteApps | Get-RDRemoteApp -CollectionName "COLLECTION_NAME" |
| 👁️ RemoteApp details | Get-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad" |
| 🆕 Publish simple RemoteApp | New-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad" -DisplayName "Notepad" -FilePath "C:\Windows\System32\notepad.exe" |
| 🆕 Publish with required arguments | New-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "ad_console" -DisplayName "AD Console" -FilePath "C:\Windows\System32\mmc.exe" -CommandLineSetting Require -RequiredCommandLine "dsa.msc" |
| 🔧 Modify RemoteApp | Set-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad" -DisplayName "New name" |
| 🗑️ Delete RemoteApp | Remove-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad" |
💡 Argument parameters:
-CommandLineSetting Require: argument is required at launch-CommandLineSetting Allow: user can add arguments-CommandLineSetting DoNotAllow: no arguments allowed (default)-RequiredCommandLine "arg": defines the argument to pass to the program
📦 Collection Management
| 📌 Action | 🧠 PowerShell Command |
|---|---|
| 📋 List collections | Get-RDSessionCollection |
| 🔍 Collection details | Get-RDSessionCollection -CollectionName "COLLECTION_NAME" |
| 🆕 Create collection | New-RDSessionCollection -CollectionName "MyCollection" -SessionHost "server.domain.com" |
| 🗑️ Delete collection | Remove-RDSessionCollection -CollectionName "MyCollection" |
👥 User and Group Management
| 📌 Action | 🧠 PowerShell Command |
|---|---|
| 👁️ View authorized groups | Get-RDSessionCollectionConfiguration -CollectionName "COLLECTION_NAME" -UserGroup |
| ➕ Add AD group | Set-RDSessionCollectionConfiguration -CollectionName "COLLECTION_NAME" -UserGroup "DOMAIN\Group" |
| 🔐 List connected users | Get-RDUserSession -CollectionName "COLLECTION_NAME" |
| 🚪 Disconnect user | Disconnect-RDUser -HostServer "server" -UnifiedSessionID 2 |
| 📤 Logoff user | Invoke-RDUserLogoff -HostServer "server" -UnifiedSessionID 2 |
🖥️ RDS Server Management
| 📌 Action | 🧠 PowerShell Command |
|---|---|
| 📋 List host servers | Get-RDSessionHost |
| 📊 Server status | Get-RDSessionHost -SessionHost "server.domain.com" |
| 🔧 Maintenance mode ON | Set-RDSessionHost -SessionHost "server.domain.com" -NewConnectionAllowed No |
| ✅ Maintenance mode OFF | Set-RDSessionHost -SessionHost "server.domain.com" -NewConnectionAllowed Yes |
| 📈 Active sessions | Get-RDUserSession -ConnectionBroker "broker.domain.com" |
🔑 RDS Licenses
| 📌 Action | 🧠 PowerShell Command |
|---|---|
| 📋 List licenses | Get-RDLicenseConfiguration |
| 🔍 License server status | Get-WmiObject Win32_TSLicenseServer -ComputerName "server" |
| 📊 Available licenses | Get-WmiObject Win32_TSIssuedLicense -ComputerName "server" |
🛠️ .rdp Configuration for RemoteApps
To create a custom .rdp file to launch a RemoteApp:
screen mode id:2
remoteapplicationmode:1
remoteapplicationprogram:s:|remoteapp_application_name
remoteapplicationname:s:DISPLAY NAME
full address:s:rds server fqdn
alternate shell:s:|remoteapp_application_nameConcrete example:
screen mode id:2
remoteapplicationmode:1
remoteapplicationprogram:s:|notepad
remoteapplicationname:s:Notepad
full address:s:rds.domain.com
alternate shell:s:|notepad📜 Useful Scripts
🚀 Publish RemoteApp with MMC console
# Publish Active Directory Users & Computers console
New-RDRemoteApp -CollectionName "COLLECTION_NAME" `
-Alias "ad_console" `
-DisplayName "AD Console - Active Directory Computers" `
-FilePath "C:\Windows\System32\mmc.exe" `
-CommandLineSetting Require `
-RequiredCommandLine "%SystemRoot%\System32\dsa.msc" `
-IconIndex 0📊 Published RemoteApps audit
# Export all RemoteApps from a collection
$collectionName = "COLLECTION_NAME"
$apps = Get-RDRemoteApp -CollectionName $collectionName
$apps | Select-Object Alias, DisplayName, FilePath, CommandLineSetting |
Export-Csv "C:\Temp\RemoteApps_$collectionName.csv" -NoTypeInformation
Write-Host "Export completed: $($apps.Count) applications found"👥 Active sessions report
# Detailed list of connected users
Get-RDUserSession -ConnectionBroker "broker.domain.com" |
Select-Object UserName, SessionState, HostServer, CollectionName, @{
Name="ConnectedTime"
Expression={(Get-Date) - $_.ConnectTime}
} |
Sort-Object ConnectedTime -Descending |
Format-Table -AutoSize🔐 Force disconnect idle sessions
# Disconnect sessions idle for more than 2 hours
$maxIdleTime = (Get-Date).AddHours(-2)
Get-RDUserSession | Where-Object {
$_.IdleTime -ne $null -and $_.IdleTime -gt $maxIdleTime
} | ForEach-Object {
Write-Host "Disconnecting $($_.UserName) - Idle since $($_.IdleTime)" -ForegroundColor Yellow
Disconnect-RDUser -HostServer $_.HostServer -UnifiedSessionID $_.UnifiedSessionID -Force
}🚨 Troubleshooting
| 🆘 Problem | 🧠 Solution |
|---|---|
| Missing RDS module | Install-WindowsFeature RSAT-RDS-Tools |
| Broker connection error | Specify -ConnectionBroker "fqdn" |
| Invisible RemoteApp | Check -ShowInWebAccess $true |
| Insufficient permissions | Admin account must be member of “Remote Desktop Services” |
🔧 RDS License Issues
If license installation errors occur, you can rebuild the database with the License Manager console. If ineffective, force a cleanup:
Option 1: Delete licenses via PowerShell
# List current licenses
Get-WmiObject Win32_TSLicenseKeyPack |
Select-Object KeyPackId, ProductVersion, TypeAndModel, AvailableLicenses, IssuedLicenses |
Format-Table
# Delete a specific license by its KeyPackId
$keypack = Get-WmiObject Win32_TSLicenseKeyPack | Where-Object {$_.KeyPackId -eq "ID_TO_DELETE"}
$keypack.Delete()Option 2: Delete all Per User licenses (risky)
# Run PowerShell as Admin on the license server
$licences = Get-WmiObject Win32_TSIssuedLicense -Namespace 'Root/CIMv2' -Filter "LicenseStatus=0"
foreach ($licence in $licences) {
$licence.Delete()
}
Write-Host "Licenses deleted. License service restart recommended."Option 3: Rename the license database file
If the console won’t start, rename the .edb file to rebuild the database:
# Stop the license service
net stop TermServLicensing
# Rename the database (backup)
Rename-Item "C:\Windows\System32\lserver\TLSLic.edb" -NewName "TLSLic.edb.bak"
# Restart the service
net start TermServLicensingThe console should now be empty and functional again.
📈 RDS Monitoring
# RDS deployment overview
Write-Host "=== RDS Status ===" -ForegroundColor Green
Write-Host "Collections: $((Get-RDSessionCollection).Count)"
Write-Host "Published RemoteApps: $((Get-RDRemoteApp).Count)"
Write-Host "Active sessions: $((Get-RDUserSession).Count)"
Write-Host "Host servers: $((Get-RDSessionHost).Count)"