hamster Posted May 21, 2012 Posted May 21, 2012 So, here's my problem: My script is running as Windows service and must every second or so get idle time of a specific user logged on via Remote Desktop.I didn't have any problem getting current user's idle time (in this case, the "current user" is SYSTEM), however I found getting another user's idle time to be very difficult.I imagine one way would be to write output of "query user" to a file and read from it, but I'd really like to avoid unnecessary writing on disk. Another way would be to run a separate script in each user's context and program it to report idle time back to the main script. I don't like this option too - too messy, too many unnecessary processes running.I found this interesting and 90% undocumented function named WinStationQueryInformationW. Here someone got the results I want from it, but it's written in C... I tried to "translate" that into AutoIT language, but I don't really have enough knownledge in this area.Is there anybody out there who could help me to make use of that function? I'm also looking for alternatives...
hamster Posted May 22, 2012 Author Posted May 22, 2012 (edited) If this helps anyone, I'm currently using the code below to get the results from "query user" into array. Tested on English versions of Windows 2003 Server Standard SP2, Windows Server 2008 Enterprise R2, Windows 7. expandcollapse popup#include <Constants.au3> #include <Array.au3> Opt("MustDeclareVars", 1) Local $users = _QueryUser() If Not @error Then _ArrayDisplay($users) Else MsgBox(48, 'Error', $users) EndIf Func _QueryUser() Local $line, $lines, $return Local $runPID = Run(@ComSpec & " /c query useur", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) Do $line = StdoutRead($runPID) If $line Then $lines &= $line Until @error If $lines Then $lines = StringSplit(StringTrimRight(StringReplace(StringRegExpReplace($lines, "(rn)|r|n|(nr)", "|"), ">", ""),1), "|") Local $data[$lines[0]][6] ;Field lengths: (1+)22, 19, 4, 8, 11, the rest For $i = 0 To $lines[0]-1 Step 1 StringStripWS($lines[$i+1], 3) $data[$i][0] = StringStripWS(StringLeft($lines[$i+1], 22), 3) $data[$i][1] = StringStripWS(StringLeft(StringTrimLeft($lines[$i+1], 22), 19), 3) $data[$i][2] = StringStripWS(StringLeft(StringTrimLeft($lines[$i+1], 22+19), 4), 3) $data[$i][3] = StringStripWS(StringLeft(StringTrimLeft($lines[$i+1], 22+19+4), 8), 3) $data[$i][4] = StringStripWS(StringLeft(StringTrimLeft($lines[$i+1], 22+19+4+8), 11), 3) $data[$i][5] = StringStripWS(StringTrimLeft($lines[$i+1], 22+19+4+8+11), 3) Next $return = $data SetError(0) Else Do $line = StderrRead($runPID) If $line Then $lines &= $line Until @error $return = String($lines) SetError(1) EndIf Return($return) EndFunc This code is far from ideal, and I'm still looking for a better way to get this information, especially user's idle time. Edit: made the code more pretty Edited May 22, 2012 by hamster
bshogeman Posted November 2, 2012 Posted November 2, 2012 (edited) Do you know a way that is compatible with Windows XP and Windows 7?And indeed this methode is far from ideal but can't find an other solution to.Now I am looking at using the SCCM client. In the file pwrmgmt.log located in C:\Windows\System32\CCM or C:WINDOWSSYSWOW64CCM you can read the power state of the monitor.In combination with a WMI query to see if there is an active task ending with .scr (screensaver) you can say for sure a pc isn't used. What I do is save the state in a SQlite database, the lib I use is ahkDBA. But using AutoIt you don't need this. Autoit can write to a SQlite database itself without help. Only include this:#include <SQLite.au3>#include <SQLite.dll.au3>In AutoHotKey you need ahkDBA lib from IsNull.If the computer stays in that state for at least 40 minutes I send a shutdown command.The WMI query you can rip out of this VBS script: http://webcache.googleusercontent.com/search?q=cache:sFx_rTsSuFEJ:www.visualbasicscript.com/Power-Off-Unused-PCs-m73824.aspx+&cd=1&hl=nl&ct=clnk&gl=nlAlso I check if there isn't an installer running. Edited November 2, 2012 by bshogeman
Moderators JLogan3o13 Posted November 2, 2012 Moderators Posted November 2, 2012 That vbscript seems kind of long for just monitoring for screensaver. You could do something like this: $pc = "<computername>" $oWMI = ObjGet("winmgmts:" & $pc & "rootcimv2") $oEventSource = $oWMI.ExecNotificationQuery("SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'") While 1 $oEventObject = $oEventSource.NextEvent() If StringRight($oEventObject.TargetInstance.Name, 4) = ".scr" Then $aItems = $oWMI.ExecQuery("Select * from Win32_OperatingSystem") For $element in $aItems $element.Win32Shutdown(4) Next EndIf WEnd "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now