Solved

novice Service writer

Posted on 2008-10-15
22
272 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 
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
 
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

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Suggested Courses
Course of the Month6 days, 17 hours left to enroll

623 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