Solved

Detecting application launches

Posted on 2003-11-14
9
524 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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 200 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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

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…
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…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …

717 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