?
Solved

Detecting application launches

Posted on 2003-11-14
9
Medium Priority
?
526 Views
Last Modified: 2010-05-18
Is there a way (I suspect a particular windows message) to find out when people launch programs/applications? Secondly once I can detect that is it possible to find out if it was launced with any parameters etc.?
0
Comment
Question by:Mat_a
[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
9 Comments
 
LVL 6

Expert Comment

by:DaFox
ID: 9750014
Nope there's no windows message that notifies your app that a second one was launched.
A windows hook would be one possibility to detect the launch though.

Markus
0
 

Author Comment

by:Mat_a
ID: 9750191
I'm not looking to see if my app is run again, I'm wanting to monitor all application activity. If you have any info on windows hooks to do this I will award the points, any answer to this would be great :)
0
 
LVL 6

Expert Comment

by:DaFox
ID: 9750727
Mat,

I was not talking about a second instance of your application, I meant a totally different application (I think that's what you are aiming at, right ;-)).
What kind of activity are you after? If you just want to know if app xy is launched, you could do it with a hook (if you got the classname, window title, ... of it).
If nobody else has a better idea I'll have a look at my personal code library for an example! ;-)

Markus
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:Mat_a
ID: 9750813
Markus

Ok, just double checking... A present it will be monitoring game launches. I could put a fake exe file there that send all teh params on and reports, but it's a lot of hassle for end users (and I don't even know if my idea will work), so I was hoping to find out when a game gets launched and what params are used :)

Have to say I've never done hooks before.
0
 
LVL 6

Accepted Solution

by:
DaFox earned 600 total points
ID: 9754780
Hi Mat,

here we go, hope this helps:

app:

function SetHook(): Boolean; stdcall; external 'MatHook.dll';
function RemoveHook(): Boolean; stdcall; external 'MatHook.dll';

// ...

procedure TForm1.Button1Click(Sender: TObject);
begin
  if (not SetHook) then ShowMessage('Couldn''t start Hook');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if (not RemoveHook) then ShowMessage('Couldn''t stop Hook');
end;

---

DLL:

library MatHook;

uses
  Windows,
  Messages;

type
  THookRec = record
    hMatHook: HHOOK;
    hMatWnd: HWND;
    oldProc: Integer;
  end;

var
  map: DWord;
  buf: ^THookRec;

// new window proc - runs in context of target process
function MatWndProc(Handle: hWnd; Msg: uInt; wp: wParam; lp: lParam): LongInt; stdcall;
begin
  try
    case Msg of
      WM_CREATE:
      begin
        MessageBox(0, GetCommandLine, 'Command Line parameter(s)', MB_OK);
      end;

      // user definied message to stop subclassing
      // (RegisterWindowMessage would be a better choice instead of WM_USER message!)
      WM_USER + 1:
      begin
        // delete custom menu entries (quick'n'dirty)
        SetWindowLong(buf^.hMatWnd, GWL_WNDPROC, buf^.oldProc);
      end;

    end;
    Result := CallWindowProc(Pointer(buf^.oldProc), Handle, Msg, wp, lp);
  except
    Result := 0;
  end;
end;

// hook proc - waits for target window to be created
function MatHookProc(nCode: Integer; wp: wParam; lp: lParam): LongInt; stdcall;
var
  hTemp: hWnd;
  szClass: array[0..255] of Char;
begin
  try
    if (nCode >= HC_ACTION) then
    begin
      Case nCode of
        HCBT_CREATEWND:
        begin
          hTemp := HWND(wp);
          FillChar(szClass, 256, 0);
          GetClassName(hTemp, szClass, 256);
          if (szClass = 'Notepad') then
          begin
            buf^.hMatWnd := htemp;
            buf^.oldProc := GetWindowLong(buf^.hMatWnd, GWL_WNDPROC);
            SetWindowLong(buf^.hMatWnd, GWL_WNDPROC, Integer(@MatWndProc));
          end;
        end;
        HCBT_DESTROYWND:
        begin
          hTemp := HWND(wp);
          FillChar(szClass, 256, 0);
          GetClassName(hTemp, szClass, 256);
          if (szClass = 'Notepad') then
          begin
            SetWindowLong(buf^.hMatWnd, GWL_WNDPROC, buf^.OldProc);
          end;

        end;
      end;
    end;
    Result := CallNextHookEx(buf^.hMatHook, nCode, wp, lp);
  except
    Result := 0;
  end;
end;

// sets up hook
function SetHook: Boolean; stdcall; export;
begin
  try
    Result := false;
    if (not assigned(buf)) then
    begin
      map := CreateFileMapping(DWord(-1), nil, PAGE_READWRITE, 0, SizeOf(THookRec), 'HookRecMemBlock');
      buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
      buf^.hMatHook := SetWindowsHookEx(WH_CBT, @MatHookProc, hInstance, 0);
      Result := true;
    end;
  except
    Result := false;
  end;
end;

// removes hook
function RemoveHook: Boolean; stdcall; export;
begin
  Result := false;
  if (assigned(buf)) then
  begin
    // tell our new wnd proc to stop subclassing
    // (has to be done in context of target process)
    SendMessage(buf^.hMatWnd, wm_User + 1, 1, 0);
    if (buf^.hMatHook <> 0) then UnhookWindowsHookEx(buf^.hMatHook);
    buf^.hMatHook := 0;
    UnmapViewOfFile(buf);
    buf := nil;
    Result := true;
  end;
end;

// DLL entry point
procedure DllEntry(dwReason: DWord);
begin
  Case dwReason of
    DLL_PROCESS_ATTACH:
    begin
      if (not assigned(buf)) then
      begin
        map := OpenFileMapping(FILE_MAP_ALL_ACCESS, false, 'HookRecMemBlock');
        buf := MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        CloseHandle(map);
        map := 0;
      end;
    end;
    DLL_PROCESS_DETACH:
    begin
      UnmapViewOfFile(buf);
      buf := nil;
    end;
  end;
end;

exports
  SetHook,
  RemoveHook;

// main
begin
  DisableThreadLibraryCalls(hInstance);
  DllProc := @DLLEntry;
  DllEntry(DLL_PROCESS_ATTACH);
end.


PS:
>> I could put a fake exe file there that send all teh params on and reports, but it's a lot of
>> hassle for end users (and I don't even know if my idea will work).

Yep, this would work. But what if your end user installs a patch or something else? Replacing the exe would be easy but has much side effects.

Markus
0
 
LVL 6

Expert Comment

by:DaFox
ID: 9754783
btw: the sample above subclasses notepad, just compile, run it and open notepad...
0
 
LVL 12

Expert Comment

by:Lee_Nover
ID: 9758509
you can use the IShellExecuteHook (doesn't 'catch' the apps run with CreateProcess)
http://www.delphi-si.com/forum/prikazisporocila.php?tema=271&mesto=0

// main unit source
unit mainunit;

interface

uses
  Windows, ActiveX, ComObj, ShlObj, ShellAPI, SysUtils;

type
  TTShellExeWiz = class(TComObject, IShellExecuteHook)
  protected
    {Declare IShellExecuteHook methods here}
    function Execute(var ShellExecuteInfo: TShellExecuteInfo): HResult; stdcall;
  end;

const
  Class_TShellExeWiz: TGUID = '{EEF655B2-0ADA-11D3-A850-00A0240CD0D7}';

implementation

uses ComServ, Dialogs;

{ TTShellExeWiz }

function TTShellExeWiz.Execute(
  var ShellExecuteInfo: TShellExecuteInfo): HResult;
begin
 Result := S_FALSE; // Allow the action to be processed

 with ShellExecuteInfo do
    begin
        if (Pos('notepad', ExtractFileName(lpFile)) > 0) then
            begin
                hInstApp := 33; // Must be >32 not to be an error
                Result := S_OK;
                ShowMessage('Jurk pa ne pusti zagnat Notepad.exe :-)');
            end;
    end;
end;

initialization
  TComObjectFactory.Create(ComServer, TTShellExeWiz, Class_TShellExeWiz,
    'TShellExeWiz', '', ciMultiInstance, tmApartment);
end.



// dll source
library IShellHook;

uses
  ComServ,
  Registry,
  ActiveX,
  Windows,
  mainu in 'mainu.pas',
  IShellHook_TLB in 'IShellHook_TLB.pas';

function DllRegisterServer: HResult;
begin
     Result:=ComServ.DllRegisterServer;
     if Failed(Result) then exit;
     with TRegistry.Create do
       try
          RootKey:=HKEY_LOCAL_MACHINE;
          if OpenKey('Software\Microsoft\Windows\CurrentVersion\explorer\ShellExecuteHooks', false) then begin
             try
                WriteString('{EEF655B2-0ADA-11D3-A850-00A0240CD0D7}', 'ShellExecCOMHook');
                Result:=S_OK;
             except
                Result:=E_FAIL;
             end;
             CloseKey;
          end;
       finally
          Free;
       end;
end;

function DllUnregisterServer: HResult;
begin
     Result:=ComServ.DllUnRegisterServer;
     if Failed(Result) then exit;
     with TRegistry.Create do
       try
          RootKey:=HKEY_LOCAL_MACHINE;
          if OpenKey('Software\Microsoft\Windows\CurrentVersion\explorer\ShellExecuteHooks', false) then begin
             if DeleteValue('ShellExecCOMHook') then
                Result:=S_OK;
             CloseKey;
          end;
       finally
          Free;
       end;
end;


exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.TLB}

{$R *.RES}

begin
end.






I'll try to find the complete project and post a link to it
0
 

Author Comment

by:Mat_a
ID: 9763181
DaFox - Works well.... I'm trying to figure out how to adapt this to watch all run apps, or how to remove the hook automatically after the info has been checked/tested

Lee - Can't find the IShellHook_TLB  unit

Thanks guys for the help, I've upped points to 200 to grab for you help
0
 
LVL 7

Expert Comment

by:twinsoft
ID: 29296274
Hi, the code that i sent to you shows how to implement the communication mechanism between the dll and the Delphi app. It does not cover the shellexecute hook as it was covered in a previous post. I will check your code and see what can be done...
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

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

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…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
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 …
Suggested Courses
Course of the Month15 days, 8 hours left to enroll

741 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