VMware Cloud Community
techie11
Contributor
Contributor

Disconnect vi client as specified intervals

Is there a way to disconnect a user from the viconsole, or disconnect all idle users after x hours with powershell.

Reply
0 Kudos
11 Replies
LucD
Leadership
Leadership

Unfortunately you can't manage client sessions with cmdlets (afaik).

The SDK contains a method called TerminateSession that does what you want.

You provide to this method an array of Session IDs and the method will terminate each of these session.

In the sample script I test if there has been no activity for 60 minutes for each session.

# Force load
[http://Reflection.Assembly|http://Reflection.Assembly]::LoadWithPartialName("vmware.vim")

$svcRef = new-object VMware.Vim.ManagedObjectReference 
$svcRef.Type = "ServiceInstance" 
$svcRef.Value = "ServiceInstance" 
$serviceInstance = get-view $svcRef

$sessMgr = get-view $serviceInstance.Content.sessionManager
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
  if ( (($sess.LastActiveTime).addminutes(60)) -lt (Get-Date)){
    $oldSessions += $sess.Key
  }
}
$sessMgr.TerminateSession($oldSessions)

Since the forum SW seems to change some code I have included the same script as a PS1 file


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
bradley4681
Expert
Expert

so building on that script is there a way to disconnect all sessions idle for more then 4hrs and exclude a list of users, say service accounts listed in a file?

Cheers! If you found this or other information useful, please consider awarding points for "Correct" or "Helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

Yes, that is possible.

Note that the previous script was written for an older version of PowerCLI (VI Toolkit) and that a lot can be done much simpler.

$excluded = "domain\user1","domain\user2" 
$sessMgr
= Get-View SessionManager
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){   if ((($sess.LastActiveTime).AddHours(4)) -lt (Get-Date) -and $excluded -notcontains $sess.UserName){     $oldSessions += $sess.Key   } } $sessMgr.TerminateSession($oldSessions)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
bradley4681
Expert
Expert

so could i do this to read from a file, easier to list the users and add or remove this way..

$excluded = Get-Content "./exclude-users.txt"
$sessMgr = Get-View SessionManager
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
  if ((($sess.LastActiveTime).AddHours(4)) -lt (Get-Date) -and $excluded -notcontains $sess.UserName){
    $oldSessions += $sess.Key
  }
}
$sessMgr.TerminateSession($oldSessions)

and then in the text file

"domain\user1"

 "domain\user2"
"helpdesk"
"someguy"
"domain\anotherguy"

Cheers! If you found this or other information useful, please consider awarding points for "Correct" or "Helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

Sure, the Get-Content cmdlet will create an array, just like it was with my inline version.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
bradley4681
Expert
Expert

so i ran the script aginst one of my VCs and it seemed to work fine against most idle users that had been connected for more then 8hrs but one user had been idled for 6hrs and it did not disconnect them.

$viservers = "VCserver1" $excluded = Get-Content "./exclude-users.txt" foreach ($singleViserver in $viservers){

    Connect-VIServer $singleViserver -user USERNAME -password 'PASSWORD' $sessMgr = Get-View SessionManager
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
  if ((($sess.LastActiveTime).AddHours(4)) -lt (Get-Date) -and $excluded -notcontains $sess.UserName){
    $oldSessions += $sess.Key
  }
}
$sessMgr.TerminateSession($oldSessions)
}


So i ran the script one more time and got the following error message:


Exception calling "TerminateSession" with "1" argument(s): "sessionId"At C:\Scripts\DisconSessions\DisconSessions.ps1:19 char:26 + $sessMgr.TerminateSession <<<< ($oldSessions)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException



The user that was idle for 6hrs was stil connected, i'm one hour ahead of the VCs location but i don't think that matters.
Cheers! If you found this or other information useful, please consider awarding points for "Correct" or "Helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

I don't know why that user's session that was idle for 6 hours wasn't terminated.

I would have to look at the content of the $sess varaible for that specific user.

The error you got on the 2nd run is most probably because the $oldSessions array was empty.

The following version tests for that

$viservers = "VCserver1" 
$excluded = Get-Content "./exclude-users.txt" 
foreach ($singleViserver in $viservers){
    Connect-VIServer $singleViserver -user USERNAME -password 'PASSWORD' 
        $sessMgr = Get-View SessionManager
        $oldSessions = @()
        foreach ($sess in $sessMgr.SessionList){
          if ((($sess.LastActiveTime).AddHours(4)) -lt (Get-Date) -and $excluded -notcontains $sess.UserName){
            $oldSessions += $sess.Key
          }
        }
        if($oldSessions.Count -gt 0){
            $sessMgr.TerminateSession($oldSessions)
        }
}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
bradley4681
Expert
Expert

anyway to keep a running log of who get's disconnected and when?

Cheers! If you found this or other information useful, please consider awarding points for "Correct" or "Helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

Sure, you can do something like this

$report = @()
$viservers = "VCserver1" 
$excluded = Get-Content "./exclude-users.txt" 
foreach ($singleViserver in $viservers){
    Connect-VIServer $singleViserver -user USERNAME -password 'PASSWORD' 
        $sessMgr = Get-View SessionManager
        $oldSessions = @()
        foreach ($sess in $sessMgr.SessionList){
          if ((($sess.LastActiveTime).AddHours(4)) -lt (Get-Date) -and $excluded -notcontains $sess.UserName){
            $oldSessions += $sess.Key
            $row = "" | Select UserName,FullName,Timestamp,Server,LoginTime,LastActiveTime
            $row.UserName = $see.userName
            $row.FullName = $sess.fullName
            $row.Timestamp = Get-Date
           
$row.Server = $singleVIServer
            $row.LoginTime = $sess.loginTime             $row.LastACtiveTime = $sess.lastActiveTime             $report += $row          }         }         if($oldSessions.Count -gt 0){             $sessMgr.TerminateSession($oldSessions)         } } $report


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
bradley4681
Expert
Expert

finally got around to playing with this again and noticed that powershell will peg the cpu while running this script. any particular reason?

Cheers! If you found this or other information useful, please consider awarding points for "Correct" or "Helpful".
Reply
0 Kudos
LucD
Leadership
Leadership

There are no CPU-intensive parts in the script afaik.

Was the CPU high on the PC where you run the script or on the vCenter ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos