[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Detecting application launches

Posted on 2003-11-14
9
Medium Priority
?
537 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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

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

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 a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

829 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