Solved

Detecting application launches

Posted on 2003-11-14
9
514 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
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
 

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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
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 seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

708 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