> Hello,
>
>
> in my program (let's call: MAIN.EXE) i start a second programm (let's call: second.exe) with the run command. The problem now is, that my user can start my programm (=MAIN) several times. The second program can take about 2 minutes to finish - if the user starts my program MAIN during this 2 minutes again, the second program (SECOND) will also start for a second time, third time and s.o. ....
>
> If i'm looking in the windows task manager, i can see the processes - how can i check, if the process SECOND.EXE is still running ?
>
> Many thanks
>
>
> Markus
*!* _IsProgramRunning.prg
*!* returns 0 if the specified exe is not running
*!* returns > 0 if the specified exe is running (the process ID)
*!* returns -1 if there was an error
*!* See also _SetForegroundProcess
#Define PROCESS_QUERY_INFORMATION 0x400
#Define PROCESS_VM_READ 0x10
#Define MAX_PATH 260
Lparameters pcFileName As String
Local ;
lnLen, ;
lnBytesReturned, ;
lcProcessIds, ;
lnResult, ;
lcProcessArray, ;
lnReturnValue, ;
lnCurrentProcessId, ;
lnProcessID, ;
lnProcessHandle, ;
lcFileName, ;
lnIndex
If Vartype(m.pcFileName) # "C" Then
m.pcFileName = Application.ServerName
Endif
If Empty(Justext(m.pcFileName)) Then
m.pcFileName = Forceext(m.pcFileName, "exe")
Endif
*!* First get an array of running processes IDs:
*!* "It is a good idea to use a large array, because it is hard to
*!* predict how many processes there will be at the time you call EnumProcesses."
*!* To determine how many processes were enumerated, divide the pBytesReturned value
*!* by sizeof(DWORD). There is no indication given when the buffer is too small to
*!* store all process identifiers. Therefore, if pBytesReturned equals cb, consider
*!* retrying the call with a larger array.
*!* processes array buffer, 256 bytes will fit 64 processes
m.lnLen = 256
*!* This will tell us how many bytes the api call returned:
m.lnBytesReturned = m.lnLen
Do While m.lnLen = m.lnBytesReturned
m.lcProcessIds = Replicate(Chr(0), m.lnLen)
m.lnResult = _apiEnumProcesses(@m.lcProcessIds, m.lnLen, @m.lnBytesReturned)
If m.lnResult = 0 Then
Exit
Endif
m.lnLen = m.lnLen * 2
Enddo
If m.lnResult = 0 Then
*!* We failed to enumerate the processes
Return -1
Endif
*!* Trim buffer:
m.lcProcessArray = Left(m.lcProcessIds, m.lnBytesReturned)
m.lnReturnValue = 0
m.lnCurrentProcessId = _apiGetCurrentProcessId()
*!* Now scan the running procesess IDs array:
For m.lnIndex = 1 To m.lnBytesReturned Step 4
m.lnProcessID = CToBin(Substr(m.lcProcessArray, m.lnIndex, 4), "4rs")
*!* If this is the process id of this actual program, just skip it:
If m.lnProcessID = m.lnCurrentProcessId Then
Loop
Endif
*!* Try to get a handle to the process:
m.lnProcessHandle = _apiOpenProcess(PROCESS_QUERY_INFORMATION + PROCESS_VM_READ, 0, m.lnProcessID)
*!* If we could not open this process, just try the next process:
If m.lnProcessHandle = 0 Then
Loop
Endif
*!* Now get the process file name:
m.lnLen = MAX_PATH
m.lcFileName = Replicate(Chr(0), m.lnLen)
m.lnResult = _apiGetModuleFileNameEx(m.lnProcessHandle, 0, @m.lcFileName, m.lnLen)
*!* Now free the process handle:
_apiCloseHandle(m.lnProcessHandle)
*!* If we could net get the process name, just try the next process:
If m.lnResult = 0 Then
Loop
Endif
m.lcFileName = Left(m.lcFileName, m.lnResult)
If Upper(Justfname(m.pcFileName)) == Upper(Justfname(m.lcFileName)) Then
m.lnReturnValue = m.lnProcessID
*!* If we found our module, just exit now:
Exit
Endif
Endfor
Return m.lnReturnValue
*!* _apiEnumProcesses.prg
Lparameters lpidProcess, cb, cbNeeded
Declare Integer EnumProcesses In psapi.Dll As _apiEnumProcesses ;
String @lpidProcess,;
Integer cb,;
Integer @cbNeeded
Return _apiEnumProcesses(@m.lpidProcess, m.cb, @m.cbNeeded)
*!* _apiGetCurrentProcessId.prg
Declare Integer GetCurrentProcessId In win32api As _apiGetCurrentProcessId
Return _apiGetCurrentProcessId()
*!* _apiOpenProcess.prg
Lparameters dwDesiredAccess, bInheritHandle, dwProcessId
Declare Integer OpenProcess In win32api As _apiOpenProcess ;
Integer dwDesiredAccess,;
Integer bInheritHandle,;
Integer dwProcessId
Return _apiOpenProcess(m.dwDesiredAccess, m.bInheritHandle, m.dwProcessId)
*!* _apiGetModuleFileNameEx.prg
Lparameters hProcess, hModule, lpFileName, nSize
Declare Integer GetModuleFileNameEx In psapi.Dll As _apiGetModuleFileNameEx ;
Integer hProcess,;
Integer hModule,;
String @lpFilename,;
Integer nSize
Return _apiGetModuleFileNameEx(m.hProcess, m.hModule, @m.lpFileName, m.nSize)
*!* _apiCloseHandle.prg
Lparameters hObject
Declare Integer CloseHandle In win32api As _apiCloseHandle ;
Integer hObject
Return _apiCloseHandle(m.hObject)
To make the above code work, save each code snippet in its own prg using the name specified in the comments. (Mike Yearwood style)
---
Carlos Alloatti