How to terminate session once user away in windows

Baharul Islam 216 Reputation points
2021-02-26T08:53:32.267+00:00

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
Azure Virtual Machines
An Azure service that is used to provision Windows and Linux virtual machines.
9,013 questions
{count} votes

3 answers

Sort by: Most helpful
  1. shiva patpi 13,366 Reputation points Microsoft Employee Moderator
    2021-03-02T01:19:56.957+00:00

    Hello @Baharul Islam ,
    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"

    0 comments No comments

  2. Baharul Islam 216 Reputation points
    2021-03-07T02:54:24.41+00:00

    Thanks @shiva patpi 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  
                                        }  
                                 }                    
                             }                  
    
    0 comments No comments

  3. shiva patpi 13,366 Reputation points Microsoft Employee Moderator
    2021-03-08T06:12:13.18+00:00

    @Baharul Islam ,
    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"

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.