Try this, work for me. DC_IsAppRunning() did not work for me
Code: Select all
#include "dll.ch"
#include "WinAPI.Ch"
#include "ot4xb.ch"
#DEFINE SW_RESTORE 9
FUNCTION IsAppRunning(cExe,cTitle,lRestore,lExactTitle)
/*
Developed on Windows 98 2nd Edition using XBase++ 1.7
Tested on Windows 98, 2000, and NT 4.0
Richard Pulliam
Richard@ClipperSolutions.com
*/
LOCAL nSearchColumn,aRunningTasks,i,nWinHandleLast,nWinHandleForeground,;
nFindId,nWinHandleFind,nForeGroundId,cColumnContents,nPos,nLenRunTasks
lRestore:=IF(lRestore==NIL,.T.,lRestore) // default to restore running app
nSearchColumn:=IF(cExe#NIL,2,3) // what column to do search on, title or exe?
cExe:=IF(cExe==NIL,"",ALLTRIM(UPPER(cExe)))
cTitle:=IF(cTitle==NIL,"",ALLTRIM(UPPER(cTitle)))
lExactTitle:=IF(lExactTitle==NIL,.T.,lExactTitle)
aRunningTasks := GetRunningTasks() // returns a multidimensional array
// of row form {nHandle,ExeName,Title}
IF WinNT() .AND. !EMPTY(cExe)
// this is because API function GetModuleBaseNameA does not return
// a full path and equivalent commands like GetModuleFileName
// did not work properly
cExe:=IF((nPos:=RAT("\",cExe))>0,SUBSTR(cExe,nPos+1),cExe)
ENDIF
nLenRunTasks:=LEN(aRunningTasks) // figure it out only one time!
FOR i:=1 TO nLenRunTasks
cColumnContents:=ALLTRIM(UPPER(aRunningTasks[i,nSearchColumn]))
IF (lExactTitle .AND. !EMPTY(cTitle) .AND. cTitle==cColumnContents) .OR. ;
(!lExactTitle .AND. !EMPTY(cTitle) .AND. AT(cTitle,cColumnContents)>0) .OR. ;
(!EMPTY(cExe) .AND. cExe==cColumnContents) // Is running!
IF !lRestore
RETURN(.T.)
ELSE
nWinHandleFind:=aRunningTasks[i,1]
nWinHandleForeground := @USER32:GetForegroundWindow()
nForeGroundId := @USER32:GetWindowThreadProcessId(nWinHandleForeground,0)
nFindId := @USER32:GetWindowThreadProcessId(nWinHandleFind,0)
IF !(nForeGroundId==nFindId) .or. !(@USER32:IsIconic(nWinHandleFind)==0)
nWinHandleLast:=@USER32:GetLastActivePopup(nWinHandleFind)
IF !(@USER32:IsIconic(nWinHandleLast)==0)
@USER32:ShowWindow(nWinHandleLast,SW_RESTORE)
ENDIF
@USER32:BringWindowToTop(nWinHandleLast)
@USER32:SetForegroundWindow(nWinHandleLast)
ENDIF
RETURN(.T.)
ENDIF
ENDIF
NEXT
RETURN(.F.)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
STATIC FUNCTION GetRunningTasks()
LOCAL aSize:={0,0},aPos:={0,0},oDlg,aList
// This is so this program will have a window to get the handle on
oDlg:=XbpDialog():new(AppDesktop(),,aPos,aSize,,.F.)
oDlg:clipSiblings:=.T.
oDlg:drawingArea:ClipChildren:=.T.
oDlg:create()
aList:=GetTaskList(oDlg:gethWnd( )) // Get a list of all running programs
oDlg:destroy()
RETURN(aList)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
#DEFINE GW_HWNDNEXT 2
STATIC FUNCTION GetTaskList( nWinHandle )
LOCAL aList:={},cWindowName,nVisible,nSize:=256,nBytes,cFileName,aProcesses,;
nPos,nId
IF WinNT()
aProcesses:=GetNTProcesses()
ENDIF
WHILE(nWinHandle#0)
cWindowName:=SPACE(nSize)
nBytes:=@USER32:GetWindowTextA(nWinHandle,@cWindowName,nSize)
IF nBytes#0
cWindowName:=LEFT(cWindowName,nBytes)
nVisible := @USER32:IsWindowVisible(nWinHandle)
IF nVisible==1
IF !WinNT() // Win 95 or 98
cFileName:=SPACE(nSize)
nBytes:=@USER32:GetWindowModuleFileNameA(nWinHandle,@cFileName,nSize)
AADD(aList,{nWinHandle,LEFT(cFileName,nBytes-1),cWindowName})
ELSE // executing in NT family. This is necessary because
// API command @USER32:GetWindowModuleFileName does not work on NT
nId:=0
@USER32:GetWindowThreadProcessId(nWinHandle,@nId)
IF (nPos:=ASCAN(aProcesses,nId))>0
AADD(aList,{nWinHandle,aProcesses[nPos,2],cWindowName})
ENDIF
ENDIF
ENDIF
ENDIF
nWinHandle:=@USER32:GetWindow(nWinHandle,GW_HWNDNEXT)
ENDDO
RETURN(aList)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
#DEFINE PROCESS_ALL_ACCESS 2035711 // hex 1F0FFF
DLLFUNCTION OpenProcess(nDesiredAccess,lInheritHandle,nProcessId) ;
USING STDCALL FROM KERNEL32.DLL
DLLFUNCTION GetModuleBaseNameW(hProcess,hModule,@lpFileName,@nSize) ;
USING STDCALL FROM PSAPI.DLL
DLLFUNCTION CloseHandle(nProcessHandle) USING STDCALL FROM KERNEL32.DLL
STATIC FUNCTION GetNTProcesses()
LOCAL aProcessIds,i,nProcessHandle,aRetVal:={},naHandleForProcess,;
cFileName,nSize:=0,nBytes,j,nLenIds,nLenHandles
aProcessIds:=EnumerateProcesses()
nLenIds:=LEN(aProcessIds)
FOR i:=1 TO nLenIds
// get a handle to the process
nProcessHandle:=OpenProcess(PROCESS_ALL_ACCESS,0,aProcessIds[i])
IF nProcessHandle>0
// get an array of the module handles for the specified process
naHandleForProcess:=EnumerateProcessModules(nProcessHandle)
IF (nLenHandles:=LEN(naHandleForProcess))>0
FOR j:=1 TO nLenHandles
cFileName:=SPACE(256)
// GetModuleBaseName and GetModuleBaseNameA do not work here
// GetModuleFileName .and GetModuleFileNameA do not work here
nBytes:=GetModuleBaseNameW(nProcessHandle,naHandleForProcess[j],;
@cFileName,@nSize)
IF nBytes>0
AADD(aRetVal,{aProcessIds[i],CleanFileName(cFileName)})
ENDIF
NEXT
ENDIF
CloseHandle(nProcessHandle)
ENDIF
NEXT
RETURN(aRetVal)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
STATIC FUNCTION CleanFileName(cFileName)
cFileName:=ALLTRIM(STRTRAN(cFileName,CHR(0),""))
RETURN(cFileName)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
DLLFUNCTION EnumProcesses(@cProcesses,nSize,@nBytesNeeded) ;
USING STDCALL FROM PSAPI.DLL
STATIC FUNCTION EnumerateProcesses()
LOCAL cProcesses,nSize:=1024,nBytesNeeded:=0,nRetVal:=0,nElements,i,;
naProcessIds:={}
cProcesses:=SPACE(nSize)
nRetVal:=EnumProcesses(@cProcesses,nSize,@nBytesNeeded)
IF nRetVal#0
nElements:=nBytesNeeded/4 // 4 is size of double word
FOR i:=1 TO nElements
AADD(naProcessIds,BIN2U(SUBSTR(cProcesses,4*(i-1)+1,4)))
NEXT
ENDIF
return(naProcessIds)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
DLLFUNCTION EnumProcessModules(hProcess,@hMod,nSizeOf,@nBytesNeeded) ;
USING STDCALL FROM PSAPI.DLL
STATIC FUNCTION EnumerateProcessModules(nProcessHandle)
LOCAL nSize:=4096,nBytesNeeded:=0,nRetVal:=0,cModuleHandles,;
naHandleForProcess:={},nElements,i
cModuleHandles:=SPACE(nSize)
nRetVal:=EnumProcessModules(nProcessHandle,@cModuleHandles,nSize,@nBytesNeeded)
IF nRetVal#0
nElements:=nBytesNeeded/4 // 4 is size of double word
FOR i:=1 TO nElements
AADD(naHandleForProcess,BIN2U(SUBSTR(cModuleHandles,4*(i-1)+1,4)))
NEXT
ENDIF
RETURN(naHandleForProcess)
/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
#INCLUDE "OS.CH" // part of xbase++ includes
STATIC FUNCTION WinNT()
RETURN(OS(OS_FAMILY)=="WINNT")