question

BaharulIslam-2413 avatar image
0 Votes"
BaharulIslam-2413 asked ·

How to terminate session once user away in windows

Hi Expert ,

We have few Windows VM for development workstation. Once user is away another user can login but old session is not getting terminated , so at end of day system resources (cpu/memory ) usages is higher. Is there any way to terminate session if its not active for some duration say 10 mins or scheduled terminate say at 12 midnight terminate all in-active session.

Thanks!

azure-virtual-machines
· 1
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@BaharulIslam-2413

Please 'Accept as answer' if the provided information is helpful, so that it can help others in the community looking for help on similar topics.

0 Votes 0 ·
shivapatpi-MSFT avatar image
0 Votes"
shivapatpi-MSFT answered ·

Hello @BaharulIslam-2413 ,
Thanks for your query and apologies for the delay.
Can you try out the below script and try to test in the machine where multiple multiple users were logged-in.
Below script uses the output of quser command

C:\Users\user>quser
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
user1 rdp-tcp#25 7 Active . 3/1/2021 11:28 PM
user2 rdp-tcp#15 11 Active 5 3/2/2021 12:53 AM

In the above output user2 was idle for 5 mins and active users are indicated by IdleTime = .


Below script will query all the users , validate the users IdleTime.
If the IdleTime >= 1 , it will invoke logoff user using the corresponding session ID

You can schedule this script in the task manager of all the machines

Execute below powershell module on the machine where you want to kill idle users who are in-active for more than 1 min

function Query-UsersInfo

 {
 [CmdletBinding()]
 Param (
     [Parameter ()]
         [string[]]
         $ComputerName = $env:COMPUTERNAME
     )

 begin
     {
     $Header = 'UserName','SessionName','ID','State','IdleTime','LogonTime'
     $NotAbleToConnect = 'NotAbleToConnect' 
     }

 process
     {
     foreach ($cn in $ComputerName)
         {
         if (Test-Connection -ComputerName $cn -Count 1 -Quiet)
             {
             quser /server:$cn | #QUery all the user sessions
                 Select-Object -Skip 1 | #Skip the header
                 ForEach-Object {($_ -replace '\s{2,}', ',').Trim()} |
                 ConvertFrom-Csv -Header $Header |
                 ForEach-Object {
                 #loop through each user
                        
                         $IdleTime = $_.IdleTime #Get Idle time
                         if ($IdleTime -ne ".")
                         {
                         #Create a customer Powershell object to query 
                             $obj = [PSCustomObject]@{
                                 ComputerName = $CN_Item
                                 UserName = $_.UserName
                                 SessionName = $_.SessionName
                                 ID = $_.ID
                                 State = $_.State
                                 IdleTime = $IdleTime
                                 LogonTime = [datetime]$_.LogonTime
                            
                                 }
                                 #Check for how long user is idle
                                 #Here I am checking for 1 min
                                if ([int]$obj.IdleTime -gt 1) #(i.e. If IdleTime > 0)
                                {
                                 logoff $obj.ID #Logoff the user
                                }
                         }
                            
                                

                     }                
             }
                
         } 
     } 

   

 }

 Query-UsersInfo "localhost"


Let us know if you need additional help .
If the above script helps , kindly "Upvote and Accept the Answer"


·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

BaharulIslam-2413 avatar image
0 Votes"
BaharulIslam-2413 answered ·

Thanks @shivapatpi-MSFT for your script. I have tried to execute the script but got some issue . After some debugging , i have updated param & begin section as it was not able to execute and target is to run to run VM only. But with below script its able to terminate session which are idle for sometime but throws error when system is having disconnected user.

Hope you can help with below error .

I am getting below error
75121-image.png

Output of quser in system as below

75008-image.png

Powershell script I have updated to

  echo "Start"
     $Header = 'UserName','SessionName','ID','State','IdleTime','LogonTime'
          $NotAbleToConnect = 'NotAbleToConnect' 
    
                  quser  | #QUery all the user sessions
                      Select-Object -Skip 1 | #Skip the header
                      ForEach-Object {($_ -replace '\s{2,}', ',').Trim()} |
                      ConvertFrom-Csv -Header $Header |
                      ForEach-Object {
                      #loop through each user
                             echo "Current user"$_.UserName
                              $IdleTime = $_.IdleTime #Get Idle time
                              echo "*********************"$IdleTime
                              if ($IdleTime -ne ".")
                              {
                              #Create a customer Powershell object to query 
                                  $obj = [PSCustomObject]@{
                                      ComputerName = $CN_Item
                                      UserName = $_.UserName
                                      SessionName = $_.SessionName
                                      ID = $_.ID
                                      State = $_.State
                                      IdleTime = $IdleTime
                                      LogonTime = [datetime]$_.LogonTime
                                    
                                      }
                                      #Check for how long user is idle
                                      #Here I am checking for 1 min
                                     if ([int]$obj.IdleTime -gt 1) #(i.e. If IdleTime > 0)
                                     {
                                      logoff $obj.ID #Logoff the user
                                     }
                              }                  
                          }                



image.png (38.5 KiB)
image.png (8.2 KiB)
·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

shivapatpi-MSFT avatar image
0 Votes"
shivapatpi-MSFT answered ·

@BaharulIslam-2413 ,
If you want to logoff the disconnected users , we might have to rely on query session property.
The script mentioned here http://blog.kuppens-switsers.net/it/close-disconnected-remote-sessions-using-powershell/ will logoff all the disconnected users.

If we want to logoff users with "In Active Idle Session" , then you will have to combine both the script and customize it accordingly based upon your requirement.


Here is the script which combines both.


echo "Start"

function Ensure-LogFilePath([string]$LogFilePath)
{
if (!(Test-Path -Path $LogFilePath)) {New-Item $LogFilePath -ItemType directory >> $null}
}
function Write-Log([string]$message)
{
Out-File -InputObject $message -FilePath $LogFile -Append
}
function Get-Sessions
{
$queryResults = query session
$starters = New-Object psobject -Property @{"SessionName" = 0; "UserName" = 0; "ID" = 0; "State" = 0; "Type" = 0; "Device" = 0;}
foreach ($result in $queryResults)
{

try
{
if($result.trim().substring(0, $result.trim().indexof(" ")) -eq "SESSIONNAME")
{
$starters.UserName = $result.indexof("USERNAME");
$starters.ID = $result.indexof("ID");
$starters.State = $result.indexof("STATE");
$starters.Type = $result.indexof("TYPE");
$starters.Device = $result.indexof("DEVICE");
continue;
}
New-Object psobject -Property @{
"SessionName" = $result.trim().substring(0, $result.trim().indexof(" ")).trim(">");
"Username" = $result.Substring($starters.Username, $result.IndexOf(" ", $starters.Username) - $starters.Username);
"ID" = $result.Substring($result.IndexOf(" ", $starters.Username), $starters.ID - $result.IndexOf(" ", $starters.Username) + 2).trim();
"State" = $result.Substring($starters.State, $result.IndexOf(" ", $starters.State)-$starters.State).trim();
"Type" = $result.Substring($starters.Type, $starters.Device - $starters.Type).trim();
"Device" = $result.Substring($starters.Device).trim()
}
}
catch
{
$e = $;
Write-Log "ERROR: " + $e.PSMessageDetails
}
}
}
Ensure-LogFilePath($ENV:LOCALAPPDATA + "\DisconnectedSessions")
$LogFile = $ENV:LOCALAPPDATA + "\DisconnectedSessions\" + "sessions
" + $([DateTime]::Now.ToString('yyyyMMdd')) + ".log"
[string]$IncludeStates = '^(Disc)$'
Write-Log -Message "Disconnected Sessions CleanUp"
Write-Log -Message "============================="
$DisconnectedSessions = Get-Sessions | ? {$.State -match $IncludeStates -and $.UserName -ne ""} | Select ID, UserName
Write-Log -Message "Logged off sessions"
Write-Log -Message "-------------------"
foreach ($session in $DisconnectedSessions)
{
logoff $session.ID
Write-Log -Message $session.Username
}
$Header = 'UserName','SessionName','ID','State','IdleTime','LogonTime'
$NotAbleToConnect = 'NotAbleToConnect'
quser | #QUery all the user sessions
Select-Object -Skip 1 | #Skip the header
ForEach-Object {($ -replace '\s{2,}', ',').Trim()} |
ConvertFrom-Csv -Header $Header |
ForEach-Object {
#loop through each user
echo "Current user"$
.UserName
$IdleTime = $.IdleTime #Get Idle time
echo "*"$IdleTime
if ($IdleTime -ne ".")
{
#Create a customer Powershell object to query
$obj = [PSCustomObject]@{
ComputerName = $CN_Item
UserName = $
.UserName
SessionName = $.SessionName
ID = $
.ID
State = $.State
IdleTime = $IdleTime
LogonTime = [datetime]$
.LogonTime
}
#Check for how long user is idle
#Here I am checking for 1 min
if ([int]$obj.IdleTime -gt 1) #(i.e. If IdleTime > 0)
{
logoff $obj.ID #Logoff the user
}
}
}


(I just tested it for both disconnected and Idle active sessions and it works)


Let me know if that above script works for you. Make sure to "Upvote and Accept the answer"

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.