Solved

Working with listing running  Processes

Posted on 2001-08-14
17
199 Views
Last Modified: 2010-04-06
make it clean, make it neat and more points will be awarded.

to make it fairely strait forward (the CTRL+ALT+DEL) in windows brings up the all to familiar list of running programs I want to for the most part recreate this.

the first thing I need to do is to be able to list the programs that are running. Once I have the process name I can close the app. can some one give me a nice clean way to get a list of all running applications.

by the way this is for a Win NT machine so unregistered proccesses shouldn't be a problem like 9x if you know of a possible conflict comments are more than welcome.

Thank you // Bloodline
0
Comment
Question by:Blood_Line
  • 6
  • 6
  • 5
17 Comments
 
LVL 20

Expert Comment

by:Madshi
ID: 6385829
Hi Bloodline,

if you have D4-6 and want to have it easy, you can use my package "madKernel" (free for non-commercial usage). With it you can do things like this:

// show all running processes:
with Processes do
  for i := 0 to ItemCount - 1 do
    ShowMessage(Items[i1].ExeFile);

// soft close first found notepad instance, as if user clicks [X]
Process('notepad.exe').Close;

// close all notepad instances without saving (Quit doesn't work with all programs correctly)
Processes('notepad.exe').Quit;

// hard stop explorer like NT task manager does, not very clean, but works (almost) always
Process('explorer.exe').Terminate;

// terminate everything including ourselves...   :-)
Processes.Terminate;

Of course everything works with both win9x and NT family.

I've also something to offer, which is free for commercial usage, too, and also contains the sources, but it's not that comfortable and mighty as "madKernel" is:

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

With it you can also enumerate all processes in all systems, but you have to care about closing yourself. You can use PostMessage(processMainWindow, WM_CLOSE, 0, 0), PostThreadMessage(processMainThreadID, WM_QUIT, 0, 0) or TerminateProcess(processHandle, 0) to achieve similar results to the examples above.

Regards, Madshi.

www.madshi.net
0
 

Author Comment

by:Blood_Line
ID: 6386696
let me have a day or so to look everything over and see if I can pick out what I need I prefer strait code makes it easier to apply to other programs later down the road and makes it easier to modify to meet my needs specificaly. but I am checking int the unumstuff for now. until then
thank you for your help and other comments are still welcome.

//BloodLine
0
 

Author Comment

by:Blood_Line
ID: 6386840
after looking over enum I am almost possitive that I should be able to pull what I need I only require a little help in converting a few results into information that I am familiar with so that I may view the processes in a list. are you willing to do this?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6387100
If it is really only "a little help", then no problem...   :-)   Have not too much time, though...

Regards, Madshi.
0
 
LVL 3

Accepted Solution

by:
smurff earned 300 total points
ID: 6387367
Ive got this if it helps, Madshis components are very good though!
Regards
Smurff

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;

And if you wanted to kill and app you could do something like:
procedure KillApp(title : string);
var h : HWND;

begin
h:=FindWindow(nil,@(title)[1]);
if h<>0 then
        begin
        SendMessage(h,WM_CLOSE,0,0);
        Showmessage('App terminated.')
        end
        else
        Showmessage('failed kill app.')
end;

//to close notepad,
KillApp('Notepad');
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6387385
Hi Smurff!

>> Ive got this if it helps

Unfortunately it doesn't help much, because NT4 doesn't support the toolhelp functions...   :-(

>> Madshis components are very good though!

Thanx...   :-)

Regards, Madshi.
0
 
LVL 3

Expert Comment

by:smurff
ID: 6387460
Madshi,

>Unfortunately it doesn't help much, because NT4 doesn't support the toolhelp functions...   :-(

Thats why theres the two procedures, I have tested it on NT and it works for me.

Regards
Smurff
0
 
LVL 3

Expert Comment

by:smurff
ID: 6387501
Madshi,
On reflection, you solution is much easier e.g.

>if you have D4-6 and want to have it easy, you can use my >package "madKernel" (free for non-commercial
>usage). With it you can do things like this:

>// show all running processes:
>with Processes do
> for i := 0 to ItemCount - 1 do
>   ShowMessage(Items[i1].ExeFile);

So dont think Im competing for points or anything, I just thought that BloodLine might learn something from seeing some code to play with.....Ive found the best way to learn is playing around. My 2 pence worth :)

Regards
Smurff
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 20

Expert Comment

by:Madshi
ID: 6387530
Ooops, I missed the NT part of your code, I'm sorry...

However: Your code needs psApi.dll to run under NT4 and psApi.dll is not included in every NT installation. So you have to distribute this dll with your application (that is allowed) if you're using that code. My code (both enumStuff and madKernel) works without needing that psApi.dll.

Regards, Madshi.
0
 

Author Comment

by:Blood_Line
ID: 6389612
thank you both I am attempting to empliment the code the best I can and smurff I appreaciate the code to me it seems a little more user friendly to apply in the future. and it also seems tailored more towards what I actualy need there for I am most likely going to award you the points but I need to examine witch works with my problem most I believe that I would like to give you both points for your help I have points to blow god bless the accumulating points thing and I usualy only use exchange for maybe one major project a year. so this is what I will do one of you may have the points listed and I will set another question out for the other I will allow you to decide who shall get wich  either way you will both make out with 300 points.

I will also soon be posting another question specificaly on killing applications and will be giving more points for that also so if you want easy points keep the eye out for it. does this sound like an agreable arangement?


I am how ever having a problem with getting applications to die do you to think this may be the way I am doing it and the code works well or should I look for a better method of closing applications?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6391522
>> does this sound like an agreable arangement?

Absolutely...  :-)

Please note, that with Smurff's code you need to distribute psApi.dll with your application. Just wanted to make that clear, in case you missed it...

>> I am how ever having a problem with getting applications to die

There are several ways of killing apps. I've explained that in my first comment (see the last paragraph). In fact the killing code in Smurff's code is not a good one. SendMessage(WM_CLOSE) fails *very* often. Just exchange "SendMessage" with "PostMessage", then it will run a lot better. Besides from the WM_CLOSE killing there are at least 2 other ways, see my first comment.

Regards, Madshi.
0
 
LVL 3

Expert Comment

by:smurff
ID: 6392068
Madshi,

>Please note, that with Smurff's code you need to >distribute psApi.dll with your application. Just wanted
>to make that clear, in case you missed it...

I havent specifically installed the .dll and I have it. Ive installed Service pack 6, IE 5.5, Office2k, Delphi5Ent, PSP7... I know its not a default installation dll so I can assume that its a popular dll.
It's documentation resides under "Windows Base Services",
"Windows NT Features", "Process Status Helper" and every PC in my company seems to have it....The dll itself is only 18k so if you did need to distribute it then its not that much of an issue (i think anyway). I am still saying your components are very good though.

Bloodline,
Wow. thanks I wasnt expecting points. How are you trying to kill it? was it the procedure I put? if so then I think theres probably a better way. I didnt know about the PostMessage like what Madshi said so sorry about that.
I also noticed that the proc. I showed you closes apps by the caption name in the titlebar, but the list produces the .exe name. The EnumProcesses does produce an array or process Id`s. Its probably better killing them by that. I`ll have a look for you(or does Madshi already know?)

Thanks anyway, Kind regards
Smurff

0
 
LVL 20

Expert Comment

by:Madshi
ID: 6392197
>> I havent specifically installed the .dll and I have it.

If I remember right it's included in SP6 or something like that. But if you don't want your application to require SP6, you would nevertheless have to distribute psApi.dll with your app. No big thing, of course. Just worth a mention...

>> I also noticed that the proc. I showed you closes apps by the caption name in the titlebar, but the list produces the .exe name. The EnumProcesses does produce an array or process Id`s. Its probably better killing them by that. I`ll have a look for you(or does Madshi already know?)

As I've stated in my first comment, there are (at least) 3 ways of closing an application. When only having the processID of the to-be-stopped process you can without much problems use OpenProcess + TerminateProcess. Getting the main window of a processID (for the WM_CLOSE solution) is a bit more work, you need to call EnumWindows and then GetWindowThreadProcessID for each enumerated window. The biggest problem is the PostThreadMessage solution, since psApi.dll can't enumerate threads. But I suggest moving the closing question to Bloodline's new question, which is already online...

Regards, Madshi.
0
 

Author Comment

by:Blood_Line
ID: 6393795
this was a rather good answer to my question it was answered in close accordance to my needs and specifications in the question.

//BloodLine
0
 
LVL 3

Expert Comment

by:smurff
ID: 6394021
Madshi,
Thanks for the comments. I havent had time today to look at the closing of the apps. Its something worth playing with for Bloodline (and myself) cos in my eyes thats the only way to learn. I didnt know about Bloodlines other question. Again, Ive learned from you and Ive took your comments on board. thanks

Bloodline,
Many thanks for the points, Im not really in it for the points, I just come here to learn new things and help out, but its always nice to know when your help and time is appreciated. Good luck with your codeing.
Regards
Smurff
0
 
LVL 3

Expert Comment

by:smurff
ID: 6396587
BloodLine,

Looking into this further Ive also found this. I dont know where it came from, it was just in my "Delphi Crap to sort" directory :) It might help you learn more about the whole "process" thing. anyway thought it might help.
Regards
Smurff

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls,TlHelp32;
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
  EnumWindowsProc = function (Hwnd: THandle;Param: Pointer): Boolean; stdcall;

function GetWindowExeName(Handle: THandle): String;
var
  PE: TProcessEntry32;
  Snap: THandle;
  ProcessId: cardinal;
begin
  GetWindowThreadProcessId(Handle,@ProcessId);
  Snap:= CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Snap <> 0 then begin
    if Process32First(Snap, PE) then
      if PE.th32ProcessID = ProcessId then
        Result:= String(PE.szExeFile)
      else while Process32Next(Snap, PE) do
        if PE.th32ProcessID = ProcessId then begin
          Result:= String(PE.szExeFile);
          break;
        end;
    CloseHandle(Snap);
  end;
end;

function GetTitle (Hwnd: THandle; Param: Pointer): Boolean; stdcall;
 var
  Text,TempString: string;
begin
  If (GetWindowLong(Hwnd,GWL_HWNDPARENT)=0) and (IsWindowVisible(Hwnd) or IsIconic(Hwnd))then
  begin
TempString := GetWindowExeName(Hwnd);
  SetLength (Text, 100);
  GetWindowText (Hwnd, PChar (Text), 100);
  Form1.ListBox1.Items.Add (IntToStr (Hwnd) + ' : '  + TempString + ' : ' +text);
  Result := True;
  end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  EWProc: EnumWindowsProc;
begin
  ListBox1.Items.Clear;
  EWProc := GetTitle;
  EnumWindows (@EWProc, 0);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
wnd :Hwnd;
temp :string;
EWProc: EnumWindowsProc;
ClickedOK :  boolean;
begin
clickedOK := InputQuery('Which Process do U wanna Kill','Process Number',temp);
if ClickedOK then
begin
Wnd := hwnd(strToInt(temp));
PostMessage(Wnd,WM_SYSCOMMAND,SC_CLOSE, 0);
  sleep(100);
  ListBox1.Items.Clear;
  EWProc := GetTitle;
  EnumWindows (@EWProc, 0);
end;
end;
end.
0
 

Author Comment

by:Blood_Line
ID: 6405049
thx I will be shure to take a look at it some time this week
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now