We help IT Professionals succeed at work.

Check if a program is running

DelRunner
DelRunner asked
on
Hi there !
Could anyone tell me how to check if a particular program (.exe) is running, and if so how to kill / close it ?

DelRunner
Comment
Watch Question

Commented:
This is the code which checks if a specific exe filename is running:
You can terminate it's process by finding the process of the filename and using
teminateprocess function

Uses
  Psapi, tlhelp32;

procedure CreateWin9xProcessList(List : TStringList) ;
var
  hSnapShot : THandle;
  ProcInfo : TProcessEntry32;
begin
  if List = nil then Exit ;
  hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnapShot <> THandle(-1)) then
  begin
    ProcInfo.dwSize := sizeof(ProcInfo) ;
    if (Process32First(hSnapshot, ProcInfo)) then
    begin
     List.Add( ProcInfo.szExeFile) ;
     while (Process32Next(hSnapShot, ProcInfo)) do
      List.Add(ProcInfo.szExeFile) ;
    end ;
    CloseHandle(hSnapShot) ;
  end ;
end ;

procedure CreateWinNTProcessList(List : TStringList) ;
var
  PIDArray : array [0..1023] of DWORD ;
  cb : DWORD ;
  I : integer ;
  ProcCount : integer ;
  hMod : HMODULE ;
  hProcess : THandle ;
  ModuleName : array [0..300] of char ;
begin
  if List = nil then Exit ;
  EnumProcesses(@PIDArray, sizeof(PIDArray), cb) ;
  ProcCount := cb div sizeof(DWORD) ;
  for I := 0 to ProcCount-1 do
  begin
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or
    PROCESS_VM_READ,
    false,
    PIDArray[I]) ;
    if (hProcess <> 0) then
    begin
      EnumProcessModules(hProcess, @hMod, sizeof(hMod), cb) ;
      GetModuleFilenameEx(hProcess,hMod,ModuleName,sizeof(ModuleName));
      List.Add(ModuleName);
      CloseHandle(hProcess);
    end;
  end;
end;

procedure GetProcessList(Var List : TStringList) ;
var ovi : TOSVersionInfo ;
begin
  if List = nil then Exit ;
  ovi.dwOSVersionInfoSize := sizeof(TOSVersionInfo) ;
  GetVersionEx(ovi) ;
  case ovi.dwPlatformId of
    VER_PLATFORM_WIN32_WINDOWS : CreateWin9xProcessList(List) ;
    VER_PLATFORM_WIN32_NT : CreateWinNTProcessList(List) ;
  end
end;

function EXE_Running(FileName : String; fullpath : boolean) : boolean;
var
  i : integer ;
  MyProcList : TStringList;
begin
 MyProcList := TStringList.Create;
 try
   GetProcessList(MyProcList) ;
   result := false;
   if MyProcList = nil then Exit;
    for i := 0 to MyProcList.Count - 1 do
    begin
      if not fullpath then
      begin
       if CompareText(ExtractFileName(MyProcList.Strings[i]),FileName) = 0 then result := true
      end else
       if CompareText(MyProcList.Strings[i],FileName) = 0 then result := true;
     if result then break;
    end;
  finally
   MyProcList.Free ;
 end;
end;
Mohammed NasmanSoftware Developer
CERTIFIED EXPERT

Commented:
Hello

  Use FindWindow and WM_CLose to to close the application

procedure TForm1.Button1Click(Sender: TObject);
var
  H : THandle;
begin
  H := FindWindow('notepad',nil);
  PostMessage(H,WM_Close,0,0);
end;

if you want to force the application to close without saving use WM_Quit

also you can find the application by it's titlebar caption
like
  H := FindWindow(nil,'untitled - notepad');

Commented:
But waht if the application have no windows and what if the application stacked

Commented:
Secondly you can use exitprocess instead of terminate process function which is the same that you told but saves the changes.

Commented:
I think this came from another question here at EE so I cant take the credit really. Cut n paste this and save it to ProcessViewer.pas and save it in your program directory.

unit ProcessViewer;

interface

uses
     Windows, Dialogs, SysUtils, Classes, ShellAPI, TLHelp32, Forms;

const
     SleepForReCheck=5000;

type TProcessInfo=record
     FileName: string;
     Caption: string;
     Visible: boolean;
     Handle: DWord;
     PClass: string;
     ThreadID: DWord;
     PID: DWord;
end;


var
     DateiList,CaptionList,VisibleList,HandleList,ClassList,ThreadIdList,PIDList: TStringList;
     ProcessInfo: array of TProcessInfo;

function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): Bool; stdcall;
function KillProcessByPID(PID: DWord): boolean;
function KillProcessByFileName(FileName: string; KillAll: boolean): boolean;
procedure GetProcessList;
function GetFileNameFromHandle(Handle: hwnd):string;
function IsFileActive(FileName: String): boolean;

implementation

procedure GetProcessList;
var
     i,Laenge: integer;
begin
DateiList.Clear;
HandleList.Clear;
ClassList.Clear;
CaptionList.Clear;
VisibleList.Clear;
ThreadIdList.Clear;
PIDList.Clear;
EnumWindows(@EnumWindowsProc, 0);
Laenge:=DateiList.Count;
SetLength(ProcessInfo,Laenge);
for i:=0 to Laenge-1 do
begin
     DateiList[i]:=UpperCase(DateiList[i]);
     with ProcessInfo[i] do
     begin
          FileName:=DateiList[i];
          Caption:=CaptionList[i];
          Visible:=VisibleList[i]='1';
          Handle:=StrToInt64(HandleList[i]);
          PClass:=ClassList[i];
          ThreadID:=StrToInt64(ThreadIdList[i]);
          PID:=StrToInt64(PIDList[i]);
     end;
end;
end;

function IsFileActive(FileName: String): boolean;
var
     i: integer;
begin
result:=false;
if FileName='' then exit;
GetProcessList;
FileName:=UpperCase(ExtractFileName(FileName));
for i:=0 to Length(ProcessInfo)-1 do
begin
     if Pos(FileName,ProcessInfo[i].FileName)>0 then
     begin
          result:=true;
          break;
     end;
end;
end;

function GetFileNameFromHandle(Handle: hwnd):string;
var
     PID: DWord;
     aSnapShotHandle: THandle;
     ContinueLoop: Boolean;
     aProcessEntry32: TProcessEntry32;
begin
GetWindowThreadProcessID(Handle, @PID);
aSnapShotHandle := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
aProcessEntry32.dwSize := SizeOf(aProcessEntry32);
ContinueLoop := Process32First(aSnapShotHandle, aProcessEntry32);
while Integer(ContinueLoop) <> 0 do
begin
     if aProcessEntry32.th32ProcessID = PID then
     begin
          result:=aProcessEntry32.szExeFile;
          break;
     end;
     ContinueLoop := Process32Next(aSnapShotHandle, aProcessEntry32);
end;
CloseHandle(aSnapShotHandle);
end;

function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): Bool;
var
     Capt,Cla: array[0..255] of char;
     Datei: string;
     ident: dword;
begin
GetWindowText(hWnd, Capt, 255);
GetClassName(hwnd,Cla,255);
ThreadIdList.Add(IntToStr(GetWindowThreadProcessId(hwnd,nil)));
Datei:=GetFileNameFromhandle(hwnd);
DateiList.Add(Datei);
HandleList.Add(IntToStr(HWnd));
if IsWindowVisible(HWnd) then VisibleList.Add('1') else VisibleList.Add('0');
ClassList.Add(Cla);
CaptionList.Add(Capt);
GetWindowThreadProcessId(StrToInt(HandleList[HandleList.Count-1]),@ident);
PIDList.Add(IntToStr(ident));
Result:=true;
end;

function KillProcessByPID(PID : DWord): boolean;
var
     myhandle : THandle;
     i: integer;
begin
myhandle := OpenProcess(PROCESS_TERMINATE, False, PID);
TerminateProcess(myhandle, 0);
for i:=0 to SleepForReCheck do Application.ProcessMessages; //Genug Zeit geben
GetProcessList;
Result:=PIDList.IndexOf(IntToStr(PID))=-1;
end;

function KillProcessByFileName(FileName: string; KillAll: boolean): boolean;
var
     i: integer;
     FileFound: boolean;
begin
result:=false;
if FileName='' then exit;
FileName:=UpperCase(ExtractFileName(FileName));
result:=true;
GetProcessList;
if KillAll then
begin
     //Kill all
     FileFound:=false;
     repeat
          GetProcessList;
          FileFound:=false;
          for i:=0 to DateiList.Count-1 do
          begin
               if Pos(Filename,DateiList[i])>0 then
               begin
                    FileFound:=true;
                    break;
               end;
          end;
          if i<DateiList.Count then
          begin
               if not KillProcessByPID(StrToInt64(PIDList[i])) then
               begin
                    result:=false;
                    exit;
               end;
          end;
     until not FileFound;
end else
begin
     //Kill one
     for i:=0 to DateiList.Count-1 do
     begin
          if Pos(Filename,DateiList[i])>0 then break;
     end;
     if i<DateiList.Count then
     begin
          if not KillProcessByPID(StrToInt64(PIDList[i])) then
          begin
               result:=false;
               exit;
          end;
     end;
end;
end;

initialization
DateiList:=TStringList.Create;
HandleList:=TStringList.Create;
ClassList:=TStringList.Create;
CaptionList:=TStringList.Create;
VisibleList:=TStringList.Create;
ThreadIdList:=TStringList.Create;
PIDList:=TStringList.Create;

finalization
DateiList.Free;
HandleList.Free;
ClassList.Free;
CaptionList.Free;
VisibleList.Free;
ThreadIdList.Free;
PIDList.Free;

end.



Then to use it just add ProcessViewer to your uses and an example is like this:


procedure Torm1.Button1Click(Sender: TObject);
Begin
  If isFileActive('Notepad.exe') then
    Begin
      ShowMessage('Notepad is found, im about to kill it!);
      killProcessByFilename('Notepad.exe',True);
    end;
end;

Regards
Smurff
Mohammed NasmanSoftware Developer
CERTIFIED EXPERT

Commented:
Hello

  here's a better code, this will kill the application by giving it's exe name, like notepad.exe, winword.exe and so on

//=========
uses
Tlhelp32;

function KillTask(ExeFileName: string): integer;
const
  PROCESS_TERMINATE=$0001;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  result := 0;
  FSnapshotHandle := CreateToolhelp32Snapshot
  (TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := Sizeof(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle,
  FProcessEntry32);
  while integer(ContinueLoop) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
    UpperCase(ExeFileName))
    or (UpperCase(FProcessEntry32.szExeFile) =
    UpperCase(ExeFileName))) then
      Result := Integer(TerminateProcess(OpenProcess(PROCESS_TERMINATE, BOOL(0),
    FProcessEntry32.th32ProcessID), 0));
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  KillTask('winword.exe');
end;


Best regards
Mohammed Nasman

Commented:
...get a list of all running Exe-Files/ Check if a Exe-File is running

Uses
  Psapi, tlhelp32;

procedure CreateWin9xProcessList(List : TStringList) ;
var
  hSnapShot : THandle;
  ProcInfo : TProcessEntry32;
begin
  if List = nil then Exit ;
  hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnapShot <> THandle(-1)) then
  begin
    ProcInfo.dwSize := sizeof(ProcInfo) ;
    if (Process32First(hSnapshot, ProcInfo)) then
    begin
     List.Add( ProcInfo.szExeFile) ;
     while (Process32Next(hSnapShot, ProcInfo)) do
      List.Add(ProcInfo.szExeFile) ;
    end ;
    CloseHandle(hSnapShot) ;
  end ;
end ;

procedure CreateWinNTProcessList(List : TStringList) ;
var
  PIDArray : array [0..1023] of DWORD ;
  cb : DWORD ;
  I : integer ;
  ProcCount : integer ;
  hMod : HMODULE ;
  hProcess : THandle ;
  ModuleName : array [0..300] of char ;
begin
  if List = nil then Exit ;
  EnumProcesses(@PIDArray, sizeof(PIDArray), cb) ;
  ProcCount := cb div sizeof(DWORD) ;
  for I := 0 to ProcCount-1 do
  begin
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or
    PROCESS_VM_READ,
    false,
    PIDArray[I]) ;
    if (hProcess <> 0) then
    begin
      EnumProcessModules(hProcess, @hMod, sizeof(hMod), cb) ;
      GetModuleFilenameEx(hProcess,hMod,ModuleName,sizeof(ModuleName));
      List.Add(ModuleName);
      CloseHandle(hProcess);
    end;
  end;
end;

procedure GetProcessList(Var List : TStringList) ;
var ovi : TOSVersionInfo ;
begin
  if List = nil then Exit ;
  ovi.dwOSVersionInfoSize := sizeof(TOSVersionInfo) ;
  GetVersionEx(ovi) ;
  case ovi.dwPlatformId of
    VER_PLATFORM_WIN32_WINDOWS : CreateWin9xProcessList(List) ;
    VER_PLATFORM_WIN32_NT : CreateWinNTProcessList(List) ;
  end
end;

function EXE_Running(FileName : String; fullpath : boolean) : boolean;
var
  i : integer ;
  MyProcList : TStringList;
begin
 MyProcList := TStringList.Create;
 try
   GetProcessList(MyProcList) ;
   result := false;
   if MyProcList = nil then Exit;
    for i := 0 to MyProcList.Count - 1 do
    begin
      if not fullpath then
      begin
       if CompareText(ExtractFileName(MyProcList.Strings[i]),FileName) = 0 then result := true
      end else
       if CompareText(MyProcList.Strings[i],FileName) = 0 then result := true;
     if result then break;
    end;
  finally
   MyProcList.Free ;
 end;
end;


// Example 1: Is a Exe-File running ?
procedure TForm1.Button1Click(Sender: TObject);
begin
 if EXE_Running('notepad.exe',false) then
    ShowMessage('EXE is running')
 else
    ShowMessage('EXE is not running');
end;


// Example 2: List running Exe-Files
procedure TForm1.Button3Click(Sender: TObject);
var
  i : integer ;
  MyProcList : TStringList;
begin
 MyProcList := TStringList.Create;
 try
   GetProcessList(MyProcList) ;
   if MyProcList = nil then Exit;
    for i := 0 to MyProcList.Count - 1 do
      ListBox1.items.add(MyProcList.Strings[i]);
 finally
   MyProcList.Free;
 end;
end;

Commented:
Sorry f15iaf .I have add just the samples .
I have see you comment to late .

Regards,
Nick
Commented:
f15iaf's code is the best one, the other stuff is either only working for win9x/2k (not NT4), or not relied to the question. The question is asking about a specific exe file, so EnumWindows/FindWindow is out of question, it has nothing to do with the actual exe file name.

However, f15iaf's code needs psApi.dll to be on your NT4 machine, it is not installed on every NT installation by default. So you have to distribute it with your application. If you don't like that, you can alternatively have a look at

http://www.madshi.net/enumStuff.zip

which is free, runs under all systems and doesn't need psApi.dll.

Regards, Madshi.

Commented:
Madshi's unit rocks!
How come you're so bad-ass at Delphi, Madshi?

Commented:
Madshi,

Once again Ive learnt alot from your code... Nice unit!
Regards
Danny

Commented:
:-)  Thanx, guys...

>> How come you're so bad-ass at Delphi, Madshi?

I'm not, I'm just pretending...   =;-D

Explore More ContentExplore courses, solutions, and other research materials related to this topic.