?
Solved

Help creating a service.

Posted on 2002-07-06
9
Medium Priority
?
391 Views
Last Modified: 2010-04-04
I have added a question :
http://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=delphi&qid=20303736

I don't think that it should be so hard but I didn't got any complete answer.

What I like to do is to create backups of a file if it has been changed.

For exaple say the file
c:\test.tmp

When the service starts I like to make a copy of c:\test.tmp
into

c:\tmp\2002-07-06\10-02-11.tmp

where '2002-07-06 is the current date
and 10-02-11 is the current time. (10:02:54)

then I want the service to check every 10 minute if
the file c:\test.tmp has been changed since the last backup. if so I like to make a new copy
(with a correct name in the same way as before.)

If possible I like to have it that way that the file is not locked for other programs during the copy.

Can someone help me out with this.

0
Comment
Question by:wqclatre
9 Comments
 
LVL 8

Expert Comment

by:TOndrej
ID: 7133562
What do you need help with?
0
 

Expert Comment

by:deansmith
ID: 7133576
hi,

I think you need to be more specfic here. Do you want someone to create the service for you or do you want to know how to create a service.

Have you also considered that you will be creating a backup every 10 minutes, 6 backups an hour and 144 backups a day. depending on the size of the file you could run out of disk space very soon. CAn you describe what you are trying to achieve because there maybe a better way.

What is being stored in the test.tmp file?


Dean


0
 
LVL 2

Author Comment

by:wqclatre
ID: 7133591
Yes. But I only want to back it up if the file has been changed. And I guess it would not be changed so often.

I think I understand how to create a service (or can figure out) But help with this would be greateful to.

THe thing I can't understand is how to make copy of the file.. how to se if the file has changed. how to create those directories etc etc,.,.

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 2

Author Comment

by:wqclatre
ID: 7133594
the test.tmp file could be anything.
for example a copy of the icq database the seems to get broken for me every now and then....
0
 
LVL 17

Expert Comment

by:geobul
ID: 7133657
Hi,
Using 'File-New-Service Application' create a new app, drop a timer, set its interval to 600000 (10 min) and use the code below.

Save and build the app. Using 'Start button-Run' execute:
path\exename.exe /install
You will see something like: Service was installed successfully

Open the 'services' window, select your service, make it logon on system account and start it.

Regards, Geo
-----
unit Unit1;

interface

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

type
  TGeoService = class(TService)
    Timer1: TTimer;
    procedure ServiceExecute(Sender: TService);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  GeoService: TGeoService;
  MyFileName: string;
  LastTime, NewTime: TDateTime;

implementation

{$R *.DFM}

uses FileCtrl, ShellApi;

function HasAttr(const FileName: string; Attr: Word): Boolean;
begin
  Result := (FileGetAttr(FileName) and Attr) = Attr;
end;

procedure CopyFile(const FileName, DestName: TFileName);
var
  CopyBuffer: Pointer; { buffer for copying }
  BytesCopied: Longint;
  Source, Dest: Integer; { handles }
  Destination: TFileName; { holder for expanded destination name }
const
  ChunkSize: Longint = 8192; { copy in 8K chunks }
begin
  Destination := ExpandFileName(DestName);  { expand the destination path }
  GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
  try
    Source := FileOpen(FileName, fmOpenRead or fmShareDenyNone); { open source file }
    if Source < 0 then raise EFOpenError.CreateFmt(SFOpenError, [FileName]);
    try
      Dest := FileCreate(Destination); { create output file; overwrite existing }
      if Dest < 0 then raise EFCreateError.CreateFmt(SFCreateError, [Destination]);
      try
        repeat
          BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk }
          if BytesCopied > 0 then { if we read anything... }
            FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
        until BytesCopied < ChunkSize; { until we run out of chunks }
      finally
        FileClose(Dest); { close the destination file }
      end;
    finally
      FileClose(Source); { close the source file }
    end;
  finally
    FreeMem(CopyBuffer, ChunkSize); { free the buffer }
  end;
end;

function GetFileTimes(const filename: string; var Modified: TDateTime): boolean;
var sr:TSearchRec;
   SysTimeStruct: TSystemTime;
   lft: TFileTime;
begin
 Result:=False;
 if FindFirst(FileName,faAnyFile,sr) = 0 then
 begin
   if FileTimeToLocalFileTime(sr.FindData.ftLastWriteTime, lft) and
      FileTimeToSystemTime(lft, SysTimeStruct) then
      Modified := SystemTimeToDateTime(SysTimeStruct);
   FindClose(sr);
   Result:=True;
 end;
end;

function CopyMyFile: boolean;
var
  NewDir, NewFile: string;
begin
  result := true;
  try
    NewDir := 'c:\tmp\'+ FormatDateTime('yyyy-mm-dd',NewTime);
    NewFile := NewDir + '\' + FormatDateTime('hh-nn-ss',NewTime) + '.tmp';
    ForceDirectories(NewDir);
    if DirectoryExists(NewDir) then begin
      if not FileExists(NewFile) then begin
        CopyFile(MyFileName, NewFile);
      end;
    end;
  except
    result := false;
  end;
end;

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

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

procedure TGeoService.ServiceExecute(Sender: TService);
begin
  // first copy
  MyFileName := 'c:\test.tmp';
  if GetFileTimes(MyFileName, LastTime) then begin
    NewTime := LastTime;
    CopyMyFile;
  end;
  while not Terminated do begin
    ServiceThread.ProcessRequests(False);
  end;
end;

procedure TGeoService.Timer1Timer(Sender: TObject);
begin
  if GetFileTimes(MyFileName, NewTime) then begin
    if NewTime <> LastTime then begin
      CopyMyFile;
      LastTime := NewTime;
    end;
  end;
end;

end.
0
 
LVL 2

Author Comment

by:wqclatre
ID: 7133674
I get

Undeclared Identifier SFOpenError on row 50:

   if Source < 0 then raise EFOpenError.CreateFmt(SFOpenError, [FileName]);
0
 
LVL 17

Expert Comment

by:geobul
ID: 7133677
add Consts to your uses clause. It's declared there.
0
 
LVL 2

Author Comment

by:wqclatre
ID: 7133681
Hm strange.

I have:

Uses
 Windows, Messages, SysUtils, Classes, Consts, Graphics, Controls, SvcMgr, Dialogs,
 ExtCtrls;

type....

I can't find SFOpenError in this unit either.
0
 
LVL 17

Accepted Solution

by:
geobul earned 800 total points
ID: 7133739
It'd be better to rewrite CopyFile procedure in order to skip raising exceptions. If an exception occurs then the file will NOT be copied.

procedure CopyFile(const FileName, DestName: TFileName);
var
 CopyBuffer: Pointer; { buffer for copying }
 BytesCopied: Longint;
 Source, Dest: Integer; { handles }
 Destination: TFileName; { holder for expanded destination name }
const
 ChunkSize: Longint = 8192; { copy in 8K chunks }
begin
 Destination := ExpandFileName(DestName);  { expand the destination path }
 GetMem(CopyBuffer, ChunkSize); { allocate the buffer }
 try
  try
   Source := FileOpen(FileName, fmOpenRead or fmShareDenyNone); { open source file }
   if not (Source < 0) then begin
    try
     Dest := FileCreate(Destination); { create output file; overwrite existing }
     if not (Dest < 0) then begin
      try
       repeat
         BytesCopied := FileRead(Source, CopyBuffer^, ChunkSize); { read chunk }
         if BytesCopied > 0 then { if we read anything... }
           FileWrite(Dest, CopyBuffer^, BytesCopied); { ...write chunk }
       until BytesCopied < ChunkSize; { until we run out of chunks }
      finally
       FileClose(Dest); { close the destination file }
      end;
     end;
    finally
     FileClose(Source); { close the source file }
    end;
   end;
  finally
    FreeMem(CopyBuffer, ChunkSize); { free the buffer }
  end;
 except
   // do nothing
 end;
end;
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
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. …
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses
Course of the Month17 days, 8 hours left to enroll

831 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