Windows 2000/XP dan 2003 mendukung sesuatu yang disebut "Program Layanan".
(1) Anda dapat berlari tanpa masuk ke sistem.
(2) Memiliki hak istimewa sistem.
Ketika saya sedang mengembangkan proyek set-top box untuk sebuah perusahaan pada tahun 2003, saya menulis unggahan courseware dan layanan media di sini adalah deskripsi tentang cara membuat program layanan dengan Delphi7.
Jalankan Delphi7, pilih file menu-> baru-> Aplikasi Layanan lainnya. kerangka kerja.
(1) DisplayName: Nama tampilan Layanan
(2) Nama: Nama Layanan.
Di sini kami mengubah nilai DisplayName menjadi "Delphi Service Demo" dan nama "Delphiservice". Berlokasi. Layanan dan status saat ini akan ditampilkan. Kembali ke IDE Delphi7.
Paket kami adalah menambahkan jendela utama untuk layanan ini. fungsi.
Faktanya, jangan berpikir bahwa program layanan bekerja di desktop Winlogon. Berdasarkan apa yang harus saya lakukan?
File-> Formulir Baru-Menambahkan jendela dari layanan, menyimpan unit sebagai unit_frmmain, dan mengatur jendela ini untuk dibuat secara manual.
unit unit_main;
antarmuka
penggunaan
Windows, pesan, sysutils, kelas, grafik, kontrol, svcmgr, dialog, unit_frmmain;
jenis
Tdelphiservice = class (tService)
Prosedur ServiceContinue (pengirim: tservice; var lanjutan: boolean);
Prosedur ServiceExecute (pengirim: tservice);
Prosedur ServicePause (pengirim: tservice; var berhenti: boolean);
Prosedur Serviceshutdown (pengirim: TService);
Prosedur ServicestArt (pengirim: tservice; var dimulai: boolean);
Prosedur Servicestop (pengirim: tservice; var berhenti: boolean);
Pribadi
{Deklarasi Pribadi}
publik
Fungsi GetServiceController: TServiceController;
{Deklarasi Publik}
akhir;
var
Delphiservice: Tdelphiservice;
Frmmain: tfrmmain;
Pelaksanaan
{$ R *.dfm}
Prosedur ServiceController (CtrlCode: DWORD);
Mulai
Delphiservice.controller (CtrlCode);
akhir;
fungsi tdelphiservice.getServiceController: tserviceController;
Mulai
Hasil: = ServiceController;
akhir;
Prosedur tdelphiservice.serviceContinue (pengirim: tservice;
Var Lanjutan: Boolean);
Mulai
Saat tidak dihentikan lakukan
Mulai
Tidur (10);
Serviceethread.processRequests (false);
akhir;
akhir;
Prosedur tdelphiservice.serviceEexecute (pengirim: tservice);
Mulai
Saat tidak dihentikan lakukan
Mulai
Tidur (10);
Serviceethread.processRequests (false);
akhir;
akhir;
Prosedur tdelphiservice.servicepause (pengirim: tservice;
var berhenti: boolean);
Mulai
Berhenti: = true;
akhir;
Prosedur tdelphiservice.serviceshutdown (pengirim: tservice);
Mulai
gbcanclose: = true;
Frmmain.free;
Status: = csstopped;
ReportStatus ();
akhir;
Prosedur tdelphiservice.servicestArt (pengirim: tservice;
var mulai: boolean);
Mulai
Dimulai: = true;
Svcmgr.application.createForm (tfrmmain, frmmain);
gbcanclose: = false;
Frmmain.hide;
akhir;
Prosedur tdelphiservice.servicestop (pengirim: tservice;
var berhenti: boolean);
Mulai
Berhenti: = true;
gbcanclose: = true;
Frmmain.free;
akhir;
akhir.
Unit jendela utama adalah sebagai berikut:
unit unit_frmmain;
antarmuka
penggunaan
Windows, pesan, sysutils, varian, kelas, shellapi, grafik, kontrol, formulir,
Dialog, extctrls, stdctrls;
const
Wm_trayicon = wm_user + 1234;
jenis
Tfrmmain = class (tform)
Timer1: timer;
Button1: tbutton;
Prosedur FormCreate (pengirim: Tobject);
Prosedur FormCloseQuery (pengirim: Tobject; var canclose: boolean);
Prosedur Formdestroy (pengirim: TOBJEK);
Prosedur Timer1Timer (Pengirim: Tobject);
Prosedur Button1Click (pengirim: Tobject);
Pribadi
{Deklarasi Pribadi}
Icondata: tnotifyicondata;
prosedur addicontotray;
Prosedur DeliconFromTray;
Prosedur TrayiconMessage (var MSG: TMessage);
Prosedur sysbuttonmsg (var msg: tmessage);
publik
{Deklarasi Publik}
akhir;
var
Frmmain: tfrmmain;
gbcanclose: boolean;
Pelaksanaan
{$ R *.dfm}
Prosedur tfrmmain.FormCreate (pengirim: tobject);
Mulai
FormStyle: = fsstayontop;
SetWindowlong (application.handle, gwl_exstyle, ws_ex_toolwindow);
gbcanclose: = false;
Timer1.Interval: = 1000;
Timer1.enabled: = true;
akhir;
Prosedur tfrmmain.FormCloseQuery (pengirim: tobject; var canclose: boolean);
Mulai
Canclose: = gbcanclose;
Jika tidak membatasi maka
Mulai
Bersembunyi;
akhir;
akhir;
Prosedur tfrmmain.Formdestroy (pengirim: tobject);
Mulai
Timer1.enabled: = false;
DeliconFromTray;
akhir;
Prosedur tfrmmain.addicontotray;
Mulai
Zeromemory (@icondata, sizeof (tnotifyicondata));
Icondata.cbsize: = sizeof (tnotifyicondata);
Icondata.wnd: = handle;
Icondata.uid: = 1;
Icondata.uflags: = nif_message atau nif_icon atau nif_tip;
Icondata.ucallbackMessage: = wm_trayicon;
Icondata.hicon: = application.icon.handle;
Icondata.sztip: = 'Program Demo Layanan Delphi';
Shell_notifyicon (nim_add, @icondata);
akhir;
Prosedur tfrmmain.deliconfromtray;
Mulai
Shell_notifyicon (nim_delete, @icondata);
akhir;
Prosedur tfrmmain.sysbuttonmsg (var msg: tmessage);
Mulai
if (msg.wparam = sc_close) atau
(Msg.wparam = sc_minimize) Kemudian sembunyikan
Lain diwarisi; // Lakukan tindakan default
akhir;
Prosedur tfrmmain.trayiconMessage (var msg: tmessage);
Mulai
if (msg.lparam = wm_lbuttondblclk) lalu tunjukkan ();
akhir;
Prosedur tfrmmain.timer1Timer (pengirim: tobject);
Mulai
Addicontotray;
akhir;
prosedur sendhokkey; stdcall;
var
Hdesk_wl: hdesk;
Mulai
Hdesk_wl: = openDesktop ('winlogon', 0, false, desktop_journalplayback);
if (hdesk_wl <> 0) lalu
if (setthreaddesktop (hdesk_wl) = true) lalu
Postmessage (hwnd_broadcast, wm_hotkey, 0, makelong (mod_alt atau mod_control, vk_delete));
akhir;
Prosedur tfrmmain.button1click (pengirim: tobject);
var
DWTHREADID: DWORD;
Mulai
CreateThread (nil, 0, @sendhokkey, nil, 0, dwthreadid);
akhir;
akhir.
Mengisi kembali:
(1) Untuk program demonstrasi program layanan lebih lanjut, silakan kunjungi URL berikut: http://www.torry.net/pages.php?id=226, yang berisi banyak kode yang menunjukkan cara mengontrol dan mengelola layanan sistem.
(2) Harap diingat: Windows sebenarnya memiliki beberapa desktop. Itu ada di desktop pelindung layar.
(3) Ada juga metode switching dinamis untuk interaksi antara program layanan dan desktop.
unit servicedesktop;
antarmuka
fungsi initservicedesktop: boolean;
prosedur doneservicedesktop;
Pelaksanaan
menggunakan windows, sysutils;
const
DefaultWindowStation = 'WinSta0';
DefaultDesktop = 'default';
var
hwinstasave: hwinsta;
hdesksave: hdesk;
hwinstauser: hwinsta;
hdeskuser: hdesk;
fungsi initservicedesktop: boolean;
var
DWTHREADID: DWORD;
Mulai
DWTHREADID: = getCurrentThreadId;
// Pastikan koneksi ke stasiun jendela layanan dan desktop, dan
// Simpan pegangan mereka.
hwinstasave: = getProcessWindowStation;
hdesksave: = getThreaddesktop (dwthreadid);
hwinstauser: = OpenWindowStation (defaultWindowStation, false, maximum_allowed);
Jika hwinstauser = 0 lalu
Mulai
OutputDebugString (pchar ('OpenWindowStation gagal' + syserrorMessage (getlasterror))));
Hasil: = false;
KELUAR;
akhir;
Jika tidak setProcessWindowStation (hwinstauser)
Mulai
OutputDebugString ('SetProcessWindowStation gagal');
Hasil: = false;
KELUAR;
akhir;
hdeskuser: = openDesktop (defaultDesktop, 0, false, maximum_allowed);
Jika hdeskuser = 0 lalu
Mulai
OutputDebugString ('Opendesktop Gagal');
SetProcessWindowStation (hwinstasave);
CloseWindowStation (HwinStauser);
Hasil: = false;
KELUAR;
akhir;
Hasil: = setThreaddesktop (hdeskuser);
Jika tidak hasilnya
OutputDebugString (pchar ('setThreaddesktop' + syserrorMessage (getlasterror))));
akhir;
prosedur doneservicedesktop;
Mulai
// Kembalikan stasiun jendela dan desktop.
SetThreaddesktop (hdesksave);
SetProcessWindowStation (hwinstasave);
Jika hwinstauser <> 0 lalu
CloseWindowStation (HwinStauser);
Jika hdeskuser <> 0 lalu
Closedesktop (hdeskuser);
akhir;
Inisialisasi
Initservicedesktop;
Finalisasi
Doneservicedesktop;
akhir.
Untuk kode demonstrasi lebih rinci, silakan merujuk ke: http://www.torry.net/samples/samples/os/isarticle.zip
(4) Cara menambahkan deskripsi layanan tentang cara menginstal layanan. Kami baru saja berlokasi di HKEY_LOCAL_MACHINE/SISTEM/CONTROLSET001. berikut:
unit winsvcex;
antarmuka
menggunakan windows, winsvc;
const
//
// Level Info Konfigurasi Layanan
//
Service_config_description = 1;
Service_config_failure_actions = 2;
//
// DLL Nama fungsi yang diimpor
//
Advapidll = 'advapi32.dll';
jenis
//
// String Deskripsi Layanan
//
PservicedescripciptiA = ^tservicedescripciptionA;
Pservicedescriptionw = ^tservicedescriptionw;
Pservicedescription = pservicedescripciption;
{$ Externalsym _service_descripciption}
_Service_descripciption = Rekam
LPDescription: PANSICHAR;
akhir;
{$ Externalsym _service_descriptionw}
_Service_descriptionw = Rekam
LPDescription: PWIDECHAR;
akhir;
{$ Externalsym _service_description}
_Service_description = _service_descripciption;
{$ Externalsym service_descripciption}
Service_descripciption = _service_descripciption;
{$ Externalsym service_descriptionw}
Service_descriptionw = _service_descriptionw;
{$ Externalsym service_description}
Service_description = _service_descripciption;
Tservicedescripciption = _service_descripciption;
Tservicedescriptionw = _service_descriptionw;
Tservicedescription = tservicedescripciptionA;
//
// Tindakan untuk melakukan kegagalan layanan
//
{$ Externalsym _sc_action_type}
_Sc_action_type = (sc_action_none, sc_action_restart, sc_action_roBoot, sc_action_run_command);
{$ Externalsym sc_action_type}
Sc_action_type = _sc_action_type;
PServiceAction = ^tserviceAction;
{$ Externalsym _sc_action}
_Sc_action = Rekam
atype: sc_action_type;
Tunda: DWORD;
akhir;
{$ Externalsym sc_action}
Sc_action = _sc_action;
TserviceAction = _sc_action;
PservicefailureactionsA = ^tservicefailureactionsA;
Pservicefailureactionsw = ^tservicefailureactionsw;
Pservicefailureactions = pservicefailureactionsA;
{$ Externalsym _service_failure_actionssa}
_Service_failure_actionssa = Rekam
dwresetperiod: dword;
lprebootmsg: LPSTR;
LPCommand: LPSTR;
CACTIONS: DWORD;
LPSAACTIONS: ^sc_action;
akhir;
{$ Externalsym _service_failure_actionsw}
_Service_failure_actionsw = Rekam
dwresetperiod: dword;
lprebootmsg: lpwstr;
LPCommand: LPWSTR;
CACTIONS: DWORD;
LPSAACTIONS: ^sc_action;
akhir;
{$ Externalsym _service_failure_actions}
_Service_failure_actions = _service_failure_actionsa;
{$ Externalsym service_failure_actionssa}
Service_failure_actionsa = _service_failure_actionssa;
{$ Externalsym service_failure_actionsw}
Service_failure_actionsw = _service_failure_actionsw;
{$ Externalsym service_failure_actions}
Service_failure_actions = _service_failure_actionsa;
TserviceFailureactionsA = _service_failure_actionsa;
TserviceFailureactionsw = _service_failure_actionsw;
Tservicefailureactions = tservicefailureactionsA;
////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////
// prototipe fungsi API
////////////////////////////////////////////////// ////////////////////////////////////////////////// ////////
TqueryServiceConfig2 = fungsi (hService: sc_handle; dwinfolevel: dword; lpbuffer: pointer;
CBBUFSIZE: DWORD;
TchangeserviceConfig2 = fungsi (hService: sc_handle; dwinfolevel: dword; lpinfo: pointer): bool;
var
hdll: thandle;
Libloaded: Boolean;
var
Osversioninfo: tosversioninfo;
{$ Externalsym queryserviceConfig2a}
QueryserviceConfig2a: tQueryServiceConfig2;
{$ ExternalSym QueryServiceConfig2W}
QueryServiceConfig2W: TQueryServiceConfig2;
{$ Externalsym queryserviceConfig2}
QueryserviceConfig2: tqueryserviceConfig2;
{$ ExternalSym ChangeserviceConfig2a}
ChangeserviceConfig2a: tchangeserviceConfig2;
{$ ExternalSym ChangeserviceConfig2W}
ChangeserviceConfig2w: tchangeserviceConfig2;
{$ ExternalSym ChangeserviceConfig2}
ChangeserviceConfig2: tchangeserviceConfig2;
Pelaksanaan
Inisialisasi
Osversioninfo.dwosversioninfosize: = sizeof (osversionInfo);
GetVersionex (osversioninfo);
if (osversioninfo.dwplatformId = ver_platform_win32_nt) dan (osversioninfo.dwmajorversion> = 5) lalu
Mulai
Jika hdll = 0 lalu
Mulai
hdll: = getModuleHandle (advapidll);
Libloaded: = false;
Jika hdll = 0 lalu
Mulai
hdll: = loadLibrary (advapidll);
Libloaded: = true;
akhir;
akhir;
Jika hdll <> 0 lalu
Mulai
@QueryserviceConfig2a: = getProcaddress (hdll, 'queryserviceConfig2a');
@QueryserviceConfig2w: = getProcaddress (hdll, 'queryserviceConfig2w');
@QueryServiceConfig2: = @queryServiceConfig2a;
@ChangeserviceConfig2a: = getProcaddress (hdll, 'ChangeserviceConfig2a');
@ChangeserviceConfig2w: = getProcaddress (hdll, 'ChangeserviceConfig2w');
@ChangeserviceConfig2: = @ChangeserviceConfig2a;
akhir;
akhir
kalau tidak
Mulai
@QueryserviceConfig2a: = nil;
@QueryserviceConfig2w: = nil;
@QueryserviceConfig2: = nil;
@ChangeserviceConfig2a: = nil;
@ChangeserviceConfig2w: = nil;
@ChangeserviceConfig2: = nil;
akhir;
Finalisasi
if (hdll <> 0) dan libloaded kemudian
Freelibrary (hdll);
akhir.
Unit WinntService;
antarmuka
penggunaan
Windows, Winsvc, WinsvCex;
fungsi installservice (const strserviceName, strdisplayname, strdescription, strfileName: string): boolean;
// misalnya: installservice ('nama layanan', 'nama tampilan', 'informasi deskripsi', 'file layanan');
Prosedur uninstallservice (strserviceName: string);
Pelaksanaan
fungsi strlcopy (dest: pchar; const Sumber: pchar; maxlen: cardinal): pchar;
Asm
Dorong EDI
Dorong ESI
Dorong EBX
Mov esi, eax
MOV EDI, Edx
MOV EBX, ECX
Xor al, AL
Uji ECX, ECX
JZ @@ 1
Repne scasb
Jne @@ 1
INC ECX
@@ 1: Sub EBX, ECX
MOV EDI, ESI
MOV ESI, Edx
MOV EDX, EDI
MOV ECX, EBX
SHR ECX, 2
Rep movsd
MOV ECX, EBX
Dan ECX, 3
Rep movsb
Stosb
MOV EAX, Edx
Pop Ebx
Pop Esi
Pop Edi
akhir;
fungsi strpchar (dest: pchar; const sumber: string): pchar;
Mulai
Hasil: = strlcopy (dest, pchar (sumber), panjang (sumber));
akhir;
fungsi installservice (const strserviceName, strdisplayname, strdescription, strfileName: string): boolean;
var
// ss: tservicestatus;
// PSTEMP: PCHAR;
HSCM, HSCS: Thandle;
SRVDESC: Pservicedescription;
desc: string;
// SRVType: DWORD;
LPSERVICEARGVECTOR: PCHAR;
Mulai
Hasil: = false;
// pStemp: = nil;
// srvType: = service_win32_own_process dan service_interactive_process;
HSCM: = OpenScManager (nil, nil, sc_manager_all_access); // hubungkan database layanan
jika hscm = 0 maka keluar; // pesan pesan (hhandle, pchar (syserrorMessage (getlasterror)), 'manajer program layanan', mb_iconerror+mb_topmost);
HSCS: = CreateService (// Buat fungsi layanan
HSCM, // Pegangan Manajemen Kontrol Layanan
Pchar (strservicename), // nama layanan
Pchar (strdisplayname), // nama layanan ditampilkan
Service_all_access, // hak akses
Service_win32_own_process atau service_interactive_process, // type service service_win32_share_process
Service_auto_start, // jenis startup
Service_error_ignore, // jenis kontrol kesalahan
PCHAR (Strfilename), // Program Layanan
nil, // nama layanan grup
nil, // ID grup
nil, // layanan dependen
nil, // Mulai akun layanan
nil); // Mulailah kata sandi layanan
jika hscs = 0 maka keluar; // pesan pesan (hHandle, pchar (syserrorMessage (getlasterror)), pchar (application.title), mb_iconerror+mb_topmost);
Jika ditugaskan (ChangeNerViceConfig2) lalu
Mulai
desc: = copy (strdescription, 1.1024);
GetMem (srvdesc, sizeof (tservicedescription));
GetMem (srvdesc^.lpdescription, length (desc) + 1);
mencoba
Strpcopy (srvdesc^.lpdescription, desc);
ChangeserviceConfig2 (HSCS, service_config_description, srvdesc);
Akhirnya
Freemem (srvdesc^.lpdescription);
Freemem (srvdesc);
akhir;
akhir;
LPServiceArgvectors: = nil;
Jika tidak startStervice (HSCS, 0, LPServiceArgvectors) lalu // Mulai Layanan
Keluar;
CloseServiceHandle (HSCS);
Hasil: = true;
akhir;
Prosedur uninstallservice (strserviceName: string);
var
ScManager: sc_handle;
Layanan: SC_HANDLE;
Status: Tservicestatus;
Mulai
ScManager: = OpenScManager (nil, nil, sc_manager_all_access);
Jika scManager = 0 maka keluar;
mencoba
Layanan: = OpenService (ScManager, PCHAR (StrserviceName), service_all_access);
ControlService (layanan, service_control_stop, status);
Deleteservice (layanan);
CloseServiceHandle (layanan);
Akhirnya
CloseServiceHandle (scManager);
akhir;
akhir;
akhir.
(5) Bagaimana cara menutup program layanan secara brutal dan mewujudkan fungsi "NT Toolbox" kami sebelumnya?
menggunakan tlhelp32;
function killTask (exeFileName: string): integer;
const
Proses_Terminate = $ 0001;
var
Continueloop: Bool;
Fsnapshothandle: Thandle;
FProcessEntry32: tprocessEntrry32;
Mulai
Hasil: = 0;
Fsnapshothandle: = createToolHelp32snapshot (th32cs_snapprocess, 0);
FprocessEntry32.dwsize: = sizeof (fProcessEntry32);
Continueloop: = Process32First (fsnapshothandle, fprocessEntry32);
Sedangkan integer (continueloop) <> 0 do
Mulai
if ((Uppercase (ExtractFileName (fProcessEntry32.szexefile)) =
Uppercase (exefilename)) atau (Uppercase (fProcessEntry32.szexefile) =
Uppercase (ExeFileName)) Lalu
Hasil: = integer (terminateProcess (
OpenProcess (Process_Terminate,
Bool (0),
FprocessEntry32.th32processid),
0));
Continueloop: = Process32Next (fsnapshothandle, fprocessEntry32);
akhir;
CloseHandle (fsnapshothandle);
akhir;
Namun, untuk program layanan, itu akan meminta "akses ditolak".
Fungsi EnabledebugPrivilege: Boolean;
fungsi enablePrivilege (htoken: cardinal; privname: string; benable: boolean): boolean;
var
TP: token_privileges;
Dummy: Kardinal;
Mulai
Tp.privilegecount: = 1;
Lookupprivilegevalue (nil, pchar (privname), tp.privileges [0] .luid);
Jika BENABLE maka
Tp.privileges [0] .attributes: = se_privilege_enabled
lain tp.privileges [0] .attributes: = 0;
AdjustTokenPrivileges (htoken, false, tp, sizeof (tp), nil, dummy);
Hasil: = getlasterror = error_success;
akhir;
var
HToken: Kardinal;
Mulai
OpenProcessToken (getCurrentProcess, token_adjust_privileges, htoken);
Hasil: = EnablePrivilege (htoken, 'SedebugPrivilege', true);
CloseHandle (htoken);
akhir;
Bagaimana menggunakan:
EnabledebugPrivilege; // Tingkatkan izin
KillTask ('xxxx.exe'); // Tutup program layanan.
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------ ----------