Solved

VB script to kill active and disconnected terminal server sessions

Posted on 2004-10-26
9,626 Views
Last Modified: 2010-08-05
I found the following VB script to kill active and disconnected terminal server sessions on the web, but I'm having difficulty getting it to work.  Since it doesn't provide any output, I don't know why it isn't working.  Can anyone suggest some lines of code to add to allow for stdout to be displayed as it steps through the script?  Is their any obvious problem withthe script?  I'm trying to use it in a Win2k3 terminal services environment.  TIA.

______________________________________________________________________________________________
' KillTsSessions.vbs
' Finds all active TS sessions on server HOST defined
' below and terminates them.  Does not terminate the
' current session if being run remotely.
' If running on local host, set HOST value to ""

HOST = ""


' Get disconnected sessions and log them off
sessions = DisconnectedSessions(HOST)

For each session in sessions
 TerminateWinSession HOST, sessionId
Next

' Now get active sessions and log them off
sessions = ActiveSessions(HOST)

For each session in sessions
 TerminateWinSession HOST, sessionId
Next

Sub TerminateWinSession(Host, sessionId)
 Dim Sh, tmpHost
 Set Sh = createobject("WScript.Shell")
 if trim(Host)="" Then
  tmpHost = ""
 Else
  tmpHost = " /SERVER:" & Host
 End If
 Sh.Run "%COMSPEC% /C rwinsta " & sessionId & tmpHost, 0, False
End Sub

Function ActiveSessions(Host)
 Dim tmpHost, aTmp, aTmp1(), i
 if trim(Host)="" Then
  tmpHost = ""
 Else
  tmpHost = " /SERVER:" & Host
 End If
 aTmp = Split(cmd("qwinsta" & tmpHost & " | find ""Active"""), _
  vbCrLf)
 ReDim aTmp1(-1)
 For i = 0 to UBound(aTmp)
  If Left(aTmp(i),1) <> ">" Then
   Redim Preserve aTmp1(UBound(aTmp1) + 1)
   aTmp1(UBound(aTmp1)) = Trim(Mid(aTmp(i), 42, 6))
  End If
 Next
 ActiveSessions = aTmp1
End Function


Function DisconnectedSessions(Host)
 Dim tmpHost, aTmp, aTmp1(), i
 if trim(Host)="" Then
  tmpHost = ""
 Else
  tmpHost = " /SERVER:" & Host
 End If
 aTmp = Split(cmd("qwinsta" & tmpHost & " | find ""Disconnected"""), _
  vbCrLf)
 ReDim aTmp1(-1)
 For i = 0 to UBound(aTmp)
  If Left(aTmp(i),1) <> ">" Then
   Redim Preserve aTmp1(UBound(aTmp1) + 1)
   aTmp1(UBound(aTmp1)) = Trim(Mid(aTmp(i), 42, 6))
  End If
 Next
 DisconnectedSessions = aTmp1
End Function


Function Cmd(cmdline)
 ' Wrapper for getting StdOut from a console command
 Dim Sh, FSO, fOut, OutF, sCmd
 Set Sh = createobject("WScript.Shell")
 Set FSO = createobject("Scripting.FileSystemObject")
 fOut = FSO.GetTempName
 sCmd = "%COMSPEC% /c " & cmdline & " >" & fOut
 Sh.Run sCmd, 0, True
 If FSO.FileExists(fOut) Then
  If FSO.GetFile(fOut).Size>0 Then
   Set OutF = FSO.OpenTextFile(fOut)
   Cmd = OutF.Readall
   OutF.Close
  End If
  FSO.DeleteFile(fOut)
 End If
End Function
__________________________________________________________________________________
0
Question by:thaller
    7 Comments
     

    Accepted Solution

    by:
    Hi I took some time and added some error handling and which writes to errorlog.txt in the same directory.

    ' KillTsSessions.vbs
    ' Finds all active TS sessions on server HOST defined
    ' below and terminates them.  Does not terminate the
    ' current session if being run remotely.
    ' If running on local host, set HOST value to ""

    '// Added to Create and Open a file to write to
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objOutputFile = objFSO.CreateTextFile(".\ErrorLog.txt", True)

    HOST = ""
    ' Get disconnected sessions and log them off
    sessions = DisconnectedSessions(HOST)
    For each session in sessions
          TerminateWinSession HOST, sessionId
    Next

    ' Now get active sessions and log them off
    sessions = ActiveSessions(HOST)

    For each session in sessions
          TerminateWinSession HOST, sessionId
    Next
    objOutputFile.WriteLine("Done.")
    objOutputFile.Close
    WScript.Quit(0)

    Sub TerminateWinSession(Host, sessionId)
           Dim Sh, tmpHost
           Set Sh = createobject("WScript.Shell")
           If trim(Host)="" Then
                  tmpHost = ""
           Else
                  tmpHost = " /SERVER:" & Host
           End If
           objOutputFile.WriteLine("Executing... " & vbCrLf & "%COMSPEC% /C rwinsta " & sessionId & tmpHost & vbCrLf)
          Err.Clear
           Sh.Run "%COMSPEC% /C rwinsta " & sessionId & tmpHost, 0, False
           If Err <> 0 Then
                 objOutputFile.WriteLine("Error: " & Err.Number & " " & Err.Description)
           End If
    End Sub

    Function ActiveSessions(Host)
          Dim tmpHost, aTmp, aTmp1(), i
          If trim(Host)="" Then
                tmpHost = ""
           Else
                  tmpHost = " /SERVER:" & Host
          End If
          aTmp = Split(cmd("qwinsta" & tmpHost & " | find ""Active"""), vbCrLf)
          ReDim aTmp1(-1)
           For i = 0 to UBound(aTmp)
                  If Left(aTmp(i),1) <> ">" Then
                         Redim Preserve aTmp1(UBound(aTmp1) + 1)
                         aTmp1(UBound(aTmp1)) = Trim(Mid(aTmp(i), 42, 6))
                  End If
           Next
          ActiveSessions = aTmp1
    End Function


    Function DisconnectedSessions(Host)
          Dim tmpHost, aTmp, aTmp1(), i
          If trim(Host)="" Then
                  tmpHost = ""
           Else
                  tmpHost = " /SERVER:" & Host
           End If
           aTmp = Split(cmd("qwinsta" & tmpHost & " | find ""Disconnected"""),vbCrLf)
           ReDim aTmp1(-1)
           For i = 0 to UBound(aTmp)
                  If Left(aTmp(i),1) <> ">" Then
                        Redim Preserve aTmp1(UBound(aTmp1) + 1)
                         aTmp1(UBound(aTmp1)) = Trim(Mid(aTmp(i), 42, 6))
                  End If
            Next
          DisconnectedSessions = aTmp1
    End Function


    Function Cmd(cmdline)
     ' Wrapper for getting StdOut from a console command
          Dim Sh, FSO, fOut, OutF, sCmd
          Set Sh = createobject("WScript.Shell")
          fOut = objFSO.GetTempName
          sCmd = "%COMSPEC% /c " & cmdline & " >" & fOut
          objOutputFile.WriteLine("Executing... " & vbCrLf & sCmd & vbCrLf)
          Err.Clear
          Sh.Run sCmd, 0, True
          If Err <> 0 Then
                 objOutputFile.WriteLine("Error: " & Err.Number & " " & Err.Description)
           End If
           If objFSO.FileExists(fOut) Then
                If objFSO.GetFile(fOut).Size>0 Then
                      Set OutF = objFSO.OpenTextFile(fOut)
                      Cmd = OutF.Readall
                      objOutputFile.Write(Cmd & vbCrLf)
                      OutF.Close
                End If
                  objFSO.DeleteFile(fOut)
           End If
    End Function
    0
     
    LVL 3

    Author Comment

    by:thaller
    Thanks, Andrew...I'll try it out.
    0
     
    LVL 3

    Author Comment

    by:thaller
    Thanks for the time you took....it did do exactly what you said it would.  I still need to work on why the script itself fails but you did exactly what I asked for.
    0
     
    LVL 3

    Author Comment

    by:thaller
    Andrew,
    Again, thanks for the help...I think I've found the problem and I'm hoping you can help out.  The 'rwinsta' command called to kill the sessions will ask the following question upon execution:

    If you reset this session, all users using this protocol will be logged off,
    continue (n=no)?

    How would I echo y to answer the question in the script?
    0
     

    Expert Comment

    by:andrewfHMS
    Thaller,
    Unfortunatley I do not have any server running terminal services were I am currently at so I havent been able to fully test the following....
    But try changing line 38 to
    Sh.Run "%COMSPEC% /C rwinsta " & sessionId & tmpHost, 1, True

    That would change the command to be run in a window ( 1)  and the script will not continue the next line of code till the command is finished running (True)

    To automate it further you could also add code for sendkeys, to send a y to the open console.  That would look like this...

    Sub TerminateWinSession(Host, sessionId)
           Dim Sh, tmpHost
           Set Sh = createobject("WScript.Shell")
           If trim(Host)="" Then
                  tmpHost = ""
           Else
                  tmpHost = " /SERVER:" & Host
           End If
           objOutputFile.WriteLine("Executing... " & vbCrLf & "%COMSPEC% /C rwinsta " & sessionId & tmpHost & vbCrLf)
          Err.Clear
           Sh.Run "%COMSPEC% /C rwinsta " & sessionId & tmpHost, 1, True
           If Err <> 0 Then
                 objOutputFile.WriteLine("Error: " & Err.Number & " " & Err.Description)
           Else
                           Sh.AppActivate "Cmd.exe"
                 Sh.Sleep 100
                 Sh.SendKeys "Y"
                 Sh.Sleep 500
                 Sh.SendKeys "~"
           End If
    End Sub

    0
     
    LVL 3

    Author Comment

    by:thaller
    I really do appreciate the help.  Id like to throw some more points your way; how would I do that?

    When I change line 38 to the following:

    Sh.Run "%COMSPEC% /K rwinsta " & sessionId & tmpHost, 1, True

    I get the following output:

    Invalid parameter(s)
    Reset the session subsytem hardware and software to known initial values.

    RESET SESSION {sessionname | sessionid} [/SERVER:servername] [/V]

      sessionname         Identifies the session with name sessionname.
      sessionid           Identifies the session with ID sessionid.
      /SERVER:servername  The server containing the session (default is current).
      /V                  Display additional information.

    which leads me to believe there is a problem with how sessioId gets it's value.  The output of the "qwinsta" command from the functions ActiveSessions and DisconnectedSessions is the following:

    >console           administrator             0  Active  wdcon              
      rdp-tcp#5        bethy                        1  Active  rdpwd

    where the number preceeding "Active" is the sessionId.  It looks like there is a problem with how the functions ActiveSessions and DisconnectedSessions assign sessionId.  Any thoughts?
    0
     

    Expert Comment

    by:Toky76
    Greetings,
    I am editing this script right now to kill all disconneted sessions except one for specific user. Can anybody help me with that? I dont know where to add a condition to skip session if the user is for example User1.
    Please, help!
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    The Complete Ruby on Rails Developer Course

    Ruby on Rails is one of the most popular web development frameworks, and a useful tool used by both startups and more established companies to build strong graphic user interfaces, and responsive websites and apps.

    Suggested Solutions

    Title # Comments Views Activity
    VB6 - Move MSFLexgrid1 row to MSHFlexgrid 2 if problem 6 32
    Problem to select 11 59
    Vb.net Listview 9 55
    Help in WHSCRIPT 9 26
    When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
    You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
    Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
    Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

    856 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    14 Experts available now in Live!

    Get 1:1 Help Now