******************************************************************************* ***** KillApp **************************************************************** * Reliable procedure of shutdown of application. Tries to shutdown application by normal way * sending WM_Quit event to its thread. If this will not help within 5 seconds (or specified), * application will be terminated by API TerminateProcess function * Parameters: * pnHWND - main Window handle * plKillImmediate - if .T., application will be killed without any waiting or messages sending. Next two parameters will be ignored in this case * plWaitShutdown - if .T., procedure will wait max.10 seconds until application shutdown. * plKillWhenNoShutdown - if .T., App will be killed anyway when shutdown time passed and App still in memory * pnShutdownTimeOut - optional, number of miliseconds to wait until application shutdown by normal way. Between 100 and 60000. * pnProcessID - optional, ID of process to be killed. Will be used if main window already does not exists (some App crashes causes such situation) * pcProcessCreationTime - optional, process creation time to verify if passed process ID is not an ID of another new process PROCEDURE KillApp LPARAMETER pnHWND, plKillImmediate, plWaitShutdown, plKillWhenNoShutdown, pnShutdownTimeOut, pnProcessID, pcProcessCreationTime IF !VARTYPE(m.pnShutdownTimeOut) == "N" m.pnShutdownTimeOut = 5000 ELSE IF m.pnShutdownTimeOut < 100 m.pnShutdownTimeOut = 100 ENDIF IF m.pnShutdownTimeOut > 60000 m.pnShutdownTimeOut = 60000 ENDIF ENDIF DECLARE INTEGER PostThreadMessage IN Win32API INTEGER Hthrd, INTEGER nMessage, short Param1, LONG Param2 DECLARE INTEGER GetWindowThreadProcessId IN Win32API INTEGER HWND, INTEGER @pID DECLARE INTEGER TerminateProcess IN Win32API INTEGER PID, INTEGER TermCode DECLARE INTEGER OpenProcess IN Win32API INTEGER fdwAccess, INTEGER fInherit, INTEGER IDProcess DECLARE INTEGER Sleep IN Win32API INTEGER cMilliseconds DECLARE INTEGER GetProcessTimes IN Win32API INTEGER HProc, STRING @lpCreation, STRING @lpExit, STRING @lpKernel, STRING @lpUser LOCAL nTries, nThreadID, nProcessID m.nProcessID = 0 m.nThreadID = GetWindowThreadProcessId(m.pnHWND,@m.nProcessID) IF m.nThreadID = 0 OR m.nProcessID = 0 IF VARTYPE(m.pnProcessID) == "N" * check if process exists in memory and creation time is same LOCAL lcTime, rrr m.lcTime = SPACE(8) m.rrr = SPACE(8) IF GetProcessTimes(OpenProcess(PROCESS_QUERY_INFORMATION, 0, m.pnProcessID),@m.lcTime,@m.rrr,@m.rrr,@m.rrr)>0 IF m.lcTime == m.pcProcessCreationTime m.nProcessID = m.pnProcessID m.plKillImmediate = .T. ELSE RETURN ENDIF ELSE RETURN ENDIF ELSE * just exit if App already released RETURN ENDIF ENDIF IF !m.plKillImmediate * try to close main App window by sending WM_Quit event just into its thread m.nTries = m.pnShutdownTimeOut/10 DO WHILE m.nTries > 0 IF PostThreadMessage(m.nThreadID, WM_QUIT, 0, 0) > 0 m.nThreadID = GetWindowThreadProcessId(m.pnHWND,@m.nProcessID) IF m.nThreadID = 0 OR m.nProcessID = 0 * just exit if App released RETURN ENDIF ELSE * check if App is in memory m.nThreadID = GetWindowThreadProcessId(m.pnHWND,@m.nProcessID) IF m.nThreadID = 0 OR m.nProcessID = 0 RETURN ENDIF * otherwise, kill it, because it does not respond to messages m.nTries = 0 m.plKillWhenNoShutdown = .T. ENDIF Sleep(10) m.nTries = m.nTries - 1 ENDDO IF !m.plKillWhenNoShutdown RETURN ENDIF ENDIF * if we're here, then we just need kill it TerminateProcess(OpenProcess(PROCESS_TERMINATE,0,m.nProcessID),-1) RETURN>