
close
close
During my recent PowerShell workshop in Finland, an attendee asked about Active Directory cmdlets from Microsoft in regards to remote desktop user settings. Although you can readily see the settings in Active Directory Users and Computers, Get-ADUser doesn’t retrieve them. I haven’t worked with Remote Desktop Services in quite a while, but I told him I’d look into this long-standing problem.
Let’s look at the problem. In Active Directory Users and Computers, you might have a setting like this:
Active Directory Users and Computers settings. (Image Credit: Jeff Hicks)
advertisment
Get-ADUser jdemo –properties *
But you don’t. However, if you happen to be using the ActiveRoles cmdlets from Dell (formerly part of Quest Software), then you can easily get these settings.
Using the ActiveRoles cmdlets from Dell. (Image Credit: Jeff Hicks)
The UserParameters property. (Image Credit: Jeff Hicks)
[ADSI]$user = "LDAP://CN=John Demo,OU=Development,DC=Globomantics,DC=Local"
Creating an ADSI object for the user account. (Image Credit: Jeff Hicks)
advertisment
Retrieving the terminal services properties. (Image Credit: Jeff Hicks)
$user.terminalServicesHomeDirectory = "Y:\RDS"
$user.setinfo()
As you can imagine, this would be a lot of work to do manually, so I wrote a function to get remote desktop settings from the ADUC tab that I’ve been showing you.
Function Get-RDUserSetting { [cmdletbinding(DefaultParameterSetName="SAM")] Param( [Parameter(Position=0,Mandatory,HelpMessage="Enter a user's sAMAccountName", ValueFromPipeline,ParameterSetName="SAM")] [ValidateNotNullorEmpty()] [Alias("Name")] [string]$SAMAccountname, [Parameter(ParameterSetName="SAM")] [string]$SearchRoot, [Parameter(Mandatory,HelpMessage="Enter a user's distingished name", ValueFromPipelineByPropertyName,ParameterSetName="DN")] [ValidateNotNullorEmpty()] [Alias("DN")] [string]$DistinguishedName, [string]$Server ) Begin { Write-Verbose "Starting $($MyInvocation.MyCommand)" Write-Verbose ($PSBoundParameters | Out-String) #remote desktop properties $TSSettings = @("TerminalServicesProfilePath","TerminalServicesHomeDirectory","TerminalServicesHomeDrive") } #Begin Process { Write-Verbose "Using parameter set $($PSCmdlet.ParameterSetName)" Switch ($PSCmdlet.ParameterSetName) { "SAM" { Write-Verbose "Retrieving distinguishedname for $samAccountname" $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.Filter = "(&(objectcategory=person)(objectclass=user)(samAccountname=$sAMAccountname))" Write-Verbose $searcher.filter if ($SearchRoot) { Write-Verbose "Searching from $SearchRoot" if ($Server) { $searchPath = "LDAP://$server/$SearchRoot" } else { $searchPath = "LDAP://$SearchRoot" } $r = New-Object System.DirectoryServices.DirectoryEntry $SearchPath $searcher.SearchRoot = $r } $user = $searcher.FindOne().GetDirectoryEntry() } "DN" { Write-Verbose "Processing $DistinguishedName" if ($server) { Write-Verbose "Connecting to $Server" [ADSI]$User = "LDAP://$Server/$DistinguishedName" } else { [ADSI]$User = "LDAP://$DistinguishedName" } } } #close Switch if ($user.path) { #initialize a hashtable Try { $hash=[ordered]@{ DistinguishedName = $User.DistinguishedName.Value Name = $user.name.Value samAccountName = $user.samAccountName.value AllowLogon = $user.psbase.InvokeGet("AllowLogon") -as [Boolean] } foreach ($property in $TSSettings) { $hash.Add($property,$user.psbase.invokeGet($property)) } #foreach #create an object New-Object -TypeName PSObject -Property $hash } Catch { Write-Warning "Failed to retrieve remote desktop settings for $Distinguishedname. $($_.exception.message)" } } #if user found else { Write-Warning "Failed to find user $DistinguishedName. $($_.exception.message)" } } #Process End { Write-Verbose "Ending $($MyInvocation.MyCommand)" } #End } #end function
To use the command, you can either specify a samaccountname or a distinguishedname. I wrote it so that you could use it in conjunction with Get-ADUser.
Using the Get-rDUserSetting function in Windows PowerShell. (Image Credit: Jeff Hicks)
advertisment
get-aduser -filter "Name -like 'demouser10*'" | get-rdusersetting | where {-Not $_.AllowLogon}
Using our function in the pipeline. (Image Credit: Jeff Hicks)
Function Set-RDUserSetting { [cmdletbinding(SupportsShouldProcess)] Param( [Parameter(Position=0,Mandatory,HelpMessage="Enter a user's sAMAccountName", ValueFromPipeline,ParameterSetName="SAM")] [ValidateNotNullorEmpty()] [Alias("Name")] [string]$SAMAccountname, [Parameter(ParameterSetName="SAM")] [string]$SearchRoot, [Parameter(Mandatory,HelpMessage="Enter a user's distingished name", ValueFromPipelineByPropertyName,ParameterSetName="DN")] [ValidateNotNullorEmpty()] [Alias("DN")] [string]$DistinguishedName, [boolean]$AllowLogon, [Alias("Profile")] [string]$TerminalServicesProfilePath, [Alias("HomeDirectory")] [string]$TerminalServicesHomeDirectory, [Alias("HomeDrive")] [string]$TerminalServicesHomeDrive, [string]$Server, [switch]$Passthru ) Begin { Write-Verbose "Starting $($MyInvocation.MyCommand)" Write-Verbose ($PSBoundParameters | out-string) #remote desktop properties $TSSettings = @("TerminalServicesProfilePath","TerminalServicesHomeDirectory","TerminalServicesHomeDrive") } #Begin Process { Write-Verbose "Using parameter set $($PSCmdlet.ParameterSetName)" Switch ($PSCmdlet.ParameterSetName) { "SAM" { Write-Verbose "Retrieving distinguishedname for $samAccountname" $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.Filter = "(&(objectcategory=person)(objectclass=user)(samAccountname=$sAMAccountname))" Write-Verbose $searcher.filter if ($SearchRoot) { Write-Verbose "Searching from $SearchRoot" if ($Server) { $searchPath = "LDAP://$server/$SearchRoot" } else { $searchPath = "LDAP://$SearchRoot" } $r = New-Object System.DirectoryServices.DirectoryEntry $SearchPath $searcher.SearchRoot = $r } $user = $searcher.FindOne().GetDirectoryEntry() } "DN" { Write-Verbose "Processing $DistinguishedName" if ($server) { Write-Verbose "Connecting to $Server" [ADSI]$User = "LDAP://$Server/$DistinguishedName" } else { [ADSI]$User = "LDAP://$DistinguishedName" } } } #close Switch if ($user.path) { if ($PSBoundParameters.ContainsKey("AllowLogon")) { Write-Verbose "Configuring AllowLogon" $user.psbase.invokeSet("AllowLogon",$AllowLogon -as [int]) } foreach ($property in $TSSettings) { if ($PSBoundParameters.ContainsKey($property)) { Write-Verbose "Setting $property = $($PSBoundParameters[$property])" $user.psbase.invokeSet($property,$PSBoundParameters[$property]) } } #commit changes if ($PSCmdlet.ShouldProcess($DistinguishedName)){ $user.setInfo() } #Whatif if ($Passthru) { $hash=[ordered]@{ DistinguishedName = $User.DistinguishedName.Value Name = $user.name.Value samAccountName = $user.samAccountName.value AllowLogon = $user.psbase.InvokeGet("AllowLogon") -as [Boolean] } foreach ($property in $TSSettings) { $hash.Add($property,$user.psbase.InvokeGet($property)) } #foreach #create an object New-Object -TypeName PSObject -Property $hash } } #if user found else { Write-Warning "Failed to find user $DistinguishedName" } } #Process End { Write-Verbose "Ending $($MyInvocation.MyCommand)" } #End } #end function
Normally I’m not a big fan of parameters that take Boolean values, but it was the simplest solution in this case. Now I can easily set remote desktop settings for multiple user accounts.
Get-ADUser -filter "Name -like 'demouser20*'" |
Set-RDUserSetting -AllowLogon $True -TerminalServicesProfilePath "\\CHI-RDS01\Profiles\$($_.samaccountname)" -TerminalServicesHomeDirectory "Y:\RDS" -Passthru
You might also need to configure settings from the Sessions tab. Those settings can be set the same way. You can either modify my functions or write your own. The property names are:
The time settings are in minutes.
I would recommend putting these functions into a module. This is definitely something you will want to test in a non-production setting.
More in PowerShell
Microsoft’s New PowerShell Crescendo Tool Facilitates Native Command-Line Wraps
Mar 21, 2022 | Rabia Noureen
Most popular on petri