Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

New method

Posted on 1999-06-24
13
Medium Priority
?
182 Views
Last Modified: 2010-04-06
How can I create a method which will listen for a new application started or closed?
for example when I click to "myshortcut" to know what is started and contra?

Cheers
0
Comment
Question by:jami55
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 2
13 Comments
 
LVL 20

Expert Comment

by:Madshi
ID: 1384448
If I understand you correctly, you want to be notified about the creation and termination of any process system wide. Is that right?

Well, that's quite difficult! What you CAN do is make a snapshot of the currently running processes in a timer. Then you can look what has changed. If you're interested in this solution, look at my homepage "http://beam.to/madshi". There you can download the unit "enumStuff.pas", which with you can enumerate all currently running processes (this unit works only with Delphi4).

If you don't like polling, tell me, then we'll find some other ways. Please tell me then for what you need this stuff in detail. E.g. tell me if you need to be notified about window-less application, too.

Regards, Madshi.
0
 

Author Comment

by:jami55
ID: 1384449
Well, I saw your unit Madshi, but it's not woking....but
never mind (I am using Delphi 4),so I need somethin like this:

unit Unit1

........
var pl1:TProcessList;
.......

TForm1.OnCreate
....
begin
pl1:=GetprocessList;

...
end

TForm1.Timer1OnTimer ----------- Interval="1"
var pl2:TProcessList;
begin
....
Timer1.Enabled:=false;
pl2:=GetprocessList
if pl1<>pl2 then GiveMeTheDifference;
Timer1.Enabled:true;
...
end;


Please give me some source. OK?
Did you understood me now?

Cheers
0
 

Author Comment

by:jami55
ID: 1384450
I mean really source, just to put it in my unit
not via another unit.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 3

Expert Comment

by:philipleighs
ID: 1384451
Hi,

If it is enough to know when any (system wide) window is created then you can use a CBT hook.
In the call back, check for HCBT_CREATEWND as the first parameter.
You need to put the callback in a DLL.

Looks like the code prevents any window whose classame is notepad from being created...

Here is some code. Someone else wrote it a while back on ee.

The dll looks like this:--------------------------------

library NewWndDll;

uses
SysUtils,
Classes,
Windows;

function NewWindowHookCallBack(pCode: Integer; pHandle: WPARAM; pWindow:LPARAM): LRESULT; stdcall;
var s1 : string;
begin
result:=0;
if pCode=HCBT_CREATEWND then begin
SetLength(s1,MAX_PATH+1);
SetLength(s1,GetClassName(pHandle,pchar(s1),MAX_PATH));

if s1 = 'NotePad' then
  Result := 1; //Don't let notepad run
end;
end;

exports NewWindowHookCallBack index 1 name 'NewWindowHookCallBack';

end.


Create an exe with this to test the dll:------------------
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

var hook : integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
hook:=SetWindowsHookEx(WH_CBT,
GetProcAddress(GetModuleHandle('NewWndDll'),'NewWindowHookCallBack'),
GetModuleHandle('NewWndDll'), 0);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
UnhookWindowsHookEx(hook);
end;

initialization
MessageBox(0,pchar(intToStr(LoadLibrary('c:\windows\desktop\newwnddll'))),'loadLibrary',0);
end.



0
 

Author Comment

by:jami55
ID: 1384452
I tried your dll, but what about application which does not
have a window. I want to stop backorffice running on my computer. Is it possible to see (not class name) but
filename which is running with your dll philip?

Cheers

Madshi?

0
 
LVL 20

Expert Comment

by:Madshi
ID: 1384453
Hi Phil, it was me who has written the code...   :-)))
Indeed the CBT hook is a possibility to avoid polling. But as jami pointed out, it works only for applications that have windows.

Hi jami, here comes a try. I did not test it, but I think it should work alright. If you have problems with it, tell me about it:

procedure TForm1.Timer1OnTimer(Sender: TObject);
var pl2 : TProcessList;
    i1  : integer;
begin
  Timer1.Enabled:=false;
  pl2:=GetProcessList;
  for i1:=0 to high(pl1) do begin
    b1:=true;
    for i2:=0 to high(pl2) do
      if pl1[i1].processID=pl2[i2].processID then begin
        b1:=false;
        break;
      end;
    if b1 then memo1.lines.add('the process "'+pl1[i1].exeFile+'" was terminated.');
  end;
  for i1:=0 to high(pl2) do begin
    b1:=true;
    for i2:=0 to high(pl1) do
      if pl2[i1].processID=pl1[i2].processID then begin
        b1:=false;
        break;
      end;
    if b1 then memo1.lines.add('the process "'+pl2[i1].exeFile+'" was newly started.');
  end;
  pl1:=pl2;  // this prepares for the next timer...
  Timer1.Enabled:=true;
end;

Regards, Madshi.
0
 

Author Comment

by:jami55
ID: 1384454
A big problem, Madshi. I include your unit to my form like
this:

uses Windows,classes,.....,EnumStuff;

and I got error:

Undelcared identifier pl[i1].processID

Could you write me a whole unit, please? (I mean wihout
enumStuff)

Cheers.
0
 
LVL 20

Accepted Solution

by:
Madshi earned 800 total points
ID: 1384455
Ok, here comes the full unit. Create a new project, add a memo and a button to the form and connect the 3 event handlers:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
type
  TProcessEntry32 = record
                      dwSize              : DWORD;
                      cntUsage            : DWORD;
                      th32ProcessID       : DWORD;        // this process
                      th32DefaultHeapID   : DWORD;
                      th32ModuleID        : DWORD;        // associated exe
                      cntThreads          : DWORD;
                      th32ParentProcessID : DWORD;        // this process's parent process
                      pcPriClassBase      : integer;      // Base priority of process's threads
                      dwFlags             : DWORD;
                      szExeFile           : array [0..MAX_PATH-1] of char;    // Path
                    end;
const TH32CS_SnapProcess = 2;
var   CreateToolhelp32Snapshot :
        function (dwFlags,th32ProcessID: cardinal) : cardinal; stdcall
        = nil;
      Process32First :
        function (hSnapshot: cardinal; var lppe: TProcessEntry32) : bool; stdcall
        = nil;
      Process32Next :
        function (hSnapshot: cardinal; var lppe: TProcessEntry32) : bool; stdcall
        = nil;

function TestToolhelpFunctions : boolean;
var c1 : cardinal;
begin
  c1:=GetModuleHandle('kernel32');
  @CreateToolhelp32Snapshot:=GetProcAddress(c1,'CreateToolhelp32Snapshot');
  @Process32First          :=GetProcAddress(c1,'Process32First'          );
  @Process32Next           :=GetProcAddress(c1,'Process32Next'           );
  result:=(@CreateToolhelp32Snapshot<>nil) and
          (@Process32First<>nil) and (@Process32Next<>nil);
end;

type TProcessList        = array of record
                                      pid  : cardinal;
                                      name : string;
                                    end;
     TPProcessList       = ^TProcessList;

function NT4_EnumProcessesAndThreads(pl: TPProcessList; tl: pointer; windowsToo: boolean) : boolean;
type TPerfDataBlock           = packed record
                                  signature              : array [0..3] of wchar;
                                  littleEndian           : cardinal;
                                  version                : cardinal;
                                  revision               : cardinal;
                                  totalByteLength        : cardinal;
                                  headerLength           : cardinal;
                                  numObjectTypes         : cardinal;
                                  defaultObject          : cardinal;
                                  systemTime             : TSystemTime;
                                  perfTime               : comp;
                                  perfFreq               : comp;
                                  perfTime100nSec        : comp;
                                  systemNameLength       : cardinal;
                                  systemnameOffset       : cardinal;
                                end;
     TPPerfDataBlock          = ^TPerfDataBlock;

     TPerfObjectType          = packed record
                                  totalByteLength        : cardinal;
                                  definitionLength       : cardinal;
                                  headerLength           : cardinal;
                                  objectNameTitleIndex   : cardinal;
                                  objectNameTitle        : PWideChar;
                                  objectHelpTitleIndex   : cardinal;
                                  objectHelpTitle        : PWideChar;
                                  detailLevel            : cardinal;
                                  numCounters            : cardinal;
                                  defaultCounter         : integer;
                                  numInstances           : integer;
                                  codePage               : cardinal;
                                  perfTime               : comp;
                                  perfFreq               : comp;
                                end;
     TPPerfObjectType         = ^TPerfObjectType;

     TPerfCounterDefinition   = packed record
                                  byteLength             : cardinal;
                                  counterNameTitleIndex  : cardinal;
                                  counterNameTitle       : PWideChar;
                                  counterHelpTitleIndex  : cardinal;
                                  counterHelpTitle       : PWideChar;
                                  defaultScale           : integer;
                                  defaultLevel           : cardinal;
                                  counterType            : cardinal;
                                  counterSize            : cardinal;
                                  counterOffset          : cardinal;
                                end;
     TPPerfCounterDefinition  = ^TPerfCounterDefinition;

     TPerfInstanceDefinition  = packed record
                                  byteLength             : cardinal;
                                  parentObjectTitleIndex : cardinal;
                                  parentObjectInstance   : cardinal;
                                  uniqueID               : integer;
                                  nameOffset             : cardinal;
                                  nameLength             : cardinal;
                                end;
     TPPerfInstanceDefinition = ^TPerfInstanceDefinition;
     TAPChar                  = array [0..maxInt div 4-1] of pchar;
     TPCardinal               = ^cardinal;
var  i1,i2,i3,i4              : integer;
     b1,b2,b3,b4              : boolean;
     bt,bp                    : boolean;
     c1                       : cardinal;
     pCard                    : TPCardinal;
     perfDataBlock            : TPPerfDataBlock;
     perfObjectType           : TPPerfObjectType;
     perfCounterDef           : TPPerfCounterDefinition;
     perfInstanceDef          : TPPerfInstanceDefinition;
begin
  result:=false;
  bt:=tl=nil; bp:=pl=nil; if not bp then pl^:=nil;
  if bt and bp then exit;
  perfDataBlock:=nil;
  try
    i1:=$10000;
    repeat
      ReallocMem(perfDataBlock,i1); i2:=i1;
      i4:=RegQueryValueEx(HKEY_PERFORMANCE_DATA,'230 232',nil,@i3,pointer(perfDataBlock),@i2);
      if i4=ERROR_MORE_DATA then i1:=i1*2;
    until (i4<>ERROR_MORE_DATA);
    if i4<>ERROR_SUCCESS then exit;
    perfObjectType:=pointer(cardinal(perfDataBlock)+perfDataBlock^.headerLength);
    for i1:=0 to integer(perfDataBlock^.numObjectTypes)-1 do begin
      b1:=             (pl<>nil) and (perfObjectType^.objectNameTitleIndex=230);   // 230 -> "Process"
      b2:=(not b1) and (tl<>nil) and (perfObjectType^.objectNameTitleIndex=232);   // 232 -> "Thread"
      if b1 or b2 then begin
        perfCounterDef:=pointer(cardinal(perfObjectType)+perfObjectType^.headerLength);
        for i2:=0 to perfObjectType^.numCounters-1 do begin
          b3:=              perfCounterDef^.counterNameTitleIndex=784;    // 784 -> "ID Process"
          b4:=(not b3) and (perfCounterDef^.counterNameTitleIndex=804);   // 804 -> "ID Thread"
          if b3 or b4 then begin
            perfInstanceDef:=pointer(cardinal(perfObjectType)+perfObjectType^.definitionLength);
            if b1 then SetLength(pl^,perfObjectType^.numInstances-1);
            for i3:=0 to perfObjectType^.numInstances-2 do begin
              c1:=TPCardinal(cardinal(perfInstanceDef)+perfInstanceDef^.byteLength+perfCounterDef^.counterOffset)^;
              if b1 then begin
                pl^[i3].pid:=c1;
                if c1<>0 then begin
                  pl^[i3].name:=wideString(PWideChar(cardinal(perfInstanceDef)+perfInstanceDef.nameOffset));
                  if pl^[i3].name<>'System' then pl^[i3].name:=pl^[i3].name+'.exe';
                end else pl^[i3].name:='[System Process]';
              end;
              pCard:=pointer(cardinal(perfInstanceDef)+perfInstanceDef^.byteLength);
              perfInstanceDef:=pointer(cardinal(pCard)+pCard^);
            end;
          end;
          inc(perfCounterDef);
        end;
        bt:=bt or b2; bp:=bp or b1; if bt and bp then break;
      end;
      perfObjectType:=pointer(cardinal(perfObjectType)+perfObjectType^.totalByteLength);
    end;
    result:=(pl<>nil) and (pl^<>nil);
  finally FreeMem(perfDataBlock) end;
end;

type TOperatingSystem = (osUnknown, osWin311, osWin95, osWin95osr2, osWin98, osWinNT3, osWinNT4, osWinNT4SP4, osWinNT5);

var OS      : TOperatingSystem;
    OSReady : boolean = false;
function GetOperatingSystem : TOperatingSystem;
var os1 : TOSVersionInfo;
begin
  if not OSReady then begin
    OSReady:=true;
    os1.dwOSVersionInfoSize:=sizeOf(os1); GetVersionEx(os1);
    case os1.dwPlatformID of
      VER_PLATFORM_WIN32s        : OS:=osWin311;
      VER_PLATFORM_WIN32_WINDOWS : if (os1.dwMajorVersion=4) and (os1.dwMinorVersion=0) then begin
                                     if os1.dwBuildNumber>1000 then OS:=osWin95osr2 else OS:=osWin95;
                                   end else if (os1.dwMajorVersion=4) and (os1.dwMinorVersion=10) then
                                     OS:=osWin98
                                   else OS:=osUnknown;
      VER_PLATFORM_WIN32_NT      : case os1.dwMajorVersion of
                                     0..3 : OS:=osWinNT3;
                                     4    : if string(os1.szCSDVersion)='Service Pack 4' then OS:=osWinNT4SP4
                                            else                                              OS:=osWinNT4;
                                     5    : OS:=osWinNT5;
                                   end;
      else                         OS:=osUnknown;
    end;
  end;
  result:=OS;
end;

function GetProcessList : TProcessList;
var c1 : cardinal;
    i1 : integer;
    pe : TProcessEntry32;
begin
  result:=nil;
  if GetOperatingSystem in [osWin95,osWin95osr2,osWin98,osWinNT5] then begin
    if not TestToolhelpFunctions then begin
      MessageBox(0,'Toolhelp functions not available.','Error...',0);
      exit;
    end;
    c1:=CreateToolHelp32Snapshot(TH32CS_SnapProcess,0);
    try
      i1:=0;
      pe.dwSize:=sizeOf(pe);
      if Process32First(c1,pe) then
        repeat
          SetLength(result,i1+1);
          result[i1].pid:=pe.th32ProcessID; result[i1].name:=pe.szExeFile;
          inc(i1);
        until not Process32Next(c1,pe);
    finally CloseHandle(c1) end;
  end else if GetOperatingSystem in [osWinNT3,osWinNT4,osWinNT4SP4] then
    if not NT4_EnumProcessesAndThreads(@result,nil,false) then
      MessageBox(0,'Error reading Performace Data.','Error...',0);
end;

var oldProcesses : TProcessList;

procedure TForm1.FormCreate(Sender: TObject);
begin
  oldProcesses:=GetProcessList;
end;

procedure TForm1.Button1Click(Sender: TObject);
var pl2   : TProcessList;
    i1,i2 : integer;
    b1    : boolean;
begin
  pl2:=GetProcessList;
  for i1:=0 to high(oldProcesses) do begin
    b1:=true;
    for i2:=0 to high(pl2) do
      if oldProcesses[i1].pid=pl2[i2].pid then begin
        b1:=false;
        break;
      end;
    if b1 then memo1.lines.add('the process "'+oldProcesses[i1].name+'" was terminated.');
  end;
  for i1:=0 to high(pl2) do begin
    b1:=true;
    for i2:=0 to high(oldProcesses) do
      if pl2[i1].pid=oldProcesses[i2].pid then begin
        b1:=false;
        break;
      end;
    if b1 then memo1.lines.add('the process "'+pl2[i1].name+'" was newly started.');
  end;
  oldProcesses:=pl2;
end;

end.

Regards, Madshi.
0
 

Author Comment

by:jami55
ID: 1384456
It's excellent Madshi,Thanks. I put a timer (interval 1mS)
and on timerevent I put onButton1Click, and it's working greate, but did you notice when starting iexporer, it returns process newly started and terminated at the same time. Why?

Cheers
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1384457
It's because that is what's happening!!! IE4's "iexplore.exe" does nothing but open a new window in the process context of "explorer.exe" with specific parameters. Look how small iexplore.exe is!
It's different with IE5. There iexplore.exe is a "real" application...

Regards, Madshi.
0
 

Author Comment

by:jami55
ID: 1384458
Ok.
0
 
LVL 3

Expert Comment

by:philipleighs
ID: 1384459
Hi Madshi,

I hope you don't mind me copying your code way back when.
I thought it might come in handy one day!

Cheers,
Phil.

0
 
LVL 20

Expert Comment

by:Madshi
ID: 1384460
No prob! I like it when other experts find my code so useful that they copy it...   :-)
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

661 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