skip to content

Search

Syspirit
EN

RDS

RDS and RemoteApps administration with PowerShell - publish and manage your remote applications!

Windows
Published on

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 moduleImport-Module RemoteDesktop
✅ Verify moduleGet-Module RemoteDesktop
🔍 List RDS cmdletsGet-Command -Module RemoteDesktop
📋 Cmdlet helpGet-Help Get-RDRemoteApp -Examples

📱 RemoteApps Management

📌 Action🧠 PowerShell Command
📋 List collection RemoteAppsGet-RDRemoteApp -CollectionName "COLLECTION_NAME"
👁️ RemoteApp detailsGet-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad"
🆕 Publish simple RemoteAppNew-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad" -DisplayName "Notepad" -FilePath "C:\Windows\System32\notepad.exe"
🆕 Publish with required argumentsNew-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "ad_console" -DisplayName "AD Console" -FilePath "C:\Windows\System32\mmc.exe" -CommandLineSetting Require -RequiredCommandLine "dsa.msc"
🔧 Modify RemoteAppSet-RDRemoteApp -CollectionName "COLLECTION_NAME" -Alias "notepad" -DisplayName "New name"
🗑️ Delete RemoteAppRemove-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 collectionsGet-RDSessionCollection
🔍 Collection detailsGet-RDSessionCollection -CollectionName "COLLECTION_NAME"
🆕 Create collectionNew-RDSessionCollection -CollectionName "MyCollection" -SessionHost "server.domain.com"
🗑️ Delete collectionRemove-RDSessionCollection -CollectionName "MyCollection"

👥 User and Group Management

📌 Action🧠 PowerShell Command
👁️ View authorized groupsGet-RDSessionCollectionConfiguration -CollectionName "COLLECTION_NAME" -UserGroup
➕ Add AD groupSet-RDSessionCollectionConfiguration -CollectionName "COLLECTION_NAME" -UserGroup "DOMAIN\Group"
🔐 List connected usersGet-RDUserSession -CollectionName "COLLECTION_NAME"
🚪 Disconnect userDisconnect-RDUser -HostServer "server" -UnifiedSessionID 2
📤 Logoff userInvoke-RDUserLogoff -HostServer "server" -UnifiedSessionID 2

🖥️ RDS Server Management

📌 Action🧠 PowerShell Command
📋 List host serversGet-RDSessionHost
📊 Server statusGet-RDSessionHost -SessionHost "server.domain.com"
🔧 Maintenance mode ONSet-RDSessionHost -SessionHost "server.domain.com" -NewConnectionAllowed No
✅ Maintenance mode OFFSet-RDSessionHost -SessionHost "server.domain.com" -NewConnectionAllowed Yes
📈 Active sessionsGet-RDUserSession -ConnectionBroker "broker.domain.com"

🔑 RDS Licenses

📌 Action🧠 PowerShell Command
📋 List licensesGet-RDLicenseConfiguration
🔍 License server statusGet-WmiObject Win32_TSLicenseServer -ComputerName "server"
📊 Available licensesGet-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_name

Concrete 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 moduleInstall-WindowsFeature RSAT-RDS-Tools
Broker connection errorSpecify -ConnectionBroker "fqdn"
Invisible RemoteAppCheck -ShowInWebAccess $true
Insufficient permissionsAdmin 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 TermServLicensing

The 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)"