Jump to content

If ProcessExists - Wildcard question


Recommended Posts

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

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 by TheXman
Link to comment
Share on other sites

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

 

Musashi-C64.png

"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

 

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.

 

#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 by TheXman
Aesthetic changes to the example script
Link to comment
Share on other sites

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.

 


 

#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.

 

#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

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 by TheXman
Link to comment
Share on other sites

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 by Musashi

Musashi-C64.png

"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

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

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...