ElfCabbage Posted March 19, 2014 Posted March 19, 2014 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. expandcollapse popup#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()
ElfCabbage Posted March 19, 2014 Author Posted March 19, 2014 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
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