And now for some thing completely different…. (VBscript to show logged on users)

Now let me start by saying I am no scripting guru, in fact apart from a few batch files and a C++ course many years ago I am a novice. However I have the ideas of how scripting / programming works and over the years have managed to throw to gather a few basic scripts.

I did not intend this blog to ever contain scripting (or at least not for a few years yet), but I came across this in work and thought others might find it useful. Now before we start this is a rehash of others work, links to there sites are at the bottom of the post and I would like to thank them for posting there work to the public.

The background to this is that I am currently working on a project to implement grid computing to process long running mathematical modelling jobs. The software CONDOR is a job scheduling application running on a server. The mathematician break there jobs up in to small chunks (maybe severely hundred jobs in total), and the CONDOR server finds available desktop PC’s they are inactive and sends the job to run on them. IF you have used “folding at home” or “Boinc” you will have been the client in the same kind of system.

Now while CONDOR can determine the user activity in terms of keyboard/mouse activity and CPU usage to decided if a computer is free to run jobs, there is no built in way to use the logged in status of the PC to control jobs. The idea is we want jobs to run when users log out of there PC’s, but stop and be prevented from running once a user logs in. To do this I needed to create a script that could return a “True” or “False” result to the question “is any one logged in to this computer”.

My first Idea was PSloggedon from Sysinternals, however this does not return a true false value and would require wrapping up in a second script to parse the output. So I decided to search around for a VB script that could do it all in one step.

This lead me to the following code,

strComputer = "servername"   ' " use "." for local computer 

Set objWMI = GetObject("winmgmts:" _ 
              & "{impersonationLevel=impersonate}!\\" _ 
              & strComputer & "\root\cimv2") 

Set colSessions = objWMI.ExecQuery _ 
    ("Select * from Win32_LogonSession Where LogonType = 10") 

If colSessions.Count = 0 Then 
   Wscript.Echo "No interactive users found" 
Else 
   WScript.Echo "RDP Sessions:"
   For Each objSession in colSessions 
     
     Set colList = objWMI.ExecQuery("Associators of " _ 
         & "{Win32_LogonSession.LogonId=" & objSession.LogonId & "} " _ 
         & "Where AssocClass=Win32_LoggedOnUser Role=Dependent" ) 
     For Each objItem in colList 
       WScript.Echo "Username: " & objItem.Name & " FullName: " & objItem.FullName 
     Next 
   Next 
End If 

Not exactly what I need but at least it will find and display the logged in users, so seems a good starting place, and easy to tidy up.

First of all we don’t want it to tell us a list of users, just return a true of false statement. This is just a case of replacing Wscript.Echo "No interactive users found" with Wscript.Echo "False" , and replacing the whole of the code under the else statment with simply Wscript.Echo "True".

Secondly this script uses the statment “LogonType = 10” from windowsecurity.com we can see that this will give us remote connections, as we want local logged on users we need to replace that with “LogonType = 2”. Ending up with the revised code below.


strComputer = "."   ' " use "." for local computer 
Set objWMI = GetObject("winmgmts:" _ 
           & "{impersonationLevel=impersonate}!\\" _ 
           & strComputer & "\root\cimv2")
Set colSessions = objWMI.ExecQuery _ 
  ("Select * from Win32_LogonSession Where LogonType = 2") 
     
If colSessions.Count = 0 Then     
  Wscript.Echo "FALSE" 
Else
  WScript.Echo "True"
  
End If

Oh and notice we needed to replace the servername with “.” as suggested. Saving this as a .vbs file and running it and a pop up box will display “True” (after all you are logged on to the PC 😉 )

And that was my script done..

Apart from the fact for it to work in CONDOR I needed it to be able to return out put to stdout, which requires it to be running under Cscript.exe (cscrfipt is command line, Wsccript will interact with windows, in this script one will out put to the command line, one will pop up the same out put but in a small window). Now there are several ways to do this, simple run it from the command line by calling it using cscript.exe c:\csccript.exe script.vbs , or you can wrap it up in a batch file. Howevver I came across a nice little trick to enable the script to check if it is run as cscript and if not switch to csccript.


Public objShell : Set objShell = CreateObject("WScript.Shell")
If Instr(1, WScript.FullName, "CScript", vbTextCompare) = 0 Then
    objShell.Run "cscript " & chr(34) & WScript.ScriptFullName & chr(34) & " //Nologo" & chr(34), 0, False
 
    WScript.Quit
End If

Simply pasting this code above the main script, (And I also updated the Wscript.echo to be

Set objStdOut = WScript.StdOut
  objStdOut.Write "UserLoggedIn = True"  

for CONDOR reasons, and we end up with the complete code below.


Public objShell : Set objShell = CreateObject("WScript.Shell")
If Instr(1, WScript.FullName, "CScript", vbTextCompare) = 0 Then
    objShell.Run "cscript " & chr(34) & WScript.ScriptFullName & chr(34) & " //Nologo" & chr(34), 0, False
 
    WScript.Quit
End If
strComputer = "."   ' " use "." for local computer 
Set objWMI = GetObject("winmgmts:" _ 
           & "{impersonationLevel=impersonate}!\\" _ 
           & strComputer & "\root\cimv2")
set colSessions = objWMI.ExecQuery _ 
  ("Select * from Win32_LogonSession Where LogonType = 2") 
     
If colSessions.Count = 0 Then     
  Set objStdOut = WScript.StdOut
  objStdOut.Write "UserLoggedIn = False"
   
  
Else
  Set objStdOut = WScript.StdOut
  objStdOut.Write "UserLoggedIn = True"  
End If

Now run that and how ever you start it, if you don’t use Cscript.exe it will resubmit it’s self using Cscript.exe and output the result to stdout.

Now by playing around with the logonType and other bits of this code we could make it quite useful, it will return the logged on status of a remote machine if you replace the “.” with a valid remote computer name.

Well I hope that may be useful to some, and my thanks goes to those who came before me and provided the foundations, Please visit there sites to see many other great scripting examples.

VBScript – How to show logged on users?

Force Cscripe

DevilWAH