• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1295
  • Last Modified:

Does JournalRecord hook from service require "Allow service to interact With Desktop"?

Hello!
  I have restarted working on my work-monitoring utility :-)
  I was wprking with my Journal Record service and noticed that it worked only when I check the "Allow service to interact With Desktop" checkbox. If it is not checked, I get the message "No Journal Hook availible" in my file.
  The service monitors different mouse/keyboard events and logs them in a file "C:\IdlLog.Txt".
  I am running it under Win XP and have compiled it in Delphi 7.
  Can some body tell me why this could happen and what is the solution?
  Here's the unit:
unit WorkUnit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  ExtCtrls;

Const
  TimeToSec = 86400;

type
  TService1 = class(TService)
    Timer1: TTimer;
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceExecute(Sender: TService);
    procedure Timer1Timer(Sender: TObject);

  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  Service1: TService1;
  MyHook, KHook: THandle;
  LastActivityTime, LastCheckTime, TheTotalIdleCount, TheCurrentIdleCount,
  TheIdleCutOff, TheCurrentWorkCount : TDateTime;
  FHookStarted : Boolean;
  MsgLog: TStringList;
  KbdLog: String;
implementation

{$R *.DFM}

Function SecondOfTheDay(CnvTime: TDateTime): Integer;
Begin
  Result := Round(CnvTime * TimeToSec);
End;

Function GetTimeDiff(CurTime, PreTime: TDateTime): TDateTime;
Begin


  If CurTime < PreTime Then
  Begin
    CurTime := 1 + CurTime;
  End;
  Result := CurTime - PreTime;

End;



Procedure UpdateIdleTime(KeyFlag:Boolean = True);
var
  TimeDiff, CurTime: TDateTime;

Begin

  CurTime := TIME;
  If KeyFlag Then
  Begin
    TimeDiff := GetTimeDiff(CurTime, LastActivityTime);
    If TimeDiff >= TheIdleCutOff Then
    Begin
      TheTotalIdleCount := TheTotalIdleCount + TimeDiff;
      TheCurrentIdleCount := TheCurrentIdleCount + (GetTimeDiff(CurTime, LastCheckTime));
    End
    Else
    Begin
      TheCurrentWorkCount := TheCurrentWorkCount + TimeDiff;
    end;

    LastCheckTime := CurTime;
    LastActivityTime := LastCheckTime;
  End
  Else
  Begin
    TimeDiff := GetTimeDiff(CurTime, LastCheckTime);
    If TimeDiff >= TheIdleCutOff Then
    Begin
      TheCurrentIdleCount := TheCurrentIdleCount + TimeDiff;
    End;
    LastCheckTime := CurTime;
  End;

End;



Function GetWorkStats: Word;

Begin

  Result := SecondOfTheDay(TheCurrentWorkCount);
  TheCurrentWorkCount := 0;

End;


procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;

function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

function JournalProc(Code, wParam: Integer; var EventStrut: TEventMsg): Integer; stdcall;
var
  s: string;
  KbdFlag: Boolean;
begin
  {this is the JournalRecordProc}
  Result := CallNextHookEx(MyHook, Code, wParam, Longint(@EventStrut));
  {the CallNextHookEX is not really needed for journal hook since it it not
  really in a hook chain, but it's standard for a Hook}
  if Code < 0 then Exit;

  {you should cancel operation if you get HC_SYSMODALON}
  if Code = HC_SYSMODALON then Exit;
  if Code = HC_ACTION then
  begin
    {
    The lParam parameter contains a pointer to a TEventMsg
    structure containing information on
    the message removed from the system message queue.
    }

    s := '';
    KbdFlag := False;
    if EventStrut.message = WM_LBUTTONUP then
      s := 'Left Mouse UP at X pos ' +
        IntToStr(EventStrut.paramL) + ' and Y pos ' + IntToStr(EventStrut.paramH);

    if (EventStrut.message = WM_RBUTTONUP) then
      s := 'Right Mouse Up at X pos ' +
        IntToStr(EventStrut.paramL) + ' and Y pos ' + IntToStr(EventStrut.paramH);

    if (EventStrut.message = WM_MOUSEWHEEL) then
      s := 'Mouse Wheel at X pos ' +
        IntToStr(EventStrut.paramL) + ' and Y pos ' + IntToStr(EventStrut.paramH);

    if (EventStrut.message = WM_KEYUP) then
    Begin
      KbdFlag := True;
      s := 'Keyboard';
      KbdLog := KbdLog + Format('<%d>',[EventStrut.paramL]);

      If wParam = VK_Return Then
      Begin
        KbdFlag := False;
        s := KbdLog;
        KbdLog := '';
      End;
    End;

    if s <> '' then
    Begin
      If not KbdFlag then
        MsgLog.Add(s);
      UpdateIdleTime;
    End;
  end;
end;

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
Var
  CutOffSec, CheckSec: Integer;
begin

  CutOffSec := 5;
  CheckSec := 10;
  MsgLog := TStringList.Create;
  KbdLog :='';
  if FHookStarted then
  begin
    MsgLog.Add('Mouse is already being Journaled, can not restart');
    Exit;
  end;

  LastActivityTime := TIME;
  LastCheckTime := LastActivityTime;
  TheIdleCutOff := CutOffSec / TimeToSec;
  TheTotalIdleCount := 0;
  TheCurrentIdleCount := 0;
  TheCurrentWorkCount := 0;

  MyHook := SetWindowsHookEx(WH_JOURNALRECORD, @JournalProc, hInstance, 0);
  Timer1.Interval := CheckSec * 1000;
  Timer1.Enabled := True;
  {SetWindowsHookEx starts the Hook}
  if MyHook > 0 then
  begin
    FHookStarted := True;
  end
  else
    MsgLog.Add('No Journal Hook availible');
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  FHookStarted := False;
  Timer1.Enabled := False;
  Timer1Timer(Timer1);
  UpdateIdleTime;
  UnhookWindowsHookEx(MyHook);
  MyHook := 0;
  MsgLog.Add(KbdLog);
  MsgLog.SaveToFile('C:\IdlLog.Txt');
  MsgLog.Free;
end;

procedure TService1.ServiceExecute(Sender: TService);
begin
 while not Terminated do
    ServiceThread.ProcessRequests(True);
end;

procedure TService1.Timer1Timer(Sender: TObject);
Var
  TotalIdl, CurIdl, CurWrk: Word;
begin
  CurWrk := GetWorkStats;
  MsgLog.Add(Format('Work = %d',[CurWrk]));
end;

end.

0
snehanshu
Asked:
snehanshu
4 Solutions
 
robert_marquardtCommented:
Applying my common sense:
You want to access an application. An application runs on a desktop.
0
 
snehanshuAuthor Commented:
>>You want to access an application.
I thought I wanted to catch windows messages.
Does it mean that keyboard hooks also would not work if I haven't checked this thing? I haven't tried it, but want to know.
What classifies as "Desktop thing" and what does not?
...Snehanshu
0
 
pritaeasSoftware EngineerCommented:
You may find some info here

http://www.geocities.com/macrotech_tr/API.html

hth, pritaeas
0
Technology Partners: 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!

 
GloomyFriarCommented:
When you have the "Allow service to interact With Desktop" checkbox unchecked your service run in a "black box" so it can't do what you want.
0
 
snehanshuAuthor Commented:
GloomyFriar,
>>your service run in a "black box"
  Is it true about JournalRecord or any hook?
  And is there some place where I can find information on what lies inside the black box and what lies outside?
:-)
Thanks,
...Snehanshu
0
 
Lee_NoverCommented:
imo mouse and kbd aren't accessible from a service
you can have different settings for them for each user
that's why you need to interact with the desktop

I also have a monitoring service and it needs to be interactive (I use the mouse and kbd hooks separately)

a simple rule of thumb .. anything that can be customized on a user level can't be accessed from a service unless it's interactive OR by using user Impersonation
0
 
snehanshuAuthor Commented:
Lee_Nover,
>>unless it's interactive
  I didn't know you could enable that check box on install just by changing the interactive property to true at design time!
  I have also got a few links from experts at Windows Programming TA and looks like I am all set to continue my task for now.
http://www.experts-exchange.com/Programming/Programming_Platforms/Win_Prog/Q_20802669.html
  Thank you all your help.
...Snehanshu
0
 
snehanshuAuthor Commented:
>>Thank you all your help.
Thank you all for your help.
:-)
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.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now