A nice 'service' detecting Outlook start

Hello there,

I would like to have a Delphi program (for project we are developping) that is being activated after an Outlook start, but before Outlook get visible (have to init a database connection then, et cetera).

A Windows service running detecting an Outlook start is Okee, but it had to run on Windows 95 and NT. And to offer security possibilities. An application in registry under currentversion/run also works for me.

Moving Outlook.exe and replacing it with my own app. or a registry thrick is not an option

Could I do something with a hook?

I'm running out of options, anybody who could give me some help? I could return the favor with some Word / WP automation.

Thanx,
Floris.

LVL 2
florisbAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

florisbAuthor Commented:
Adjusted points to 360
0
intheCommented:
righty ho,
i spent a whie taking snippets of code from here and there trying to get this to work and came up with the following.
it is a hook which hooks the creating of windows if you know the class name
i dunno how much you know about class names but for instance
notepads classname is "notepad" and the form you see if outlook starts in inbox has a classname of "rctrl_renwnd32"..
you can get a program called "sinfo" (search yahoo for download address) this program will give class names etc..also does winsight program if you hav eit..

anyway here is demo of hooking notepad starting:

the dll is like:

library TheHook;

uses
  Windows,
  Messages,
  Dialogs,
  SysUtils;

{Define a record for recording and passing information process wide}  
type
  PHookRec = ^THookRec;
  THookRec = packed record
    TheHookHandle : HHOOK;
    TheAppWinHandle : HWND;
    TheCtrlWinHandle : HWND;
    TheKeyCount : DWORD;
  end;

var
  hObjHandle : THandle; {Variable for the file mapping object}
  lpHookRec : PHookRec; {Pointer to our hook record}


procedure MapFileMemory(dwAllocSize : DWORD);
begin
 {Create a process wide memory mapped variable}
  hObjHandle := CreateFileMapping($FFFFFFFF,
                                  NIL,
                                  PAGE_READWRITE,
                                  0,
                                  dwAllocSize,
                                  'HookRecMemBlock');
   if (hObjHandle = 0) then begin
     MessageBox(0,
                'Hook DLL',
                'Could not create file map object',
                MB_OK);
     exit;
   end;
 {Get a pointer to our process wide memory mapped variable}
  lpHookRec := MapViewOfFile(hObjHandle,
                             FILE_MAP_WRITE,
                             0,
                             0,
                             dwAllocSize);
  if (lpHookRec = NIL) then begin
    CloseHandle(hObjHandle);
    MessageBox(0,
               'Hook DLL',
               'Could not map file',
               MB_OK);
    exit;
  end;
end;


procedure UnMapFileMemory;
begin
 {Delete our process wide memory mapped variable}
  if (lpHookRec <> NIL) then begin
    UnMapViewOfFile(lpHookRec);
    lpHookRec := NIL;
  end;
  if (hObjHandle > 0) then begin
    CloseHandle(hObjHandle);
    hObjHandle := 0;
  end;
end;


function GetHookRecPointer : pointer stdcall;
begin
 {Return a pointer to our process wide memory mapped variable}
  result := lpHookRec;
end;


{The function that actually processes the keystrokes for our hook}
function KeyBoardProc(code:integer;wparam,lparam:longint):longint;stdcall;
var
    res:longint;
    cbtcreatewnd:pcbtcreatewnd;
begin
  if code < 0 then result := CallNextHookEx(lpHookRec^.TheHookHandle, code, wparam, lparam)
    else if code=hcbt_createwnd then
      begin
        try
          cbtcreatewnd:=pointer(lparam);
          with cbtcreatewnd^.lpcs^ do
            begin
              res:=0;
              if lowercase(lpszclass)=lowercase('notepad') then res:=1;
              result:=res;
            end;
        except on exception do
          result:=0;
        end;
      end
      else result:=0;
    IF RES = 1 THEN SHOWMESSAGE('NOTEPAD');//DEBUGGING
end;

procedure StartKeyBoardHook; stdcall;
begin
 {If we have a process wide memory variable}
 {and the hook has not already been set...}
  if ((lpHookRec <> NIL) AND
      (lpHookRec^.TheHookHandle = 0)) then begin
   {Set the hook and remember our hook handle}
    lpHookRec^.TheHookHandle := SetWindowsHookEx(WH_CBT,
                                                 @KeyBoardProc,
                                                 hInstance,
                                                 0);
  end;
end;


procedure StopKeyBoardHook; stdcall;
begin
 {If we have a process wide memory variable}
 {and the hook has already been set...}
  if ((lpHookRec <> NIL) AND
      (lpHookRec^.TheHookHandle <> 0)) then begin
   {Remove our hook and clear our hook handle}
    if (UnHookWindowsHookEx(lpHookRec^.TheHookHandle) <> FALSE) then
begin
      lpHookRec^.TheHookHandle := 0;
    end;
  end;
end;


procedure DllEntryPoint(dwReason : DWORD);
begin
  case dwReason of
    Dll_Process_Attach : begin
     {If we are getting mapped into a process, then get}
     {a pointer to our process wide memory mapped variable}
      hObjHandle := 0;
      lpHookRec := NIL;
      MapFileMemory(sizeof(lpHookRec^));
    end;
    Dll_Process_Detach : begin
     {If we are getting unmapped from a process then, remove}
     {the pointer to our process wide memory mapped variable}
      UnMapFileMemory;
    end;
  end;
end;


exports
  KeyBoardProc name 'KEYBOARDPROC',
  GetHookRecPointer name 'GETHOOKRECPOINTER',
  StartKeyBoardHook name 'STARTKEYBOARDHOOK',
  StopKeyBoardHook name 'STOPKEYBOARDHOOK';



begin
 {Set our Dll's main entry point}
  DLLProc := @DllEntryPoint;
 {Call our Dll's main entry point}
  DllEntryPoint(Dll_Process_Attach);
end.







and the demo is like:


unit TestTheHook;
interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Timer1: TTimer;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button1KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{Functions prototypes for the hook dll}
type TGetHookRecPointer = function : pointer stdcall;

type TStartKeyBoardHook = procedure stdcall;

type TStopKeyBoardHook = procedure stdcall;

{The record type filled in by the hook dll}
type THookRec = packed record
  TheHookHandle : HHOOK;
  TheAppWinHandle : HWND;
  TheCtrlWinHandle : HWND;
  TheKeyCount : DWORD;

end;

{A pointer type to the hook record}
type PHookRec = ^THookRec;

var
  hHookLib : THANDLE; {A handle to the hook dll}
  GetHookRecPointer : TGetHookRecPointer; {Function pointer}
  StartKeyBoardHook : TStartKeyBoardHook; {Function pointer}
  StopKeyBoardHook : TStopKeyBoardHook; {Function pointer}
  LibLoadSuccess : bool; {If the hook lib was successfully loaded}
  lpHookRec : PHookRec; {A pointer to the hook record}
  EnterKeyCount : DWORD; {An internal count of the Enter Key}
  procedure TForm1.FormCreate(Sender: TObject);
begin
 {Set our initial variables}
  Timer1.Enabled := FALSE;
  Timer1.Interval := 1000;
  Label1.Caption := '0 Keys Logged';
  Label2.Caption := '0 Enter Keys Logged';
  EnterKeyCount := 0;
  lpHookRec := NIL;
  LibLoadSuccess := FALSE;
  @GetHookRecPointer := NIL;
  @StartKeyBoardHook := NIL;
  @StopKeyBoardHook := NIL;
 {Try to load the hook dll}
  hHookLib := LoadLibrary('THEHOOK.DLL');
 {If the hook dll was loaded successfully}
  if hHookLib <> 0 then begin
   {Get the function addresses}
    @GetHookRecPointer :=
      GetProcAddress(hHookLib, 'GETHOOKRECPOINTER');
    @StartKeyBoardHook :=
      GetProcAddress(hHookLib, 'STARTKEYBOARDHOOK');
    @StopKeyBoardHook :=
      GetProcAddress(hHookLib, 'STOPKEYBOARDHOOK');
   {Did we find all the functions we need?}
    if ((@GetHookRecPointer <> NIL) AND
        (@StartKeyBoardHook <> NIL) AND
        (@StopKeyBoardHook <> NIL)) then begin
       LibLoadSuccess := TRUE;
      {Get a pointer to the hook record}
       lpHookRec := GetHookRecPointer;
      {Were we successfull in getting a ponter to the hook record}
       if (lpHookRec <> nil) then begin
        {Fill in our portion of the hook record}
         lpHookRec^.TheHookHandle := 0;
         lpHookRec^.TheCtrlWinHandle := Button1.Handle;
         lpHookRec^.TheKeyCount := 0;
        {Start the keyboard hook}
         StartKeyBoardHook;
        {Start the timer if the hook was successfully set}

         if (lpHookRec^.TheHookHandle <> 0) then begin
           Timer1.Enabled := TRUE;

         end;
       end;
    end else begin
     {We failed to find all the functions we need}
      FreeLibrary(hHookLib);
      hHookLib := 0;
      @GetHookRecPointer := NIL;
      @StartKeyBoardHook := NIL;
      @StopKeyBoardHook := NIL;
    end;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 {Did we load the dll successfully?}
  if (LibLoadSuccess = TRUE) then begin
   {Did we sucessfully get a pointer to the hook record?}
    if (lpHookRec <> nil) then begin
     {Did the hook get set?}
      if (lpHookRec^.TheHookHandle <> 0) then begin
        Timer1.Enabled := FALSE;
        StopKeyBoardHook;
      end;
    end;
   {Free the hook dll}
    FreeLibrary(hHookLib);
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 {Display the number of keystrokes logged}
  Label1.Caption := IntToStr(lpHookRec^.TheKeyCount) + ' Keys Logged';
end;

procedure TForm1.Button1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 {Process message sent from hook dll and display}
 {number of time the enter key was pressed}
  if (Key = 0) then begin
    Inc(EnterKeyCount);
    Label2.Caption := IntToStr(EnterKeyCount) + ' Enter Keys Logged';
  end;
end;

end.




the labels and button in the demo are irrelevent (as is some of the code) they were for testing a keyboard hook as that what most of this code origianlly came from hence the names "startkeyboardhook" etc..

make the demo and run the program then start a instance of notepad to see the hook in action ..

ill do some tests on other outlook classnames like rctrl_renwnd32 to check how it best works
Regards Barry
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
intheCommented:
btw
when satisfies that all is well, we'll skim all the rubbish off the code and make it much smaller.and have it running all the time (via run in registry) and hide the form from ctrl-alt-del menu and taskbar etc so it is like a service..
0
snoop_doggy_doggCommented:
Woah Nelly!

Could you just write an add-in for Outlook that hides the Outlook window or shows some kind of splash screen or progress screen while making your DB connection?

Woof!
0
florisbAuthor Commented:
I'm happy with your answer, inthe.

I'm not an expert in the area of dll. You said something about skimming the code? Could you send this to me in a Delphi project?

Great great... ...:-)

Would you like to have my Word / WordPerfect COM object?

I'll send you this message by mail too.

Thanks again,
Floris.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.