Jump to content
Sign in to follow this  
ElfCabbage

File listener script

Recommended Posts

ElfCabbage

Here is code for a file listener.  It takes an .ini file for specifics (directory, file name) and it will execute multiple actions once it finds the files.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_outfile=Listener.exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <File.au3>
#Include <Array.au3>
#Include <Constants.au3>

Opt("TrayOnEventMode",1)

Opt("TrayMenuMode",0)
Opt("TrayAutoPause",0)

;Set log file location
$g_logFile = @ScriptDir & "\listener.log"


;***********************DON'T CHANGE BELOW THIS AREA****************************
;sets build reference
$g_iniFile = getIniFile()
$g_ArrayBaseSize = IniReadSection ( $g_iniFile, "Products" )
dim $g_manLaunch[UBound($g_ArrayBaseSize)]
dim $g_ExecuteArray[24][60][7]
dim $g_pid[20]
dim $g_WaitTime[3]

func main()
    dim $ExamineBuild
    $TimeOut = 2000
;$g_iniFile = $CmdLine[1]
    $i = 1
    ;$ProductName = IniRead($g_iniFile,"Products",$i,"1") ;This product name will be displayed just before executing.  This helps when executing with multiple products.
    $Array_LaunchOrder = IniReadSection ( $g_iniFile, "Products" )

;declaring public variable
    $n = UBound($Array_LaunchOrder)
    dim $Build[$n]
    ; creates tray menu items to launch specific launchOrder items

    For $q =1 to $n-1 Step 1 ; loop to set array of Tray Menu Items
        $g_manLaunch[$q] = TrayCreateItem(IniRead($g_iniFile,"Products",$q,"1"))
        TrayItemSetOnEvent(-1,"singleExecute")
        ;MsgBox(0,"id",TrayItemGetText($g_manLaunch[$q]))
    Next
    TraySetState()

;Credentials to build directory
    ;$Networkshare = 
    ;$UserName = 
    ;$NetworkPassword = 
    ;MountBuild($Networkshare, $UserName, $NetworkPassword);Ensures credentials to build directory
    Do
        For $i = 1 To $n-1 Step 1 ;this for loop is to cycle through install dirs checking for new builds of multiple products

            $CurrentSection = $Array_LaunchOrder[$i][1]
            $BuildDir = IniRead($g_iniFile,$CurrentSection,"BuildDir","1")
            $BuildSuffix = IniRead($g_iniFile,$CurrentSection,"BuildSuffix","1")
            $StripPrefix = IniRead($g_iniFile,$CurrentSection,"BuildPrefix","LotR")
            $BuildFinish = IniRead($g_iniFile,$CurrentSection,"BuildFinish","cabbage")
            $PassDir = IniRead($g_iniFile,$CurrentSection,"PassDir","elf")
            $ExecuteWait = IniRead($g_iniFile,$CurrentSection,"ExecuteWait","90")
            ;Individual credentials for each section
            $Networkshare = IniRead($g_iniFile,$CurrentSection,"NetworkShare","")
            $UserName = IniRead($g_iniFile,$CurrentSection,"UserName","")
            $NetworkPassword = IniRead($g_iniFile,$CurrentSection,"NetworkPassword","")
            if $Networkshare <> "" then MountBuild($Networkshare, $UserName, $NetworkPassword);Ensures credentials to build directory
            
            if Not $Build[$i] Then
                $Build[$i]=LocateBuildNumber($BuildDir,$StripPrefix);Sets the initual build number
                if $Build[$i] <> 0 Then
                    $answer = MsgBox(260, "Listener - " & $CurrentSection, "Start execution for " & $CurrentSection & "  build " & $Build[$i] & "?  Will default to ""No"" after 20 seconds.", 20)
                    If $answer = 6 Then
                        _FileWriteLog($g_logFile, "User chose to start execution for " & $CurrentSection & ",  build " & $Build[$i] )
                        $Preempted = Preempt($CurrentSection)

                        If $Preempted = 0 Then
                            ExecuteScript(1,$Build[$i],$g_iniFile,$CurrentSection,$PassDir)
                        EndIf
                    EndIf
                    $ExamineBuild = $Build[$i]
                    $TimeOut = 1000
                EndIf

            Else
                $TimeOut = IniRead($g_iniFile,"Timeout","wait","300000")
            EndIf
            
            $ExamineBuild = LocateBuildNumber($BuildDir,$StripPrefix)
            
            _FileWriteLog($g_logFile,"For product: " & $CurrentSection & " the current build #'s are: " & $ExamineBuild & ", " & $Build[$i] & " (new, existing).")
            If ($ExamineBuild <> $Build[$i] And $ExamineBuild <> 0 And $Build[$i] <> 0) Then
                $TimedOutWaiting = BuildNumSuffixWait($BuildFinish)

                if $TimedOutWaiting = 0 Then

                    $DoneAlready = CheckExecution($CurrentSection)
                    $Preempted = Preempt($CurrentSection)
                    ;MsgBox(0,"there?",$DoneAlready)
                    if $DoneAlready = 50 Then
                        _FileWriteLog($g_logFile, "Execution for " & $CurrentSection & ",  build " & $Build[$i] & " has run in the last " & $ExecuteWait & " minutes.  Skipping execution.")

                    ElseIf $Preempted = 0 Then
                        ExecuteScript (0,$ExamineBuild,$g_iniFile,$CurrentSection,$PassDir)
                        $Build[$i] = $ExamineBuild
                    EndIf



                ElseIf $TimedOutWaiting = 18 Then
                    _FileWriteLog($g_logFile, "Continuing to listen.  Skipped execution from " & $CurrentSection & ".")
                EndIf
            EndIf

            ClearExecution($CurrentSection)
            
        Next
        sleep ($TimeOut) ; Sleep 5 minutes
            
    Until 0

EndFunc

;This function is for the execution of a single process via the Tray menu.
Func singleExecute()

    $Array_LaunchOrder = IniReadSection ( $g_iniFile, "Products" )
    $b = UBound($g_ArrayBaseSize)


    For $y = 1 to $b-1 Step 1
        $msg = TrayItemGetState($g_manLaunch[$y])
        
        Select
            Case $msg = 68
                ContinueLoop
            Case $msg = 65

                $CurrentSection = TrayItemGetText($g_manLaunch[$y])
                $buildDir = IniRead($g_iniFile,$CurrentSection,"BuildDir","1")
                $StripPrefix = IniRead($g_iniFile,$CurrentSection,"BuildPrefix","cabbage" )
                $buildNum = LocateBuildNumber($buildDir,$StripPrefix)

                _FileWriteLog($g_logFile,"starting " & $CurrentSection & " from system tray selection.")
                ExecuteScript(0,$buildNum,$g_iniFile,$CurrentSection,1)
                TrayItemSetState($g_manLaunch[$y],$TRAY_UNCHECKED)
                ExitLoop
        EndSelect
    Next
EndFunc

; This function calculates the time wait period based on the time wait value in the ini file and the current time.
func CalcExecutionTime($CurrentSection)
    $ExecuteWait = IniRead($g_iniFile,$CurrentSection,"ExecuteWait","90")
    $theHour = @HOUR
    $theMin = @MIN
    $Hours = Floor($ExecuteWait/60)
    $Mins = Mod ($ExecuteWait,60)
    $Mins = $theMin - $Mins
    If $Mins < 0 Then
        $theHour = $theHour - 1
        $Mins = 59 + $Mins
    EndIf
    $Hours = $theHour - $Hours
    If $Hours < 0 Then
        $Hours = 23 + $Hours
    EndIf
    $g_WaitTime[1] = $Hours
    $g_WaitTime[2] = $Mins
    
EndFunc

; This function checks to see whether the current product has been executed within it's time wait period.
func CheckExecution($CurrentSection)

    _FileWriteLog($g_logFile,"Checking for recent execution of " & $CurrentSection)
    For $k = 0 To 23
            For $n = 0 To 59

                For $i = 1 To 6 Step 1

                    $file = $g_ExecuteArray[$k][$n][$i]
                    If $file = $CurrentSection Then
                        return 50
                    EndIf
                Next
            Next
    Next

    return 0
EndFunc

; This function clears the execution time array from "current time - time wait value" to at least 2 hours before then.
func ClearExecution($CurrentSection)
    CalcExecutionTime($CurrentSection)
    $KillWait = IniRead($g_iniFile,$CurrentSection,"KillWait","2")
    $n = $g_WaitTime[1]
    $b = $g_WaitTime[1] - $KillWait
    $g = $g_WaitTime[2]
    ;This first if handles the case where we need to clear the beginning and then the end of the array.
    If $b < 0 Then
        For $k = $n To 0 Step -1
            For $j = $g-1 To 0 Step -1
                For $i = 1 To 6 Step 1
                    If $g_ExecuteArray[$k][$j][$i] = $CurrentSection Then
                        $g_ExecuteArray[$k][$j][$i] = ""
                        if $CurrentSection <> "" Then
                            For $w = 0 To UBound($g_pid)-1
                                $Match = StringInStr($g_pid[$w],$CurrentSection)
                                If  $Match <> 0 Then
                                    $ParseMe = StringSplit($g_pid[$w],",")
                                    if ProcessExists($ParseMe[2]) Then

                                        _FileWriteLog($g_logFile,"Process ID " & $ParseMe[2] & " for " & $CurrentSection & " is being shutdown.")
                                        ProcessClose($ParseMe[2])
                                    EndIf
                                    $g_pid[$w] = ""

                                EndIf

                            Next
                        EndIf
                    EndIf
                Next
            Next
            $g = 60
        Next
        For $k = 23 To 23+$b Step -1
            $g = 59
            For $j = $g To 0 Step -1
                For $i = 1 To 6 Step 1
                    If $g_ExecuteArray[$k][$j][$i] = $CurrentSection Then
                        $g_ExecuteArray[$k][$j][$i] = ""
                        if $CurrentSection <> "" Then
                            For $w = 0 To UBound($g_pid)-1
                                $Match = StringInStr($g_pid[$w],$CurrentSection)
                                If  $Match <> 0 Then
                                    $ParseMe = StringSplit($g_pid[$w],",")
                                    if ProcessExists($ParseMe[2]) Then

                                        _FileWriteLog($g_logFile,"Process ID " & $ParseMe[2] & " for " & $CurrentSection & " is being shutdown.")
                                        ProcessClose($ParseMe[2])
                                    EndIf
                                    $g_pid[$w] = ""
                                EndIf

                            Next
                        EndIf
                    EndIf
                Next
            Next

        Next

    Else
        For $k = $n To $b Step -1
            For $j = $g-1 To 0 Step -1
                For $i = 1 To 6 Step 1
                    If $g_ExecuteArray[$k][$j][$i] = $CurrentSection Then
                        $g_ExecuteArray[$k][$j][$i] = ""
                        if $CurrentSection <> "" Then
                            For $w = 0 To UBound($g_pid)-1
                                $Match = StringInStr($g_pid[$w],$CurrentSection)
                                If  $Match <> 0 Then
                                    $ParseMe = StringSplit($g_pid[$w],",")
                                    if ProcessExists($ParseMe[2]) Then

                                        _FileWriteLog($g_logFile,"Process ID " & $ParseMe[2] & " for " & $CurrentSection & " is being shutdown.")
                                        ProcessClose($ParseMe[2])
                                    EndIf
                                    $g_pid[$w] = ""
                                EndIf

                            Next
                        EndIf
                    EndIf
                Next
            Next
            $g = 60
        Next
    EndIf

EndFunc

Func Preempt($CurrentSection)
    $CheckFor = IniRead($g_iniFile,$CurrentSection,"Preempt","")
    if $CheckFor <> "" Then
        For $j = 0 To UBound($g_pid)-1
            $Match = StringInStr($g_pid[$j],$CheckFor)
            If  $Match <> 0 Then
                $ParseMe = StringSplit($g_pid[$j],",")
                if ProcessExists($ParseMe[2]) Then
                    _FileWriteLog($g_logFile,"Process " & $ParseMe[2] & " for " & $CheckFor & " exists and preempts this launch of " & $CurrentSection & ".")
                    Return 5
                Else
                    Return 0
                EndIf
            EndIf

        Next
    EndIf
EndFunc

Func BuildNumSuffixWait($BuildFinish)
    $checkForFinish = FileExists ($BuildFinish)
    $tick = 0
    While ($checkForFinish == 0)
        if $tick = 15 Then
            _FileWriteLog($g_logFile,"Timed out looking for: " & $BuildFinish)
            return 18
        EndIf
        sleep (60000); Sleep 1 Minute
        $checkForFinish = FileExists ($BuildFinish)
        $tick = $tick +1
    WEnd
    _FileWriteLog($g_logFile,"Discovered: " & $BuildFinish)
    return 0
EndFunc

Func ExecuteScript ($flag,$Build,$g_iniFile,$CurrentSection,$PassDir);$flag set 0 will prompt before execution, else, it'll not prompt.
    $k = 1
    dim $answer

    ;This code is to check for Process ID's associated with the product being executed and close them.
    For $j = 0 To UBound($g_pid)-1
        If StringInStr($g_pid[$j],$CurrentSection) <> 0 Then
            $ParseMe = StringSplit($g_pid[$j],",")
            if ProcessExists($ParseMe[2]) Then

                _FileWriteLog($g_logFile,"Process ID " & $ParseMe[2] & " for " & $CurrentSection & " is being shutdown.")
                ProcessClose($ParseMe[2])
            EndIf
        EndIf

    Next
    ; This loop is to add the product name to the execution time array in the first available slot for that minute in time.
    For $w =1 To 6
        $b = @HOUR
        $q = @MIN
        if $g_ExecuteArray[$b][$q][$w] = "" Then
            $g_ExecuteArray[$b][$q][$w] = $CurrentSection
            ExitLoop
        EndIf
    Next

    $NumToEx = IniRead($g_iniFile,$CurrentSection,"NumToEx","1")
    $ExeWait = IniRead($g_iniFile,$CurrentSection,"RunWait","0")
    if $flag = 0 Then
        $answer = MsgBox(4, "Listener - " & $CurrentSection, "Start execution for " & $CurrentSection & " build " & $Build & "?  Will default to ""Yes"" after 20 seconds.", 20)
    EndIf

    If $answer = 7 Then
        _FileWriteLog($g_logFile, "Not starting " & $CurrentSection & " since end user clicked no. Continuing to listen")
    Else
        For $k = 1 To $NumToEx
            $exeCom = "Execute" & $k
            $Execute = IniRead($g_iniFile,$CurrentSection,$exeCom,"")
            _FileWriteLog($g_logFile, "Executing: " & $Execute)
            if $ExeWait = 0 Then
                $pid = Run($Execute)
            ElseIf $ExeWait = 1 Then
                $pid = RunWait($Execute)
            EndIf

            $ProdPid = $CurrentSection & "," & $pid
            _ArrayAdd($g_pid,$ProdPid)
            _FileWriteLog($g_logFile, "Process ID(PID) returned: " & $pid );if PID = 0, then there was an error running.
        Next
    EndIf
EndFunc

func LocateBuildNumber($BuildDir,$StripPrefix) ;This function searches for the latest build, including alpha builds.  Prereq is the build directory must start as a number.
    dim $search = FileFindFirstFile($BuildDir & "\*")
    if $search = -1 then
        MsgBox(0, "Error", "No build folders found.")
        Return 0
    endif

    ; find the most recent build
    SetError(0)
    dim $file = FileFindNextFile($search)
    dim $number = 0
    dim $build
    dim $buildNum
    _FileWriteLog($g_logFile,StringReplace($file,$StripPrefix,"") & " -- " & $StripPrefix)
    while @error <> 1
        if ($file <> ".") and ($file <> "..") then
            _FileWriteLog($g_logFile,StringReplace($file,$StripPrefix,"") & " -- " & $StripPrefix)
            if (Number(StringReplace($file,$StripPrefix,"")) > $number) then
                $number = Number(StringReplace($file,$StripPrefix,""))
                $build = $number

            endif
        endif
        $file = FileFindNextFile($search)
    wend
    FileClose($search)

    if ($build = "") then
        Return 0
    endif
    Return $build
EndFunc

Func MountBuild($NetworkShare, $UserName, $NetworkPassword);This ensures permissions to network shares.
    If Not($UserName = "") Then
        RunWait(@ComSpec & " /c net use " & $NetworkShare & " /u:" & $UserName & " """ & $NetworkPassword & """ /persistent:no", _
            "", @SW_HIDE)   ;I'm including a set of quotes arround the password in case special characters are included.
    EndIf
endfunc

func getIniFile();Defaults to listener.ini if one isn't specified.
    dim $ini
    if ($CmdLine[0] = 0) then
        $ini = @ScriptDir & "\listener.ini"
      Else
        $ini = $CmdLine[1]
    EndIf
    if not FileExists($ini) Then
        _FileWriteLog($g_logFile, "Ini file could not be found: " & $ini)
        MsgBox(48, "Listener", "Ini file could not be found: " & $ini)
        exit 5
    EndIf
    _FileWriteLog($g_logFile, "Ini file: " & $ini)
    return $ini
EndFunc

main()

Share this post


Link to post
Share on other sites
ElfCabbage

Forgot to put the ini file info in:

[Products]
1=Sample
2=Example
 
 
[Timeout]
wait=300000
 
[sample]
BuildFinish=<any file that will appear once a build has finished publishing>
BuildDir = <root directory down to where build directories vary>
BuildSuffix = <text that might come after build number in directory name>
BuildPrefix = <text that might come before build number in directory name>
PassDir = 1
NumToEx = 2
Execute1=<path to file to execute if finish file is found>
Execute2 =<path to file to execute if finish file is found>
ExecuteWait = 30
KillWait = 10
 
[Example]
NetworkShare=<network path to build directory>
UserName=<credentials for permission to build directory>
NetworkPassword=<credentials for permission to build directory>
BuildDir = <root directory down to where build directories vary>
BuildSuffix = 
NumToEx = 1
Execute1=<path to file to execute if finish file is found>
ExecuteWait = 45
 

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  

×