Most popular

วันพฤหัสบดีที่ 14 กรกฎาคม พ.ศ. 2554

Delphi กับการสร้าง Windows Service

การสร้าง Windows Service ด้วย Delphi ไม่ว่าจะเป็น Delphi Version ไหนๆ ล้วนแล้วแต่ง่ายๆทั้งสิ้น
ผู้เขียนจะสาธิตด้วยการใช้ Delphi XE ซึ่งเป็น Version ที่ค่อนข้างสมบูรณ์มากไม่แพ้ Delphi 7 และการสร้าง Windows Service ก็เหมือนกับใน Delphi Version อื่นๆ
โดย Service ที่จะสร้างขึ้นมีหน้าที่สลับ Desktop Wallpaper ไปมา เพื่อให้ท่านทำความเข้าใจกับการติดตั้ง และการทำงานของ Windows Service

สร้าง Project ใหม่เป็น Service Application

เลือกเป็น Service Application
ผู้เขียนเปลี่ยนชื่อ Unit1 เป็น serviceXE และกำหนด DisplayName เป็น SwitchWall
Display Name นี่เองที่จะแสดงใน Service List ใน Windows
จากนั้นก็ใส่ Component Timer เข้ามา 2 ตัว ตามภาพด้านบน
โดยตั้งค่าให้ตัว Timer ทั้ง 2 มี Enable = false และ Interval = 2000 (รอบละ 2 วินาที)

จากนั้นให้ Save ทั้งหมดได้เลย 
ในที่นี้ผู้เขียนตั้งชื่อไฟล์เป็น mainService.pas และชื่อ Project คือ SXE 

เขียนคำสั่งในการทำงาน
จากนั้นก็ให้สร้าง method ในการเปลี่ยน Desktop Wallpaper ดังนี้

procedure TserviceXE.setWallpaper(path: String);
var
  PicPath: String;
begin
  PicPath := path;
  SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pChar(PicPath), SPIF_SENDCHANGE);
end;

ผู้เขียนได้มีรูปภาพที่จะใช้เปลี่ยน Desktop Wallpaper อยู่แล้วจำนวน 2 รูป โดยมีชื่อว่า
  1. Kawasaki_ER_6N_2009_31_1024x768.bmp
  2. 2011_Honda_CBR_600F_05.bmp
จากนั้นให้การเปลี่ยน Desktop Wallpaper ทำงานตามรอบการทำงานของ Timer โดยเขียนคำสั่งใน Event OnTimer ดังนี้

procedure TserviceXE.Timer1Timer(Sender: TObject);
begin
   Self.setWallpaper('E:\Kawasaki_ER_6N_2009_31_1024x768.bmp');
   Self.Timer1.Enabled:=false;
   Self.Timer2.Enabled:=true;
end;

procedure TserviceXE.Timer2Timer(Sender: TObject);
begin
   Self.setWallpaper('E:\2011_Honda_CBR_600F_05.bmp');
   Self.Timer1.Enabled:=true;
   Self.Timer2.Enabled:=false;
end;

ต่อไปคือขั้นตอนของการทำงานของ Service ที่จะมี Event ที่สำคัญอย่างมากคือ AfterInstall และ OnStart


คำสั่งใน Event AfterInstall

procedure TserviceXE.ServiceAfterInstall(Sender: TService);
begin
With TRegistry.Create Do
 Begin
  Try
     RootKey := HKEY_LOCAL_MACHINE;
     OpenKey('\SYSTEM\CurrentControlSet\Services\serviceXE\',FALSE);
     WriteInteger('Type',272);
     CloseKey;
  Finally
     Free;
  End;
 end;
end;

คำสั่งภายใน Event AfterInstall นี้เป็นการปรับปรุง Registry หลังจากติดตั้ง Service เสร็จเรียบร้อย
ให้สามารถทำงานกับ Windows Desktop ได้ โดยเฉพาะหากการทำงานของ Service มีความเกี่ยวข้องกับ Application อื่นๆ (ในที่นี้คือ Windows API)

หากไม่ทำการปรับปรุง Registry ของ Service จะต้องทำการตั้งค่าเองเมื่อติดตั้ง Service เสร็จแล้ว ตามภาพด้านล่างนี้ ซึ่งดูไม่เป็นมืออาชีพเอาเสียเลย และในการใช้งานจริงๆ ผู้ใช้ (User) คงจะมีทักษะไม่เพียงพอ

การตั้งค่าเองโดยเข้าที่ไป Properties ของ Service
สุดท้ายคือ การให้ Timer เริ่มทำงานเมื่อ Service ถูก Start ขึ้น

procedure TserviceXE.ServiceStart(Sender: TService; var Started: Boolean);
begin
  Self.Timer1.Enabled:=true;
end;

จากนั้นให้ทำการ Compile และ Build Project ได้เลย หากไม่มี Error ก็พร้อมที่จะนำ Service ไปติดตั้งแล้ว

การติดตั้ง Windows Service
เมื่อ Build Project แล้วจะได้ไฟล์ .exe ชื่อเดียวกับ Project เหมือนกับการสร้าง Application ปกติ
ให้รันของ Windows หรือใช้ Command Line ในการติดตั้ง Service โดยมีรูปแบบคือ

"Service Application.exe path"  /install
"Service Application.exe path"  /install
เมื่อติดตั้งแล้วให้ตรวจสอบรายชื่อ Windows Service ว่าได้ติดตั้งเรียบร้อยหรือไม่
โดยเข้าไปที่ Control Panel > Administrative Tools > Services

Service "serviceXE" ที่เพิ่งติดตั้ง
เมื่อ Re Start เครื่อง หรือเปิดเครื่องใหม่ครั้งต่อไป Service ที่ได้ติดตั้งไปก็จะทำงานทันที

ภาพ Desktop Wallpaper ที่เปลี่ยนไป
หมายเหตุ
การถอนการติดตั้งของ Windows Service ให้ทำการปิด Service ก่อน และใช้รันของ Windows หรือ Command Line เหมือนเดิมแต่เปลี่ยนจาก /install เป็น /uninstall เช่น "Service Apllication Path.exe"  /uninstall

"Service Apllication Path.exe"  /uninstall
Code ทั้งหมด


unit mainService;


interface


uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  DBXDataSnap, DBXCommon, DB, SqlExpr, ExtCtrls,registry;


type
  TserviceXE = class(TService)
    Timer1: TTimer;
    Timer2: TTimer;
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceAfterInstall(Sender: TService);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    procedure setWallpaper(path: String);
    { Public declarations }
  end;


var
  serviceXE: TserviceXE;


implementation


{$R *.DFM}


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


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


procedure TserviceXE.ServiceAfterInstall(Sender: TService);
begin
With TRegistry.Create Do
 Begin
  Try
     RootKey := HKEY_LOCAL_MACHINE;
     OpenKey('\SYSTEM\CurrentControlSet\Services\serviceXE\',FALSE);
     WriteInteger('Type',272);
     CloseKey;
  Finally
     Free;
  End;
 end;
end;


procedure TserviceXE.ServiceStart(Sender: TService; var Started: Boolean);
begin
  Self.Timer1.Enabled:=true;
end;


procedure TserviceXE.setWallpaper(path: String);
var
  PicPath: String;
begin
  PicPath := path;
  SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pChar(PicPath), SPIF_SENDCHANGE);
  Self.Timer1.Enabled:=false;


end;


procedure TserviceXE.Timer1Timer(Sender: TObject);
begin
   Self.setWallpaper('E:\Kawasaki_ER_6N_2009_31_1024x768.bmp');
   Self.Timer1.Enabled:=false;
   Self.Timer2.Enabled:=true;
end;


procedure TserviceXE.Timer2Timer(Sender: TObject);
begin
   Self.setWallpaper('E:\2011_Honda_CBR_600F_05.bmp');
   Self.Timer1.Enabled:=true;
   Self.Timer2.Enabled:=false;
end;


end.

ไม่มีความคิดเห็น:

แสดงความคิดเห็น