Solved

novice Service writer

Posted on 2008-10-15
22
265 Views
Last Modified: 2012-06-27
i'm new at writing services. i've written my first one in D7 that attempts to update a field in a table when a someone alters the clock on the computer, but am having trouble running/connecting it to the time change event (so it seems). i'm attaching my .pas file (in a text document), in hopes someone can tell me what's missing from the code. i think i may be missing a component or two but i'm not sure. the file compiles fine and i can install the service but when i start it and make a change to the time it doesn't do anything. it seems like its just running but not watching/listening for the time change.
ServicePas.txt
0
Comment
Question by:mikesExpertExchange
  • 9
  • 5
  • 5
  • +1
22 Comments
 
LVL 18

Expert Comment

by:Johnjces
ID: 22723892
What code do you have in your timer procedure?

You need to put code in there that every 10 seconds the timer fires, checks to see if the time has changed greater or less than 10 seconds, then write to the database and do whatever in your log.

John
0
 
LVL 18

Expert Comment

by:Johnjces
ID: 22723948
I am however not certain why your windows message is not firing in your service. Works in regular win 32 apps....

So, I am at a loss...

john
0
 
LVL 18

Assisted Solution

by:Johnjces
Johnjces earned 100 total points
ID: 22723956
A question,

is your service set to interact with the desktop?
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22724009
no its not set to interact with the desktop. is that the problem?
0
 
LVL 18

Expert Comment

by:Johnjces
ID: 22724040
I am not certain, but it is simple to try it. In this manner you may be able to get a messagebox on success/failure as I recall.

John
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22724271
i think i need to make/declare the service as a system process maybe. how do i do that?
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22724852
also,..on a different but related note,...from a dos window when i installed my service,...i ran:

myService.exe /install

when i look it up in the SCM the name of it is: "Service 1" how do i fix this and give it a better name?
0
 
LVL 14

Expert Comment

by:SteveBay
ID: 22725057
Change the Display Name in the properties of the TService.
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22725237
that worked (the name change), but my service seems to still not be working once i start it. i'm attaching the new code. i did enable that timer (disabled then enabled). originally enabled in the execute.
ServicePas.txt
0
 
LVL 14

Expert Comment

by:SteveBay
ID: 22725614
Per John's first suggestion you could do something like this and detect a time change greater than a second. Also this avoids using windows messaging which will not work in Vista anyway.
procedure TSystemSetBack.Timer1Timer(Sender: TObject);

var

  TheTime: TDateTime;

begin

     Timer1.Enabled := False;

     try

     TheTime := Now;
 

     if ((FLastTime + OneSecond) > (TheTime - (Timer1.Interval * OneMillisecond))) and

        (FLastTime < (TheTime - (Timer1.Interval * OneMillisecond) )) then

          FTimeChanged := False

     else

          FTimeChanged := True;
 

     if FTimeChanged then

          begin

          upDateNow.Close;

          upDateNow.Parameters.ParamByName( 'tmNw' ).Value := TheTime;

          upDateNow.Prepared := True;

          upDateNow.ExecSQL;

          end;

     end;

     FLastTime := TheTime;

     except

     end;

     LogData('Hello');

     Timer1.Enabled := True;

end;

Open in new window

0
 
LVL 14

Expert Comment

by:SteveBay
ID: 22725635
Note: Add DateUtils to your uses clause
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 18

Expert Comment

by:Johnjces
ID: 22725647
Ahh, are you using Vista? That will certainly make some differences!

John
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22725706
i'm not currently using vista. i'd be more than willing to use that code in my timer. i still don't think my service is being "recognized" or being connected properly. i can see it in the SCM window as "Started" but no matter what i do to the clock it doesn't do anything. I do have it set to interact with the desktop.
0
 
LVL 14

Expert Comment

by:SteveBay
ID: 22725729
Slight error in the if statement:
     if ((FLastTime + OneSecond) > (TheTime - (Timer1.Interval * OneMillisecond))) and

        (FLastTime < (TheTime - (Timer1.Interval * OneMillisecond) + OneSecond ) ) then

Open in new window

0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22725757
and...i can IncSecond(FLastTime, 1) to add a second  but how do i multiply by one millisecond???
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22725832
nevermind that last question...i didn't know it was a constant in delphi...
0
 
LVL 14

Accepted Solution

by:
SteveBay earned 400 total points
ID: 22725833
Try this code. I put in a service app and tested it. It works for me.
procedure TSystemSetBack.Timer1Timer(Sender: TObject);

var  TheTime: TDateTime;

     LogFile : String;

     LogList : TStringList;

begin

     Timer1.Enabled := False;

     try

     TheTime := Now;
 

     if ((FLastTime + OneSecond) > (TheTime - (Timer1.Interval * OneMillisecond))) and

        (FLastTime < (TheTime - (Timer1.Interval * OneMillisecond) + OneSecond ) ) then

          FTimeChanged := False

     else

          FTimeChanged := True;
 

     if FTimeChanged then

          begin

          LogList := TStringList.Create;

          LogFile := ChangeFileExt(ParamStr(0),'.log');

          if FileExists(LogFile) then

               LogList.LoadFromFile(LogFile);

          LogList.Add(Format('LastTime: %s <> NewTime: %s', [DateTimeToStr(FLastTime), DateTimeToStr(TheTime)]));

          LogList.SaveToFile(LogFile);

          LogList.Free;

          end;

     FLastTime := TheTime;

     except

     end;

     Timer1.Enabled := True;

end;

Open in new window

0
 
LVL 1

Author Closing Comment

by:mikesExpertExchange
ID: 31506412
i'm not sure what i did but the code that Seve gave me worked when i opened/started a new service app. so i awarde him most of the points. i gave john the remainder as i didn't know that i needed to set that property. thanks to all for your time (patience) and efforts...
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 22726348
Firstly, you are missing 1 very important part...

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

Secondly, I don't think services can easily receive windows messages

Thirdly, you should probably be using a thread instead of a TTimer, but if it works, go for it :-)
0
 
LVL 1

Author Comment

by:mikesExpertExchange
ID: 22732182
TheRealLoki: Thanks for that code suggestionsI will implement that code. It seems to take (be able to pickup/listen to )the time change event pretty well. I'm curious about your thread suggestion and would be open to try it if there were some examples. I'm more of a novice to using / coding threads so I'd need some guidance. I'm open to continue this discussion if you are...
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 22753892
receiving broadcast messages when your serviceis set to interactive does not seem to be a problem. but if it were a specific message, then you'd have to do some work.

If the TTimer solution is working, then don't mess with it.
however, here is an example of using a  simple replacement for a TTimer, using a TThread in a service

unit Unit1;
 

interface
 

uses

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

type TReplacementForTimersThread = class(TThread)

  private

    fInterval: integer;

    fOnTimer: TNotifyEvent;

  protected

    procedure Execute; override;

  public

    constructor Create; overload; // you can call the create in many wanys, it is up to you

    constructor Create( Interval_: integer ); overload;

    constructor Create( Interval_: integer; TimerEvent_: TNotifyEvent); overload;

    property OnTimer: TNotifyEvent read fOnTimer write fOnTimer;

    property Interval: integer read fInterval write fInterval;

// synchronized events

    procedure DoOnTimer;

  end;
 

type

  TService1 = class(TService)

    procedure ServiceStart(Sender: TService; var Started: Boolean);

    procedure ServiceStop(Sender: TService; var Stopped: Boolean);

    procedure ServiceExecute(Sender: TService);

  private

    { Private declarations }

    workerthread: TReplacementForTimersThread;

    procedure ThreadTimer(sender: TObject);

  public

    function GetServiceController: TServiceController; override;

    { Public declarations }

  end;
 

var

  Service1: TService1;
 

implementation
 

{$R *.DFM}
 

procedure ServiceController(CtrlCode: DWord); stdcall;

begin

  Service1.Controller(CtrlCode);

end;
 

function TService1.GetServiceController: TServiceController;

begin

  Result := ServiceController;

end;
 

{ TReplacementForTimersThread }
 

constructor TReplacementForTimersThread.Create;

begin

  inherited Create(True);

  FreeOnTerminate := True;

  Interval := 1000;

end;
 

constructor TReplacementForTimersThread.Create(Interval_: integer);

begin

  inherited Create(True);

  FreeOnTerminate := True;

  Interval := Interval_;

end;
 

constructor TReplacementForTimersThread.Create(Interval_: integer; TimerEvent_: TNotifyEvent);

begin

  inherited Create(True);

  FreeOnTerminate := True;

  Interval := Interval_;

  OnTimer := TimerEvent_;

end;
 

procedure TReplacementForTimersThread.DoOnTimer;

begin

  if assigned(fOnTimer) then

    fOnTimer(self);

end;
 

procedure TReplacementForTimersThread.Execute;

begin

  while not terminated do

  try

    sleep(fInterval); // the sleeping part

    if not terminated then Synchronize(DoOnTimer);

  except

    Terminate;

  end;

end;
 

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);

begin

  workerthread := TReplacementForTimersThread.Create( 1000, self.ThreadTimer);

  workerthread.Execute; // start the timer

  Started := True;

end;
 

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);

begin

  workerthread.Terminate;

  workerthread.Waitfor;

end;
 

procedure TService1.ServiceExecute(Sender: TService);

begin

  while not terminated do

    ServiceThread.ProcessRequests(true);

end;
 

procedure TService1.ThreadTimer(sender: TObject);

begin

  beep;

end;
 

end.

Open in new window

0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 22753898
forgot this part

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  workerthread.Terminate;
  workerthread.Waitfor;
  Stopped := True;
end;
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

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

16 Experts available now in Live!

Get 1:1 Help Now