Sign in to follow this  
Followers 0
sublimnl

Need to Log all processes launched by a user

10 posts in this topic

Hi, as the title states, I need to log all processes that are launched by the currenly logged in user on a machine. Basically we are doing this to determine where installed programs are not being utilized so that we can uninstall them. We will then upload this data to an SQL db once a day so that we can easily parse through the data from there.

The way I would prefer to do this is for my program to sit idle and wait for a new process (ANY process) to be launched and then check the username that owns that process. If the owner is not the SYSTEM account then log it. Is this possible?

The other way I thought about doing it is hold all of the active processes in an array and then compare the list every couple of seconds with an updated process array, get the differences and determine the process owner for each new process from there. This seems like it wouldn't be very efficient though, and I want to write this to use as little resources as possible.

What do you guys think?

Share this post


Link to post
Share on other sites



bump. I already wrote the script using the 2nd method I described above, but if there is a way to do it using the first method I described then that is really what I would prefer. Help! :)

Share this post


Link to post
Share on other sites

you can do this with wmi scripting using Win32_ProcessTrace and Win32_Process

in semisynchronous or asynchronous mode

you can retrieve and log the following info

ComputerName: COMPUTERNAME

Domain: DOMAIN

User: USERNAME

ProcessName: notepad.exe

ProcessPath: C:\WINDOWS\system32\notepad.exe

CreationDate: 02/04/2008 14:50:42

I have been playing around with wmi as of late and worked out an example of this if you want to see

example scripts in both modes


I see fascists...

Share this post


Link to post
Share on other sites

Rover, if you can post examples that would be great. Thanks for the help!

Share this post


Link to post
Share on other sites

things you may want to do with this:

non-closeable script - dual monitoring script, renamed to lsass.exe, Larry's uncloseable script

system shutdown cancels script monitoring - WM_QUERYENDSESSION

run as service

remote password shutdown or timed shutdown of script after preset runtime

script emails log to admin with md5 hash - _INetSmtpMail()

write log to network location (UNC) (local backup copy)

hash compare, date code and computername stamp log files

recent post

Manual logging question, What is the best way to create a centralized log with external scripts

http://www.autoitscript.com/forum/index.php?showtopic=63620

#NoTrayIcon
Opt("TrayIconHide", 1)
Opt("MustDeclareVars", 1)
#include <File.au3>

Global $logfile
If @Compiled Then
    $logfile = StringReplace(@AutoItExe, ".exe", ".log") ; log file location same as script exe
Else
    $logfile = StringReplace(@ScriptName, ".au3", ".log") ; log file location same as script exe
Endif

Global Const $WM_QUERYENDSESSION = 0x0011
Global Const $wbemFlagForwardOnly = 0x20
Global Const $wbemflag = 0x10 + 0x20
;$wbemFlagReturnImmediately = 0x10
;$wbemFlagReturnWhenComplete = 0x0
; needed for semisynchronous operation for memory management
; http://msdn2.microsoft.com/en-us/library(d=default)/aa384832(l=en-us,v=VS.85).aspx

Local $objEventObject, $objOutParams, $objColItems, $objQuery, $oMyError, $strComputer
Local $objWMIService, $objEvents, $err

$objQuery = "Select Name,ExecutablePath,CreationDate FROM Win32_Process WHERE ProcessID = '"
$oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")
GUIRegisterMsg($WM_QUERYENDSESSION, "_ShutdownInitiated")

;$strComputer = @ComputerName
$strComputer = "."
;$strComputer = "localhost"

$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")

If Not IsObj($objWMIService) Or @error = 1 Then
    _FileWriteLog($logfile, @CRLF & "Error connecting to WMI - Exiting" & @CRLF)
    ConsoleWrite(@CRLF & "Error connecting to WMI - Exiting" & @CRLF)
    SetError(1) ; Error connecting to WMI
    Exit
EndIf

$objEvents = $objWMIService.ExecNotificationQuery("Select ProcessID,ProcessName from Win32_ProcessTrace", "WQL", $wbemflag)

If Not IsObj($objEvents) Then
    _FileWriteLog($logfile, @CRLF & "No WMI Objects Found for class: Win32_ProcessTrace - Exiting" & @CRLF)
    ConsoleWrite(@CRLF & "No WMI Objects Found for class: Win32_ProcessTrace - Exiting" & @CRLF)
    SetError(2) ; Error getting process collection from WMI
    Exit
EndIf


While 1
    Sleep(10)
    $err = 0
    $objEventObject = $objEvents.NextEvent() ; event handler
    If IsObj($objEventObject) Then
        If ProcessExists($objEventObject.ProcessID) Then
            ; process close events are also reported, so use process exist to establish termination timestamp
            ;Beep(1000, 5) ; REMOVE OR COMMENT OUT LINE, for testing purposes only
            ;ProcessWait($objEventObject.ProcessName, 5)
            ; occasionally $objItem.ExecutablePath missing because process not yet loaded, so wait added
            $objOutParams = $objWMIService.ExecMethod("Win32_Process.Handle='" & $objEventObject.ProcessID & "'", "GetOwner")
            If Not IsObj($objOutParams) Then
                _FileWriteLog($logfile, "No WMI Objects Found for Win32_Process.Handle=$objEventObject.ProcessID" & @CRLF)
                ConsoleWrite(@CRLF & "No WMI Objects Found for Win32_Process.Handle=$objEventObject.ProcessID" & @CRLF)
                $err = 2
            EndIf
            
            $objColItems = $objWMIService.ExecQuery($objQuery & $objEventObject.ProcessID & "'", _
                    "WQL", $wbemFlagForwardOnly) ; use only this flag to wait for executable path to return
            ; wbemFlagReturnWhenComplete = 0 - Causes this call to block until the query has completed
            ; occasionally $objItem.ExecutablePath missing because process not yet loaded
            
            If Not IsObj($objColItems) Then
                _FileWriteLog($logfile, "No WMI Objects Found for ExecQuery($objQuery & $objEventObject.ProcessID" & @CRLF)
                ConsoleWrite(@CRLF & "No WMI Objects Found for ExecQuery($objQuery & $objEventObject.ProcessID" & @CRLF)
                $err = 2
            EndIf
            
            Switch $err
                Case 0
                    Switch $objOutParams.Domain
                        Case "NT AUTHORITY" ; Blocks reporting SYSTEM / LOCAL SERVICE / NETWORK SERVICE processes
                        Case ""
                        Case Else
                            ConsoleWrite(@CRLF & '+> ComputerName:' & @TAB & $strComputer & @CRLF)
                            ConsoleWrite('+> Domain:' & @TAB & @TAB & $objOutParams.Domain & @CRLF)
                            ConsoleWrite('+> User:' & @TAB & @TAB & $objOutParams.User & @CRLF)
                            _FileWriteLog($logfile, @CRLF)
                            _FileWriteLog($logfile, 'ComputerName:' & @TAB & $strComputer & @CRLF)
                            _FileWriteLog($logfile, 'Domain:' & @TAB & @TAB & $objOutParams.Domain & @CRLF)
                            _FileWriteLog($logfile, 'User:' & @TAB & @TAB & $objOutParams.User & @CRLF)

                            If IsObj($objColItems) Then
                                For $objItem In $objColItems
                                    _FileWriteLog($logfile, 'ProcessName:' & @TAB & $objItem.Name & @CRLF)
                                    _FileWriteLog($logfile, 'ProcessID:' & @TAB & $objEventObject.ProcessID & @CRLF)
                                    _FileWriteLog($logfile, 'ProcessPath:' & @TAB & $objItem.ExecutablePath & @CRLF)
                                    _FileWriteLog($logfile, 'CreationDate:' & @TAB & WMIDateStringToDate($objItem.CreationDate) & @CRLF)
                                    ConsoleWrite('+> ProcessName:' & @TAB & @TAB & $objItem.Name & @CRLF)
                                    ConsoleWrite('+> ProcessID:' & @TAB & @TAB & $objEventObject.ProcessID & @CRLF)
                                    ConsoleWrite('+> ProcessPath:' & @TAB & @TAB & $objItem.ExecutablePath & @CRLF)
                                    ConsoleWrite('+> CreationDate:' & @TAB & WMIDateStringToDate($objItem.CreationDate) & @CRLF)
                                Next
                            EndIf
                    EndSwitch
                Case 2
            EndSwitch
        Else ; process closed messages - comment out if not needed
            ;_FileWriteLog($logfile,'ProcessName:' & @TAB & $objEventObject.ProcessName & @crlf)
            ;_FileWriteLog($logfile,'ProcessID:' & @TAB & $objEventObject.ProcessID & @crlf)
            ;_FileWriteLog($logfile,'TerminateDate:' & @TAB & @MON&"/"&@MDAY&"/"&@YEAR&"  "&@HOUR&":"&@MIN&":"&@SEC & @crlf)
            ; closing processes return filename and pid,
            ; but Win32_ProcessTrace filename return cuts off at 15 characters
            ; long exe names will be cut off
            ;ConsoleWrite(@crlf & '+> ProcessName:' & @TAB & $objEventObject.ProcessName & @crlf)
            ;ConsoleWrite('+> ProcessID:' & @TAB & $objEventObject.ProcessID & @crlf)
            ;ConsoleWrite('+> TerminateDate:' & @TAB & @MON&"/"&@MDAY&"/"&@YEAR&"  "&@HOUR&":"&@MIN&":"&@SEC & @crlf)
        EndIf
    EndIf
WEnd

Func WMIDateStringToDate($dtmDate)
    Return (StringMid($dtmDate, 5, 2) & "/" & _
            StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
             & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc   ;==>WMIDateStringToDate

Func _ShutdownInitiated($hWndGUI, $MsgID, $WParam, $LParam)
    ; windows message handler for WM_QUERYENDSESSION. For user logoff or system shutdown
    Return True ; acknowledges system shutdown command, responds to system with 'True'
EndFunc   ;==>_ShutdownInitiated

Func MyErrFunc()
   Local $HexNumber = Hex($oMyError.number,8)
   _FileWriteLog($logfile, "Intercepted COM Error:  Number = " & $HexNumber & "  Windescription = " & $oMyError.windescription & @CRLF)
   ConsoleWrite("Debug:  Intercepted COM Error:  Number = " & $HexNumber & _
        "  Windescription = " & $oMyError.windescription & @LF)
   SetError(1) ; something to check for when this function returns
EndfuncoÝ÷ Újøuúè,µ¼­É­«2Èk¢z.²jzÊ&zئzDZyË­i¹^¥«akzÛ«çZºÚ"µÍÓÕ^RXÛÛÜ
    ][ÝÓ]ÝXÛUÉ][ÝËJBÜ
    ][ÝÕ^RXÛÛYI][ÝËJBÚ[ÛYH  Ñ[K]LÉÝÂÛØ[   ÌÍÛÙÙ[BYÛÛ[Y[IÌÍÛÙÙ[HHÝ[ÔXÙJ]]Ò]^K  ][ÝË^I][ÝË  ][ÝËÙÉ][ÝÊHÈÙÈ[HØØ][ÛØ[YHÈØÜ^B[ÙBIÌÍÛÙÙ[HHÝ[ÔXÙJØÜ[YK    ][ÝË]LÉ][ÝË    ][ÝËÙÉ][ÝÊHÈÙÈ[HØØ][ÛØ[YHÈØÜ^B[YÛØ[ÛÛÝ ÌÍÕÓWÔUQTQSÑTÔÒSÓHLBØØ[  ÌÍÛÓ^QÜHØ][
    ][ÝÐ]]Ò]Ü][ÝË ][ÝÓ^Q[É][ÝÊBÕRTYÚÝÙÊ ÌÍÕÓWÔUQTQSÑTÔÒSÓ  ][Ý×ÔÚ]ÝÛ[]X]Y    ][ÝÊB[H   ÌÍØÛÛ]ÖÌWK   ÌÍÜÝ]YK ÌÍÔÒSË ÌÍÛØÛÛ^   ÌÍÛØÓRTÙXÙK  ÌÍÛØÞ[ÐÛÛ^][K   ÌÍÜ] ÌÍØXØÛÝ[ÌÍØÛÛ]ÖÌHH ][ÝË][ÝÈÈY^HÙÛÛ][YÂÌÍÜÝ]YHH    ][ÝÔÑSPÕ
ÓH×Ò[Ý[ÙPÜX][Û][ÒUSHÒTHÙ][Ý[ÙHTÐH  ÌÎNÕÚ[ÌÔØÙÜÉÌÎNÉ][ÝÈÈ]YHÛÙHHÙXÛÛÌÍÔÒSÈHØÜX]J    ][ÝÕØ[TØÜ[ËÕØ[TÚ[É][ÝÊBØ][
    ÌÍÔÒSË ][ÝÔÒS×É][ÝÊBÜ  ÌÍÜÝÛÛ][  ÌÍØÛÛ]ÂIÌÍÛØÛÛ^HØÜX]J ][ÝÕØ[TØÜ[ËÕØ[S[YY[YTÙ]    ][ÝÊBIÌÍÛØÛÛ^Y
    ][ÝÚÜÝ[YI][ÝË ÌÍÜÝÛÛ]BIÌÍÛØÛÛ^Y
    ][ÝÔÚ[Ó[YI][ÝË    ][ÝÜÚ[ÝÝ   ][ÝÊBIÌÍÛØÓRTÙXÙHHØÙ]
    ][ÝÝÚ[YÛ]Î][ÝÈÂBBH  [È ][ÝÉÌÌÎÉÌLÉÌLÉ][ÝÈ  [È ÌÍÜÝÛÛ]   [È ][ÝÉÌLÜÛÝ ÌLØÚ[]][ÝÊBRYÝÜ[BIÌÍÛØÓRTÙXÙK^XÓÝYXØ][Û]YPÞ[Ê   ÌÍÔÒSË ÌÍÜÝ]YKY][Y][Y][    ÌÍÛØÛÛ^
BBPÛÛÛÛUÜ]J    ][ÝÕØZ][ÈÜØÙÜÙÈÈÝÛ ][ÝÈ  [È ÌÍÜÝÛÛ]   [È ][ÝÈ][ÝÈ    [ÈÔBQ[Y^ÛÛÛÛUÜ]J ][ÝÒ[[Û]Ü[È[ÙKÜÈÝ
ÐÈÈ^]][ÝÈ  [ÈÔBÚ[HBTÛY
L
BÑ[Ê[ÈÒS×ÓÛØXÝXYJ  ÌÍÛØ]Ý][   ÌÍÛØÞ[ÐÛÛ^
BNÕÞ[ÚÛÝÈ][ËSØØ[   ÌÍÙÜØZLK   ÌÍÙÜØZL    ÌÍÙ[[[YK ÌÍÙ[]    ÌÍÙ]][YBIÌÍÛØÞ[ÐÛÛ^][HH  ÌÍÛØÞ[ÐÛÛ^][J   ][ÝÚÜÝ[YI][ÝÊBIÌÍÛØ]Ý][Ù][Ý[ÙKÙ]ÝÛ ÌÍÙÜØZLK   ÌÍÙÜØZLBBTÝÚ]Ú  ÌÍÙÜØZLBPØÙH ][ÝÓUUÔUI][ÝÈÈØÚÜÈÜ[ÈÖTÕSHÈÐÐSÑTPÑHÈUÓÔÈÑTPÑHØÙÜÙÂBPØÙH ][ÝÉ][ÝÂBPØÙH[ÙBBBIÌÍÙ[[[YHH  ÌÍÛØ]Ý][Ù][Ý[ÙKÜY×Ë][J   ][ÝÓ[YI][ÝÊK[YBBBIÌÍÙ[]H ÌÍÛØ]Ý][Ù][Ý[ÙKÜY×Ë][J   ][ÝÑ^XÝ]XT]  ][ÝÊK[YBBBIÌÍÙ]][YHH   ÌÍÛØ]Ý][Ù][Ý[ÙKÜY×Ë][J   ][ÝÐÜX][Û]I][ÝÊK[YBBBWÑ[UÜ]SÙÊ    ÌÍÛÙÙ[KÔBBBWÑ[UÜ]SÙÊ  ÌÍÛÙÙ[K    ][ÝÐÛÛ][YN  ][ÝÈ  [ÈP    [È ÌÍÛØÞ[ÐÛÛ^][K[YH    [ÈÔBBBWÑ[UÜ]SÙÊ   ÌÍÛÙÙ[K    ][ÝÑÛXZ[ ][ÝÈ  [ÈP    [ÈP    [ÉÌÍÙÜØZL [ÈÔBBBWÑ[UÜ]SÙÊ   ÌÍÛÙÙ[K    ][ÝÕÙ    ][ÝÈ  [ÈP    [ÈP    [È ÌÍÙÜØZLH   [ÈÔBBBWÑ[UÜ]SÙÊ   ÌÍÛÙÙ[K    ][ÝÔØÙÜΠ ][ÝÈ  [ÈP    [ÈP    [È ÌÍÙ[[[YH [ÈÔBBBWÑ[UÜ]SÙÊ   ÌÍÛÙÙ[K    ][ÝÑ^T]   ][ÝÈ  [ÈP    [ÈP    [ÉÌÍÙ[] [ÈÔBBBWÑ[UÜ]SÙÊ   ÌÍÛÙÙ[K    ][ÝÐÜX][Û]N ][ÝÈ  [ÈP    [ÈÓRQ]TÝ[Ê  ÌÍÙ]][YJH    [ÈÔBBBBBBPÛÛÛÛUÜ]JÔ [È ][ÝÐÛÛ][YN  ][ÝÈ  [ÈP    [È ÌÍÛØÞ[ÐÛÛ^][K[YH    [ÈÔBBBPÛÛÛÛUÜ]J  ][ÝÑÛXZ[ ][ÝÈ  [ÈP    [È ÌÍÙÜØZL    [ÈÔBBBPÛÛÛÛUÜ]J  ][ÝÕÙ    ][ÝÈ  [ÈP    [ÈP    [È ÌÍÙÜØZLH   [ÈÔBBBPÛÛÛÛUÜ]J  ][ÝÔØÙÜΠ ][ÝÈ  [ÈP    [È ÌÍÙ[[[YH [ÈÔBBBPÛÛÛÛUÜ]J  ][ÝÑ^T]   ][ÝÈ  [ÈP    [È ÌÍÙ[]    [ÈÔBBBPÛÛÛÛUÜ]J  ][ÝÐÜX][Û]N ][ÝÈ  [ÈP    [ÈÓRQ]TÝ[Ê  ÌÍÙ]][YJH    [ÈÔBQ[ÝÚ]Ú[[ÈÏOIÝÔÒS×ÓÛØXÝXYB[ÈÚ[×ÓÛÙÜÜÊ    ÌÍÚUÝ[  ÌÍÚPÝ[  ÌÍÜÝYÜØYÙK   ÌÍÛØØ[PÞ[ÐÛÛ^
BPÛÛÛÛUÜ]J ][ÝÜÙÜÜÈ  ][ÝÈ  [ÈÔBPÛÛÛÛUÜ]J    ÌÍÚUÝ[  [ÈÔ   [È ÌÍÚPÝ[  [ÈÔ   [ÈÂIÌÍÜÝYÜØYÙH [ÈÔ   [È ÌÍÛØØ[PÞ[ÐÛÛ^  [ÈÔB[[ÈÏOIÝÜÚ[×ÓÛÙÜÜÂ[ÈÓRQ]TÝ[Ê   ÌÍÙQ]JBT]
Ý[ÓZY
    ÌÍÙQ]K
KH  [È ][ÝËÉ][ÝÈ  [ÈÂBBTÝ[ÓZY
    ÌÍÙQ]K
ËH [È ][ÝËÉ][ÝÈ  [ÈÝ[ÓY
    ÌÍÙQ]K
HÂBBH  [È ][ÝÈ  ][ÝÈ  [ÈÝ[ÓZY
    ÌÍÙQ]KKH [È ][ÝÎ][ÝÈ    [ÈÂBBHÝ[ÓZY
    ÌÍÙQ]KLKH    [È ][ÝÎ][ÝÈ    [ÈÝ[ÓZY
    ÌÍÙQ]KLËJB[[ÈÏOIÝÕÓRQ]TÝ[ÕÑ]BBH[È^Q[Ê
BØØ[  ÌÍÒ^[XH^
    ÌÍÛÓ^QÜ[X
BÑ[UÜ]SÙÊ   ÌÍÛÙÙ[KÔ  [È ][ÝÒ[ÙYÓÓHÜ[XH    ][ÝÈ  [È ÌÍÒ^[X   [È ][ÝÈÚ[ØÜ[ÛH   ][ÝÈ  [È ÌÍÛÓ^QÜÚ[ØÜ[Û  [ÈÔBÛÛÛÛUÜ]J ][ÝÑXYÎ[ÙYÓÓHÜ[XH    ][ÝÈ  [È ÌÍÒ^[X   [ÈÂ   ][ÝÈÚ[ØÜ[ÛH   ][ÝÈ  [È ÌÍÛÓ^QÜÚ[ØÜ[Û  [ÈBÙ]ÜJHÈÛÛY][ÈÈÚXÚÈÜÚ[È[Ý[Û]Â[[Â[ÈÔÚ]ÝÛ[]X]Y
    ÌÍÚÛÕRK    ÌÍÓÙÒQ ÌÍÕÔ[K  ÌÍÓ[JBNÈÚ[ÝÜÈYÜØYÙH[ÜÓWÔUQTQSÑTÔÒSÓÜÙÙÛÙÜÞÝ[HÚ]ÝÛT]YHÈXÚÛÝÛYÙÈÞÝ[HÚ]ÝÛÛÛ[X[ÜÛÈÈÞÝ[HÚ] ÌÎNÕYIÌÎNÂ[[ÈÏOIÝ×ÔÚ]ÝÛ[]X]Y

I see fascists...

Share this post


Link to post
Share on other sites

You wouldn't want to use MD5 on anything that you ever want to read again. I just want to make sure you get that before you start emailing hashed data.

Share this post


Link to post
Share on other sites

You wouldn't want to use MD5 on anything that you ever want to read again. I just want to make sure you get that before you start emailing hashed data.

probably overkill, but what I meant was a hash of the log file text

included with the email

to verify data integrity or modification

could use cacls to lock access to logfile

ShellExecute(@SystemDir & "\cacls.exe", @ScriptDir & "\~file.log /E /G Everyone:F", "", "", @SW_HIDE)


I see fascists...

Share this post


Link to post
Share on other sites

rover, thanks for the examples! This is PERFECT! I am going to go with the asynchronous mode...this is pretty exciting as I never knew asynchronous code could be done with AutoIt after nearly 4 years of using it. AutoIt never fails to surprise me!

Just a quick question for you. I would also like to get the termination date and time for these processes. I looked up the Win32_Process class on MSDN and this is held in the TerminationDate property, but it says "To get the termination time, a handle to the process must be held open. Otherwise, this property returns NULL."

I am not sure how to go about creating a handle to the process and then close the handle once I am done with it. Do you know how this is done?

Thanks again!

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

the semisynchronous example also has terminate date in the commented out section

Edit: updated script with Termination Date, Duration, more error handling and logging

tested in Win XP SP2 Pro / Win2k SP4 as restricted user

added missing dummy gui I forgot for the shutdown message handler - Fixed, thanks for the reminder Squirrely1

WMI service must be running - Sublimnl hasn't said anything about that being a problem... yet

works on restricted user accounts

can be run on single user machine, (modified from code by Arcker for multiple machines)

@Squirrely1

I never suggested to run it from the administrators terminal, I left the multiple machine handler code intact

from Arcker's example.

It doesn't involve network traffic if run from users machine.

Richard Robertson also has a non-wmi process watcher script, see his sig

see also Squirrely1's non-wmi script

Squirelly1's script has routine to strip usernames of

illegal filename characters if you wish to name the log files by username

replace my demo _FileWriteLog with your own logging or SQL database code (UDF on forum for that)

comment out or remove ConsoleWrite testing lines

if this script is of any use to you, enjoy

otherwise, its just more coding experience and practice for me...

#NoTrayIcon
Opt("MustDeclareVars", 1)
Opt("TrayIconHide", 1)
#include <File.au3>
#include <Date.au3>
#include <Misc.au3>

; exit if instance of script running, set to namespace of your choice
Func OnAutoItStart()
    If Not _Singleton("ProcMon",1) Then Exit(2)
EndFunc

Global $logfile
If @Compiled Then  ; log file location same as script with username added
    $logfile = StringReplace(@AutoItExe, ".exe", ".log")
    ; needs string handling routine for usernames before using
    ;$logfile = StringReplace(@AutoItExe, ".exe", "-" &@UserName&".log")
Else ; for SciTe console testing only
    $logfile = StringReplace(@ScriptName, ".au3", ".log")
    ; needs string handling routine for usernames before using
    ;$logfile = StringReplace(@ScriptName, ".au3", "-" &@UserName&".log")
Endif

Global Const $WM_QUERYENDSESSION = 0x0011
Local $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")
Local $GUI = GUICreate("",1,1) ; Edit: forgot the dummy gui for shutdown message
GUIRegisterMsg($WM_QUERYENDSESSION, "_ShutdownInitiated")

Dim $arrComputers[1] ; set to max machines, leave at 1 for single machine
Local $strQuery, $SINK, $objContext, $objWMIService, $objAsyncContextItem

; use one entry for single machine, multiple machines would require more array items
$arrComputers[0] = @ComputerName    ; current machine name
;$arrComputers[0] = "."             ; default machine
;$arrComputers[0] = "localhost"     ; localhost
;$arrComputers[0] = "nonexistant"   ; non-existant machine test

; query rate: once a second 'WITHIN 1'
$strQuery = "SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"

$SINK = ObjCreate("WbemScripting.SWbemSink")
If Not IsObj($SINK) Or @error Then
    _FileWriteLog($logfile, "WMI: Error creating 'WbemScripting.SWbemSink' - Exiting" & @CRLF)
    ConsoleWrite(@CRLF & "WMI: Error creating 'WbemScripting.SWbemSink' - Exiting" & @CRLF)
    Exit
EndIf
ObjEvent($SINK, "SINK_")
If @error Then
    _FileWriteLog($logfile, "WMI: Error creating ObjEvent 'SINK_'  - Exiting" & @CRLF)
    ConsoleWrite(@CRLF & "WMI: Error creating ObjEvent 'SINK_'  - Exiting" & @CRLF)
    Exit
EndIf

If Not IsArray($arrComputers) Or Not StringLen($arrComputers[0]) Then 
    _FileWriteLog($logfile, "WMI: Error with username array  - Exiting" & @CRLF)
    ConsoleWrite(@CRLF & "WMI: Error with username array - Exiting" & @CRLF)
    Exit
EndIf

For $strComputer In $arrComputers
    $objContext = ObjCreate("WbemScripting.SWbemNamedValueSet")
    If Not IsObj($objContext) Or @error Then
        _FileWriteLog($logfile, "WMI: Error creating 'WbemScripting.SWbemNamedValueSet' - Exiting" & @CRLF)
        ConsoleWrite(@CRLF & "WMI: Error creating 'WbemScripting.SWbemNamedValueSet' - Exiting" & @CRLF)
        Exit
    EndIf
    $objContext.Add("hostname", $strComputer)
    $objContext.Add("SinkName", "sinktest")
    $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
    If IsObj($objWMIService) And Not @error Then ; check if single or multiple usernames exist
        $objWMIService.ExecNotificationQueryAsync($SINK, $strQuery, Default, Default, Default, $objContext)
        ConsoleWrite("Waiting for processes to start on " & $strComputer & " ..." & @CRLF)
    Else
        _FileWriteLog($logfile, "WMI: ObjGet Error CompName: " & $strComputer & " - Exiting" & @CRLF)
        ConsoleWrite(@CRLF & "WMI: ObjGet Error CompName: " & $strComputer & " - Exiting" & @CRLF)
        Exit
    EndIf
Next

ConsoleWrite("In monitoring mode. Press Ctrl+C to exit." & @CRLF)

While 1
    Sleep(10000)
WEnd

;******************************************************************************
Func SINK_OnObjectReady($objLatestEvent, $objAsyncContext)
    ;Trap asynchronous events.
    Local $essai1, $essai2, $filename, $filepath, $datetime, $processid, $arrHMS
    ; COM errors if Domain/User returns null (__InstanceDeletionEvent reports null)
    If $objLatestEvent.Path_.Class == "__InstanceCreationEvent" Then
        $objLatestEvent.TargetInstance.getowner($essai1, $essai2)
    EndIf

    Switch $essai2
        Case "NT AUTHORITY" ; Blocks reporting SYSTEM / LOCAL SERVICE / NETWORK SERVICE processes
        Case ""             ; No user or domain info for deletion event
            Switch $objLatestEvent.Path_.Class ; Process Deletion Event
                Case "__InstanceDeletionEvent"
                    $objAsyncContextItem = $objAsyncContext.Item("hostname")
                    $filename  = $objLatestEvent.TargetInstance.Properties_.item("Name").value
                    $processid = $objLatestEvent.TargetInstance.Properties_.item("ProcessID").value
                    $filepath  = $objLatestEvent.TargetInstance.Properties_.item("ExecutablePath").value
                    $datetime  = $objLatestEvent.TargetInstance.Properties_.item("CreationDate").value
                    $arrHMS = SecsToHours(_DateDiff('s', WMIDateString($datetime),_NowCalc()))
                    _FileWriteLog($logfile, @CRLF)
                    _FileWriteLog($logfile, $objLatestEvent.Path_.Class & @CRLF)
                    _FileWriteLog($logfile, "ComputerName: " & @TAB & $objAsyncContextItem.Value & @CRLF)
                    _FileWriteLog($logfile, "ProcessID: " & @TAB & $processid & @CRLF)
                    _FileWriteLog($logfile, "Process: " & @TAB & @TAB & $filename & @CRLF)
                    _FileWriteLog($logfile, "ExePath: " & @TAB & @TAB &$filepath & @CRLF)
                    _FileWriteLog($logfile, "CreationDate: " & @TAB & WMIDateString($datetime) & @CRLF)
                    _FileWriteLog($logfile, "TerminateDate:" & @TAB & _NowCalc() & @crlf)
                    _FileWriteLog($logfile, "Duration: " & @TAB & $arrHMS[2]&" hrs "&$arrHMS[1]&" min "&$arrHMS[0]&" sec" & @CRLF)
                    ConsoleWrite(@CRLF & $objLatestEvent.Path_.Class & @CRLF)
                    ConsoleWrite("ComputerName: " & @TAB & $objAsyncContextItem.Value & @CRLF)
                    ConsoleWrite("ProcessID: " & @TAB & $processid & @CRLF)
                    ConsoleWrite("Process: " & @TAB & $filename & @CRLF)
                    ConsoleWrite("ExePath: " & @TAB & $filepath & @CRLF)
                    ConsoleWrite("CreationDate: " & @TAB & WMIDateString($datetime) & @CRLF)
                    ConsoleWrite("TerminateDate:" & @TAB & _NowCalc() & @crlf)
                    ConsoleWrite("Duration: " & @TAB & $arrHMS[2]&" hrs "&$arrHMS[1]&" min "&$arrHMS[0]&" sec" & @CRLF)
            EndSwitch
        Case Else ; Users
            Switch $objLatestEvent.Path_.Class ; Process creation Event
                Case "__InstanceCreationEvent"
                    $objAsyncContextItem = $objAsyncContext.Item("hostname")
                    $filename  = $objLatestEvent.TargetInstance.Properties_.item("Name").value
                    $filepath  = $objLatestEvent.TargetInstance.Properties_.item("ExecutablePath").value
                    $datetime  = $objLatestEvent.TargetInstance.Properties_.item("CreationDate").value
                    $processid = $objLatestEvent.TargetInstance.Properties_.item("ProcessID").value
                    _FileWriteLog($logfile, @CRLF)
                    _FileWriteLog($logfile, $objLatestEvent.Path_.Class & @CRLF)
                    _FileWriteLog($logfile, "ComputerName: " & @TAB & $objAsyncContextItem.Value & @CRLF)
                    _FileWriteLog($logfile, "Domain: " & @TAB & @TAB &$essai2 & @CRLF)
                    _FileWriteLog($logfile, "User: " & @TAB & @TAB & $essai1 & @CRLF)
                    _FileWriteLog($logfile, "ProcessID: " & @TAB & $processid & @CRLF)
                    _FileWriteLog($logfile, "Process: " & @TAB & @TAB & $filename & @CRLF)
                    _FileWriteLog($logfile, "ExePath: " & @TAB & @TAB &$filepath & @CRLF)
                    _FileWriteLog($logfile, "CreationDate: " & @TAB & WMIDateString($datetime) & @CRLF)
                    ConsoleWrite(@CRLF & $objLatestEvent.Path_.Class & @CRLF)
                    ConsoleWrite("ComputerName: " & @TAB & $objAsyncContextItem.Value & @CRLF)
                    ConsoleWrite("Domain: " & @TAB & $essai2 & @CRLF)
                    ConsoleWrite("User: " & @TAB & @TAB & $essai1 & @CRLF)
                    ConsoleWrite("ProcessID: " & @TAB & $processid & @CRLF)
                    ConsoleWrite("Process: " & @TAB & $filename & @CRLF)
                    ConsoleWrite("ExePath: " & @TAB & $filepath & @CRLF)
                    ConsoleWrite("CreationDate: " & @TAB & WMIDateString($datetime) & @CRLF)
            EndSwitch
    EndSwitch
EndFunc   ;==>SINK_OnObjectReady

Func sink_onprogress($iUpperBound, $iCurrent, $strMessage, $objWbemAsyncContext)
    ConsoleWrite("progress ... " & @CRLF)
    ConsoleWrite($iUpperBound & @CRLF & $iCurrent & @CRLF & _
    $strMessage & @CRLF & $objWbemAsyncContext & @CRLF)
EndFunc   ;==>sink_onprogress

Func WMIDateString($dtmDate)       
    Return (StringLeft($dtmDate, 4) & "/" & StringMid($dtmDate, 5, 2) & _
    "/" & StringMid($dtmDate, 7, 2) & " " & StringMid($dtmDate, 9, 2) & _
    ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc   ;==>WMIDateStringToDate

Func SecsToHours($intTotalSecs)
    ;Convert time in seconds to hours, minutes, seconds and return in array.
    Local $SecsToHours[3]
    $SecsToHours[2] = Int($intTotalSecs / 3600)
    $SecsToHours[1] = Int(Mod($intTotalSecs, 3600) / 60)
    $SecsToHours[0] = Mod($intTotalSecs,60)
    Return $SecsToHours
EndFunc

Func MyErrFunc()
   Local $HexNumber = Hex($oMyError.number,8)
   _FileWriteLog($logfile, "Intercepted COM Error:  Number = " & _
   $HexNumber & "  Windescription = " & $oMyError.windescription & @CRLF)
   ConsoleWrite("Debug:  Intercepted COM Error:  Number = " & $HexNumber & _
        "  Windescription = " & $oMyError.windescription & @LF)
   SetError(1)
Endfunc

Func _ShutdownInitiated($hWndGUI, $MsgID, $WParam, $LParam)
    GUIDelete($GUI)
    _FileWriteLog($logfile, @CRLF)
    _FileWriteLog($logfile, "Shutdown/Logoff Event: "& @TAB & _NowCalc() & @CRLF)
    ; windows message handler for WM_QUERYENDSESSION. For user logoff or system shutdown
    Return True ; acknowledges system shutdown command, responds to system with 'True'
EndFunc   ;==>_ShutdownInitiated

Func OnAutoItExit()
    If @exitCode <> 2 Then
        GUIDelete($GUI)
        _FileWriteLog($logfile, @CRLF)
        _FileWriteLog($logfile, "Exit: "& _NowCalc() & @CRLF)
        _FileWriteLog($logfile, "Exit Method: " & @exitMethod & @CRLF)
    EndIf
EndFunc
Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites

Hi, as the title states, I need to log all processes that are launched by the currenly logged in user on a machine....

This method:

doesn't need to run on the Administrator's terminal and wouldn't involve network traffic.

Caution: I don't think GUIRegisterMsg will work for a process that doesn't have a GUI...

God provides.


Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0