Remote Desktop Script

Hi Guys!

I’m working on a script to automate the resetting of RDS profiles when they get stuck / errors occur.

Currently, i have the script finding users, deleting their local rds profiles and clearing them down, which is great.

Before i run the script, i want to make sure that i disconnect the current users session from whatever RDS server they are logged in to, (we have an RDS farm of 3 session hosts)

I would like the script to automate this part of it too. Helpdesk enters the username, script searches the array of RDS session hosts, grabs the session ID and logs them off, then continues down the script. Problem is, i can’t figure out this part of it, anyone have any experience with this? Is it possible? I’ve included what i have so far and also what i’ve tried.

## Created by Chris Pounds 2017 ##

## Script to find a Users folder in C drive of target computer, created to clear RDS Profiles ##

## if you want to target multiple machines, place them in this string list ##


$sessionhost = @("***","***","***")
$filestore = "***"
$user = Read-Host "Please enter username"





foreach ($sessionhosts in $sessionhost) { 
Invoke-Command -Computer $sessionhosts -ArgumentList $sessionhosts,$user -ScriptBlock { param($sessionhosts,$user)

Remove-Item -Path \\$sessionhosts\C$\Users\$user* 

     }


     Write-Host "Profiles deleted"
}


Invoke-Command -Computer $filestore -ArgumentList $filestore,$user -ScriptBlock { param($filestore,$user)
    
    Remove-Item -Path \\$filestore\C$\RDS` Roaming` Profiles\$user* -Recurse 
        
 }

 Write-Host "All instances of $user have been removed" 

The code i tried to use to find users sessions is


foreach($sessionhosts in $sessionhost) {

$session = ((quser /server:$sessionhost | ? { $_ -match $user }) -split ’ +')[2]

logoff $session /server:$server

}

Write-Host $user “Logged off from server”


which works if the session hosts aren’t listed in an array like i currently have. The errors i received when i ran the script are.

quser : Error 0x000006BA enumerating sessionnames
At N:\PSScripts\RemoveLocalProfileWithArray.ps1:15 char:14
+ $session = ((quser /server:$sessionhost | ? { $_ -match $user }) -spl ...
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Error 0x000006B...ng sessionnames:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
Error [1722]:The RPC server is unavailable.
logoff : If you give a server name, you need to specify a session ID or a session name.
At N:\PSScripts\RemoveLocalProfileWithArray.ps1:17 char:1
+ logoff $session /server:$server
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (If you give a s...a session name.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
quser : Error 0x000006BA enumerating sessionnames
At N:\PSScripts\RemoveLocalProfileWithArray.ps1:15 char:14
+ $session = ((quser /server:$sessionhost | ? { $_ -match $user }) -spl ...
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Error 0x000006B...ng sessionnames:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
Error [1722]:The RPC server is unavailable.
logoff : If you give a server name, you need to specify a session ID or a session name.
At N:\PSScripts\RemoveLocalProfileWithArray.ps1:17 char:1
+ logoff $session /server:$server
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (If you give a s...a session name.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
quser : Error 0x000006BA enumerating sessionnames
At N:\PSScripts\RemoveLocalProfileWithArray.ps1:15 char:14
+ $session = ((quser /server:$sessionhost | ? { $_ -match $user }) -spl ...
+              ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Error 0x000006B...ng sessionnames:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
Error [1722]:The RPC server is unavailable.
logoff : If you give a server name, you need to specify a session ID or a session name.
At N:\PSScripts\RemoveLocalProfileWithArray.ps1:17 char:1
+ logoff $session /server:$server
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (If you give a s...a session name.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError 

Sorry about the long post! Any help / tips would be smashing :slight_smile:

Line 3

$session = ((quser /server:$sessionhost | ? { $_ -match $user }) -split ' +')[2]

should read

$session = ((quser /server:$sessionhosts | ? { $_ -match $user }) -split ' +')[2]

Do you know why?

And, pretty please get in the habit of using Write-out not Write-host. Haven’t you heard Don Jones’ story about a puppy dying every time you use write-host!!??

Well there are reason to use Write-Host, well, only one or two of them but (mostly writing color to the screen)
Yet, you can write to the screen without ever using Write-*.

This…

Write-Host "Profiles deleted"

… and this …

"Profiles deleted"

… will do the same thing.

Just like with variables …

$MyString = ‘Hello’

This…

Write-Host $MyString

This …

$MyString

This …

($MyString = ‘Hello’)

… will all do the same thing…

… they all write to the screen using whatever PoSH is doing to make that happen.

Folks, IMHO go into the ‘Write-Host’ habit, because the saw someone do it, saw it somewhere in some samples, they were taught that way, or the came from another environment were echo and print for screen output was a thing.

Using Write-Host has been a hotly debated topic for a long while. Even by the inventor / author of PowerShell as well.

Write-Host Considered Harmful - by PowerShell founder Jeffrey Snover

Start-Process ‘Write-Host Considered Harmful | Jeffrey Snover's blog

When you are writing or reviewing PowerShell scripts, I’d like you to remember
the following rule of thumb:
:black_medium_small_square: Using Write-Host is almost always wrong.

However, in PoSHv5 Jeffrey Snover now says...

With PowerShell v5 Write-Host no longer “kills puppies”. data is captured into
info stream

Start-Process ‘Write-Information (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Learn

Description

The Write-Information cmdlet specifies how Windows PowerShell handles information
stream data for a command.

Windows PowerShell 5.0 introduces a new, structured information stream (number 6 in Windows PowerShell streams) that you can use to transmit structured data between a script and its callers (or hosting environment). Write-Information lets you add an informational message to the stream, and specify how Windows PowerShell handles information stream data for a command.

As for the Write-Host for color output in the console. You can still use colors, without using Write host, by doing this …

PowerTip: Write PowerShell Output in Color Without Using Write-Host

Start-Process ‘PowerTip: Write PowerShell Output in Color Without Using Write-Host - Scripting Blog [archived]

Summary: Write colorized output to the Windows PowerShell console without using the Write-Host cmdlet.
Hey, Scripting Guy! Question How can you write output to the Windows PowerShell console without using the Write-Host cmdlet?
Hey, Scripting Guy! Answer Set ForegroundColor to a different color by using

<pre>
$host.Ui.RawUi
</pre>

and then use the Write-Output cmdlet to write the output.
When you are finished, set the ForegroundColor back to its original color.

   
   $t = $host.ui.RawUI.ForegroundColor
   $host.ui.RawUI.ForegroundColor = "DarkGreen"
   Write-Output "this is green output"
   this is green output
   $host.ui.RawUI.ForegroundColor = $t

…but it’s a bit more cumbersome IMHO. I wrote a function called…

    Set-TextColor 
   

… that I keep in my profile for easy access and use, you also don’t have to use the Write-Output part as the console screen will stay whatever color you set it to, until you set it to another or back to its defaults.

Ahh yes, i put the wrong variable from the loop!

Sorry about write-host, i have been told before by Don, but i took a break from making any scripts and when i came back for some reason i naturally wrote it! I do hope the puppies are ok…

Thank you for all that postanote, very informative! I’ll modify my script and let you guys know :slight_smile: