Starlord30 Posted October 1, 2020 Share Posted October 1, 2020 We have a scenario where we need to do a wildcard for if a process exists. The process increments itself for each update made to the application which is making our update process a bit harder than normal as we have to update this script each time as well. If we were able to wildcard it, we would not need to do this anymore which would save a lot of time. Here is what our script was. Note: "ProcessToIncrement30.exe" will change to "ProcessToIncrement31.exe" after the application updates. Updates are fairly common, about 3-4 per year. While $Forever < 1 If ProcessExists("ProcessToIncrement30.exe") Then Sleep (15000) Else If @OSArch = "x86" Then Run("C:\Program Files\Test\Test.exe") Else Run("C:\Program Files (x86)\Test\Test.exe") EndIf EndIf WEnd What we changed it to is, but it doesn't work: While $Forever < 1 If ProcessExists("ProcessToIncrement*") Then Sleep (15000) Else If @OSArch = "x86" Then Run("C:\Program Files\Test\Test.exe") Else Run("C:\Program Files (x86)\Test\Test.exe") EndIf EndIf WEnd Basically saying "If the process exists, go to sleep, if not, launch Test.exe which in task manager is labeled as "ProcessToIncrement30.exe". Any ideas on how to wildcard our process? I'm fairly new to AutoIT, but have some knowledge of other languages such as PowerShell and syntax for the two are not even remotely similar. Thanks! Link to comment Share on other sites More sharing options...
TheXman Posted October 1, 2020 Share Posted October 1, 2020 (edited) 19 minutes ago, Starlord30 said: I'm fairly new to AutoIT, but have some knowledge of other languages such as PowerShell and syntax for the two are not even remotely similar. The syntax may be different but the logic is the same. I would do one of 2 things: Get a list of processes (ProcessList()) and do a partial/fuzzy search against the array of processes that is returned to see if the target process exists Using COM, you can do a query against the Win32_Process object to see if your process exists. With WQL, you can do partial/fuzzy searches using the "LIKE" clause. Edited October 1, 2020 by TheXman Musashi 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
Musashi Posted October 1, 2020 Share Posted October 1, 2020 A (simple) approach : The name with the highest increment will be determined. Local $sSearchStr = "ProcessToIncrement" Local $aProcessList = ProcessList() Local $sProcessName = '' Local $bProcessFound = False For $i = 1 To $aProcessList[0][0] If StringRegExp($aProcessList[$i][0], "^" & $sSearchStr & "\d+\.exe$") Then $sProcessName = $aProcessList[$i][0] ConsoleWrite("> >>>> Process in List : " & $sProcessName & @CRLF) $bProcessFound = True EndIf Next If $bProcessFound Then ConsoleWrite("+ >>>> Found : " & $sProcessName & @CRLF) Else ConsoleWrite("! >>>> No process found" & @CRLF) EndIf Starlord30 1 "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
TheXman Posted October 1, 2020 Share Posted October 1, 2020 (edited) Here's a quick & dirty example of using COM to find a process using a partial match. It is written so that if the process name contains the string, it will return true. expandcollapse popup#include <Constants.au3> If fuzzy_process_match('svchost') Then MsgBox($MB_ICONINFORMATION, "INFO", "Process found!") Else MsgBox($MB_ICONWARNING, "WARNING", "Process not found!") EndIf Func fuzzy_process_match($sFuzzyMatch) ; This function will return true if there are process names ; that contain the specified string Local $oWmi, $oInstances ObjEvent("AutoIt.Error", comm_error_handler) ;Get WMI object $oWmi = ObjGet("winmgmts:\\.\root\CIMV2") If Not IsObj($oWmi) Then Exit MsgBox($MB_ICONERROR, "ERROR", "Unable to create WMI object") ;Search for process names that contain the specified string $oInstances = $oWmi.ExecQuery(StringFormat("SELECT name FROM Win32_Process WHERE name like '%%%s%%'", $sFuzzyMatch)) ;Return boolean result Return ($oInstances.Count > 0 ? True : False) EndFunc Func comm_error_handler($oComError) ConsoleWrite(@CRLF) ConsoleWrite(StringFormat("Script Line = %s", $oComError.ScriptLine) & @CRLF) ConsoleWrite(StringFormat("Win Err Desc = %s", StringStripWS($oComError.WinDescription, $STR_STRIPTRAILING)) & @CRLF) ConsoleWrite(StringFormat("Error Number = %i (0x%x)", $oComError.Number, $oComError.Number) & @CRLF) ConsoleWrite(StringFormat("Error Desc = %s", $oComError.Description) & @CRLF) Exit EndFunc Edited October 2, 2020 by TheXman Aesthetic changes to the example script FrancoDM and Starlord30 2 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
Starlord30 Posted October 1, 2020 Author Share Posted October 1, 2020 This worked great - you guys rock. My last question is, how would I loop this? Here is what I tried but it never processes. If I move the WEnd to the bottom to loop the entire thing, I receive syntax errors. expandcollapse popup#include <Constants.au3> $Forever = 0 Sleep (165000) While $Forever < 1 If fuzzy_process_match('Notepad') Then Sleep (25) Else If @OSArch = "x86" Then Run("notepad.exe") Else Run("notepad.exe") EndIf EndIf WEnd Func fuzzy_process_match($sFuzzyMatch) ; This function will return true if there is a process that contains ; the specified string Local $oWmi, $oInstances ObjEvent("AutoIt.Error", comm_error_handler) ;Get WMI object $oWmi = ObjGet("winmgmts:\\.\root\CIMV2") If Not IsObj($oWmi) Then Exit MsgBox($MB_ICONERROR, "ERROR", "Unable to create WMI object") With $oWmi ;Search for process that contains the specified string $oInstances = .ExecQuery("SELECT name FROM Win32_Process WHERE name like '%" & $sFuzzyMatch & "%'") If $oInstances.Count > 0 Then Return True Else Return False EndIf EndWith EndFunc Func comm_error_handler($oComError) ConsoleWrite(@CRLF) ConsoleWrite(StringFormat("Script Line = %s", $oComError.ScriptLine) & @CRLF) ConsoleWrite(StringFormat("Win Err Desc = %s", StringStripWS($oComError.WinDescription, $STR_STRIPTRAILING)) & @CRLF) ConsoleWrite(StringFormat("Error Number = %i (0x%x)", $oComError.Number, $oComError.Number) & @CRLF) ConsoleWrite(StringFormat("Error Desc = %s", $oComError.Description) & @CRLF) Exit EndFunc 24 minutes ago, TheXman said: Here's a quick & dirty example of using COM to find a process using a partial match. It is written so that if the process name contains the string, it will return true. expandcollapse popup#include <Constants.au3> If fuzzy_process_match('svchost') Then MsgBox($MB_ICONINFORMATION, "INFO", "Process found!") Else MsgBox($MB_ICONWARNING, "WARNING", "Process not found!") EndIf Func fuzzy_process_match($sFuzzyMatch) ; This function will return true if there are process names ; that contain the specified string Local $oWmi, $oInstances ObjEvent("AutoIt.Error", comm_error_handler) ;Get WMI object $oWmi = ObjGet("winmgmts:\\.\root\CIMV2") If Not IsObj($oWmi) Then Exit MsgBox($MB_ICONERROR, "ERROR", "Unable to create WMI object") With $oWmi ;Search for process that contains the specified string $oInstances = .ExecQuery("SELECT name FROM Win32_Process WHERE name LIKE '%" & $sFuzzyMatch & "%'") If $oInstances.Count > 0 Then Return True Else Return False EndIf EndWith EndFunc Func comm_error_handler($oComError) ConsoleWrite(@CRLF) ConsoleWrite(StringFormat("Script Line = %s", $oComError.ScriptLine) & @CRLF) ConsoleWrite(StringFormat("Win Err Desc = %s", StringStripWS($oComError.WinDescription, $STR_STRIPTRAILING)) & @CRLF) ConsoleWrite(StringFormat("Error Number = %i (0x%x)", $oComError.Number, $oComError.Number) & @CRLF) ConsoleWrite(StringFormat("Error Desc = %s", $oComError.Description) & @CRLF) EndFunc Link to comment Share on other sites More sharing options...
TheXman Posted October 1, 2020 Share Posted October 1, 2020 (edited) Quote #include <Constants.au3> $Forever = 0 Sleep (165000) While $Forever < 1 If fuzzy_process_match('Notepad') Then Sleep (25) Else If @OSArch = "x86" Then Run("notepad.exe") Else Run("notepad.exe") EndIf EndIf WEnd Your code above should loop. However, before it starts looping, it sleeps for 2 minutes and 45 secs. Also, inside the loop, you are only sleeping for 25 milliseconds if the process is found. That's a rather "tight" loop. Lastly, you can shortcut your While statement to be just "While 1" for an endless loop. You don't need $Forever. As long as the "While" condition is true, the while will continue to loop. The logic in that loop needs to be examined more closely. If it does not find the process, it will start notepad over and over in a tight loop. VERY BAD! Edited October 1, 2020 by TheXman Starlord30 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
Musashi Posted October 1, 2020 Share Posted October 1, 2020 (edited) 13 hours ago, Starlord30 said: Here is what I tried but it never processes. Not necessarily the perfect solution, but it should work . Global $g_sSearchProcess = "Notepad" ; leading part or full name of the process (without .exe) While True If _ProcessPartialMatch($g_sSearchProcess) Then ConsoleWrite("+ >>>> Process exists -> WAIT 3 sec." & @CRLF) ; *** only during test Sleep(3000) Else ConsoleWrite("! >>>> Process not found -> Start Program" & @CRLF) ; *** only during test If @OSArch = "x86" Then Run("notepad.exe") ExitLoop Else Run("notepad.exe") ExitLoop EndIf EndIf WEnd Func _ProcessPartialMatch($sPartialName) Local $aProcessList, $bProcessFound = False $aProcessList = ProcessList() For $i = 1 To $aProcessList[0][0] If StringRegExp($aProcessList[$i][0], "(?i)^\Q" & $sPartialName & "\E(.*)\.exe$") Then $bProcessFound = True ExitLoop EndIf Next Return $bProcessFound EndFunc ;==>_ProcessPartialMatch @Starlord30 EDIT -> I have extended the regular expression a bit :Old : "(?i)^" & $sPartialName & "(.*)\.exe$" New : "(?i)^\Q" & $sPartialName & "\E(.*)\.exe$" The background is, that the process name may contain characters that need to be escaped, e.g. the dot in Process01.test.exe (Thanks to @mikell , who pointed this out to me in another thread ) Edited October 2, 2020 by Musashi Starlord30 1 "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
Starlord30 Posted October 2, 2020 Author Share Posted October 2, 2020 15 hours ago, TheXman said: Your code above should loop. However, before it starts looping, it sleeps for 2 minutes and 45 secs. Also, inside the loop, you are only sleeping for 25 milliseconds if the process is found. That's a rather "tight" loop. Lastly, you can shortcut your While statement to be just "While 1" for an endless loop. You don't need $Forever. As long as the "While" condition is true, the while will continue to loop. The logic in that loop needs to be examined more closely. If it does not find the process, it will start notepad over and over in a tight loop. VERY BAD! Thanks for all of your help. I really appreciate it. I tightened everything up and it runs great. I had made the sleep 25 milliseconds just for testing purposes so I didn't have to wait to see if it worked. I'm going to play around with it a bit more today, but so far, I couldn't be happier! Link to comment Share on other sites More sharing options...
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