O Windows 2000/XP e 2003 suportam algo chamado "Programas de serviço".
(1) Você pode ser executado sem fazer login no sistema.
(2) Ter privilégios do sistema.
Quando eu estava desenvolvendo um projeto de caixa de configuração para uma empresa em 2003, escrevi uploads de cursos e serviços de mídia.
Execute o Delphi7, selecione o arquivo de menu-> novo-> OUTRA ---> APLICAÇÃO DE SERVIÇO. Estrutura.
(1) DisplayName: o nome da exibição do serviço
(2) Nome: Nome do serviço.
Aqui, alteramos o valor do DisplayName para "Demo de serviço Delphi" e o nome para "Delphiservice". está localizado. Serviço e status atual serão exibidos. Volte ao IDE de Delphi7.
Nosso plano é adicionar uma janela principal para este serviço. função.
De fato, não pense que o programa de serviço funcione no WinLogon Desktop. Marcado.
Arquivo-> Novo-> Formulário adiciona uma janela FRMMAIN ao serviço, salva a unidade como unit_frmmin e define esta janela a ser criada manualmente.
unidade unit_main;
interface
usos
Windows, mensagens, sysutils, classes, gráficos, controles, svcmgr, diálogos, unit_frmMain;
tipo
Tdelphiservice = classe (tService)
Procedimento ServiceContinue (remetente: tService; VAR continuação: booleano);
Procedimento ServiceExecute (remetente: tService);
Procedimento ServicePause (remetente: tService; var pausado: booleano);
Procedimento ServiceShutDown (remetente: tService);
Procedimento Servicestart (remetente: tService; var iniciado: booleano);
Procedimento ServiceStop (remetente: tService; var parado: booleano);
Privado
{Declarações privadas}
público
função getServiceController: tServiceController;
{Declarações públicas}
fim;
var
Delphiservice: Tdelphiservice;
FRMMAIN: TfrMMain;
Implementação
{$ R *.dfm}
Procedimento ServiceController (CtrlCode: DWORD);
Começar
DelphMervice.Controller (CtrlCode);
fim;
função tdelphiseService.getServiceController: tServiceController;
Começar
Resultado: = serviceController;
fim;
procedimento tdelphiservice.ServiceContinue (remetente: tService;
Var continuado: booleano);
Começar
Embora não seja encerrado, faça
Começar
Sono (10);
ServiceThread.processRequests (false);
fim;
fim;
procedimento tdelphiseService.ServiceExecute (remetente: tService);
Começar
Embora não seja encerrado, faça
Começar
Sono (10);
ServiceThread.processRequests (false);
fim;
fim;
procedimento tdelphiservice.ServicePause (remetente: tService;
var pausado: booleano);
Começar
Parado: = true;
fim;
procedimento tdelphiservice.Serviceshutdown (remetente: tService);
Começar
gbCanclose: = true;
FrmMain.Free;
Status: = csstopped;
RelationStatus ();
fim;
procedimento tdelphiservice.Servicestart (remetente: tService;
Var iniciado: booleano);
Começar
Iniciado: = true;
Svcmgr.application.creatEform (tfrmmAin, frmMain);
gbCanclose: = false;
FrmMain.hide;
fim;
procedimento tdelphiservice.servicestop (remetente: tService;
var parado: booleano);
Começar
Parado: = true;
gbCanclose: = true;
FrmMain.Free;
fim;
fim.
A unidade de janela principal é a seguinte:
unidade unit_frmMain;
interface
usos
Janelas, mensagens, sysutils, variantes, classes, shellapi, gráficos, controles, formulários,
Diálogos, extctrls, stdctrls;
const
Wm_trayicon = wm_user + 1234;
tipo
TfrmMain = classe (tform)
Timer1: ttimer;
Button1: tbutton;
Procedimento FormCreate (remetente: Tobject);
Procedimento formCloseQuery (remetente: TOBJECT; VAR CALCLOSE: Boolean);
procedimento formDestroy (remetente: tabjas);
Procedimento Timer1timer (remetente: tabjas);
Procedimento Button1Click (remetente: Tobject);
Privado
{Declarações privadas}
Icondata: tnotifyicondata;
Procedimento Addicontotray;
Procedimento DeliconFromtray;
Procedimento TrayiconMessage (var msg: tMessage);
Procedimento sysbuttonmsg (var msg: tmessage);
público
{Declarações públicas}
fim;
var
FRMMAIN: TfrMMain;
gbcanclose: booleano;
Implementação
{$ R *.dfm}
procedimento tfrmMain.formCreate (remetente: tabjas);
Começar
FormStyle: = fsStayOntop;
SetWindowlong (Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWindow);
gbCanclose: = false;
Timer1.Interval: = 1000;
Timer1.enabled: = true;
fim;
procedimento tfrmMain.formCloseQuery (remetente: TObject; var canclose: boolean);
Começar
CanClose: = gbCanclose;
Se não cancelar então
Começar
Esconder;
fim;
fim;
procedimento tfrmmAin.formDestroy (remetente: tabjas);
Começar
Timer1.enabled: = false;
Deliconfromtray;
fim;
procedimento tfrmmAin.addicontotray;
Começar
Zeromemory (@icondata, sizeof (tnotifyicondata));
Icondata.cbsize: = sizeof (tnotifyicondata);
Icondata.Wnd: = Handle;
Icondata.uid: = 1;
Icondata.uflags: = nif_message ou nif_icon ou nif_tip;
Icondata.ucallbackMessage: = wm_trayicon;
Icondata.hicon: = Application.icon.handle;
Icondata.sztip: = 'Programa de demonstração de serviço Delphi';
Shell_notifyicon (nim_add, @icondata);
fim;
procedimento tfrmmAin.deliconFromtray;
Começar
Shell_notifyicon (nim_delete, @icondata);
fim;
procedimento tfrmmAin.sysButtonmsg (var msg: tmessage);
Começar
if (msg.wparam = sc_close) ou
(Msg.wparam = sc_minimize) depois ocultar
else herdado;
fim;
procedimento tfrmmAin.TrayiconMessage (var msg: tMessage);
Começar
if (msg.lparam = wm_lbuttondblclk) então show ();
fim;
procedimento tfrmMain.timer1timer (remetente: tabjas);
Começar
Addicontotray;
fim;
procedimento sendHokkey; stdcall;
var
Hdesk_wl: hdesk;
Começar
Hdesk_wl: = opendesktop ('winlogon', 0, false, desktop_journalplayback);
if (hdesk_wl <> 0) então
if (setThreadDesktop (hdesk_wl) = true) então
PostMessage (hwnd_broadcast, wm_hotkey, 0, makelong (mod_alt ou mod_control, vk_delete));
fim;
procedimento tfrmMain.button1Click (remetente: tabjas);
var
dwthreadId: dword;
Começar
CreateThread (nil, 0, @sendhokkey, nil, 0, dwthreadId);
fim;
fim.
Reabastecer:
(1) Para mais programas de demonstração de programas de serviço, visite o seguinte URL: http://www.torry.net/pages.php?id=226, que contém vários códigos que demonstram como controlar e gerenciar serviços do sistema.
(2) Lembre -se: o Windows realmente tem vários desktops. Ele está no desktop do protetor de tela.
(3) Há também um método de comutação dinâmica para interação entre o programa de serviço e a área de trabalho.
Unidade Serviços de Atenção;
interface
função initServicedesktop: booleano;
procedimento DoneServicedesktop;
Implementação
usa janelas, sysutils;
const
DefaultWindowStation = 'winsta0';
DefaultDesktop = 'padrão';
var
Hwinstasave: Hwinsta;
Hdesksave: HDESK;
HwinstaUser: Hwinsta;
HDESKUSER: HDESK;
função initServicedesktop: booleano;
var
dwthreadId: dword;
Começar
dwthreadId: = getCurrentThReadId;
// Garanta a conexão com a estação de janela e a área de trabalho, e
// Salve suas alças.
hwinstasave: = getProcessWindowStation;
hdeskSave: = getThreadDesktop (dwthreadId);
hwinstaUser: = OpenWindowStation (defaultWindowStation, false, maximum_allowed);
Se hwinstauser = 0 então
Começar
OutputDeBugString (PChar ('OpenWindowStation falhou' + SySerRormessage (getLasterRor)));
Resultado: = false;
saída;
fim;
Se não for SetProcessWindowStation (HwinstaUser), então
Começar
OutputDebugString ('SetProcessWindowStation falhou');
Resultado: = false;
saída;
fim;
hdeskuser: = opendesktop (defaultdesktop, 0, false, maximum_allowed);
Se hdeskuser = 0 então
Começar
OutputDebugString ('Opendesktop falhou');
SetProcessWindowStation (Hwinstasave);
CloseWindowStation (HwinstaUser);
Resultado: = false;
saída;
fim;
Resultado: = setThreadDesktop (hdeskuser);
Se não resultar então
OutputDebugString (PChar ('SetThreadDesktop' + sySerRormessage (getLasterror)));
fim;
procedimento DoneServicedesktop;
Começar
// Restaurar a estação de janela e a área de trabalho.
SetThreaddesktop (hdesksave);
SetProcessWindowStation (Hwinstasave);
Se hwinstauser <> 0 então
CloseWindowStation (HwinstaUser);
Se hdeskuser <> 0 então
Fechesktop (Hdeskuser);
fim;
Inicialização
InitServicedesktop;
Finalização
DoneServicedesktop;
fim.
Para um código de demonstração mais detalhado, consulte: http://www.torry.net/samples/samples/os/isarticle.zip
(4) Como adicionar descrições de serviço sobre como instalar um serviço. Agora está localizado em HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001. segue:
unidade winsvcex;
interface
usa Windows, Winsvc;
const
//
// Níveis de informação de configuração de serviço
//
Service_config_description = 1;
Service_config_failure_actions = 2;
//
// Nome da DLL das funções importadas
//
Advapidll = 'advapi32.dll';
tipo
//
// String de descrição de serviço
//
PServicedEscriptiona = ^tServicedDescriptiona;
PServicedEscriptionW = ^tServicedEscriptionw;
PSERVICEDescription = PSERVICEDescriptiona;
{$ Externalsym _service_descriptiona}
_Service_descriptiona = registro
LPDescription: Pansichar;
fim;
{$ ExternalSym _service_descriptionw}
_Service_descriptionw = registro
LPDescription: pwidechar;
fim;
{$ Externalsym _service_description}
_Service_description = _service_descriptiona;
{$ ExternalSym Service_Descriptiona}
Service_Descriptiona = _service_Descriptiona;
{$ ExternalSym Service_DescriptionW}
Service_DescriptionW = _Service_DescriptionW;
{$ ExternalSym Service_Description}
Service_Description = _service_Descriptiona;
TServicedDescriptiona = _service_Descriptiona;
TServicedEScriptionW = _service_DescriptionW;
TServicedEScription = tServicedDescriptiona;
//
// ações a serem executadas na falha do serviço
//
{$ Externalsym _sc_action_type}
_Sc_action_type = (sc_action_none, sc_action_restart, sc_action_reboot, sc_action_run_command);
{$ Externalsym sc_action_type}
Sc_action_type = _sc_action_type;
PSERVICEACTION = ^TSERVICEACTION;
{$ Externalsym _sc_action}
_Sc_action = registro
atype: sc_action_type;
Atraso: DWORD;
fim;
{$ Externalsym sc_action}
Sc_action = _sc_action;
TServiceAction = _SC_Action;
PServiceFailureActionsa = ^TServiceFailureActionsa;
PServiceFailureActionSw = ^tServiceFailurEactionSw;
PServiceFailureActions = PServiceFailureActionsa;
{$ Externalsym _service_failure_actana}
_Service_failure_AchaSA = registro
dresetperiod: dword;
lprebootmsg: lpstr;
LPCommand: lpstr;
Ações: DWORD;
lpsaActions: ^sc_action;
fim;
{$ ExternalSym _service_failure_actionsw}
_Service_failure_actionsw = registro
dresetperiod: dword;
lprebootmsg: lpwstr;
LPCommand: LPWSTR;
Ações: DWORD;
lpsaActions: ^sc_action;
fim;
{$ ExternalSym _service_failure_Actions}
_Service_failure_Actions = _service_failure_Acsa;
{$ ExternalSym Service_failure_AchaSA}
Service_failure_AchaSA = _service_failure_Acsa;
{$ ExternalSym Service_failure_ActionSw}
Service_failure_actionsw = _service_failure_actionsw;
{$ ExternalSym Service_failure_Actions}
Service_failure_Actions = _service_failure_Acsa;
TServiceFailureActionsa = _service_failure_Actsa;
TServiceFailureActionSw = _service_failure_actionSw;
TServiceFailureActions = tServiceFailureActionsa;
/////////////////////////////////////////////////////////Tipos /////////////////////////////////////////////////////////Tipos /////////
// protótipos de função da API
/////////////////////////////////////////////////////////Tipos /////////////////////////////////////////////////////////Tipos /////////
TQUERYSERVICECONFIG2 = FUNÇÃO (HSERVICE: SC_HANDLE; DWINFOLEVEL: DWORD; LPBUFFER: POINTER;
CBBUFSIZE: DWORD;
TCHANGESERVICECONFIG2 = função (hservice: sc_handle; dwinfolevel: dword; lpinfo: ponteiro): bool;
var
HDLL: THANDLE;
Libloaded: booleano;
var
OsversionInfo: TosversionInfo;
{$ ExternalSym QueryServiceConfig2a}
QueryServiceConfig2a: TQUERYSERVICECONFIG2;
{$ ExternalSym QueryServiceConfig2W}
QueryServiceConfig2W: TQUERYSERVICECONFIG2;
{$ ExternalSym QueryServiceConfig2}
QueryServiceConfig2: TQUERYSERVICECONFIG2;
{$ ExternalSym ChangeServiceConfig2a}
Alterações de alteraçãoConfig2a: tChangServiceConfig2;
{$ ExternalSym alterações serviceconfig2w}
Alterações de alteraçãoConfig2w: tcHangServiceConfig2;
{$ ExternalSym alterações serviceconfig2}
Alterações de alteraçãoConfig2: tChangServiceConfig2;
Implementação
Inicialização
OsversionInfo.dwosversionInfosize: = sizeof (OsversionInfo);
GetversionEx (OsversionInfo);
if (OsversionInfo.dwplatformid = ver_platform_win32_nt) e (OsversionInfo.dwmajorversion> = 5) então
Começar
Se hdll = 0 então
Começar
hdll: = getModuleHandle (advapidll);
Libloaded: = false;
Se hdll = 0 então
Começar
hdll: = loadlibrary (advapidll);
Libloaded: = true;
fim;
fim;
Se hdll <> 0 então
Começar
@QueryServiceConfig2a: = getProcaddress (hdll, 'queryServiceConfig2a');
@QueryServiceConfig2W: = getProcaddress (hdll, 'queryServiceConfig2w');
@QueryServiceConfig2: = @QueryServiceConfig2a;
@Alterações de alteraçãoConfig2a: = getProcAddress (hdll, 'alterações de alteraçãoConfig2a');
@Alterações de alteraçãoConfig2w: = getProcaddress (hdll, 'alterações
@Alterações serviceConfig2: = @alterações serveconfig2a;
fim;
fim
outro
Começar
@QueryServiceConfig2a: = nil;
@QueryServiceConfig2w: = nil;
@QueryServiceConfig2: = nil;
@Alterações serviceConfig2a: = nil;
@Alterações serviceconfig2w: = nil;
@Alterações serviceConfig2: = nil;
fim;
Finalização
if (hdll <> 0) e libered então
Freelibrary (HDLL);
fim.
Unidade WinntService;
interface
usos
Windows, Winsvc, Winsvcex;
função installService (const strServicename, strDisplayName, strDescription, strfilename: string): boolean;
// por exemplo: installService ('Nome do serviço', 'Nome da exibição', 'Informações de descrição', 'arquivo de serviço');
procedimento desinstallService (StrServicename: string);
Implementação
função strlcopy (dest: pchar; const fonte: pchar; maxlen: cardeal): pchar;
ASM
Empurre edi
Empurre ESI
Empurre EBX
Mov Esi, Eax
Mov Edi, Edx
Mov ebx, ecx
XOR AL, AL
Teste 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
Representante movsd
Mov ecx, ebx
E ECX, 3
Rep Movsb
Stosb
Mov Eax, Edx
Pop ebx
Pop esi
Pop edi
fim;
função strpchar (dest: pchar; const fonte: string): pchar;
Começar
Resultado: = strlcopy (dest, pchar (fonte), comprimento (fonte));
fim;
função installService (const strServicename, strDisplayName, strDescription, strfilename: string): boolean;
var
// ss: tServicestatus;
// PSTEMP: PCHAR;
HSCM, HSCs: THANDLE;
SRVDESC: PSERVICEDescription;
Desc: string;
// srvtype: dword;
LPServiceargVectors: PChar;
Começar
Resultado: = false;
// PSTemp: = nil;
// srvtype: = service_win32_own_process e serviço_interactive_process;
HSCM: = OpenScManager (nil, nil, sc_manager_all_access); // conectar o banco de dados de serviço
se hscm = 0, então exit; // messagebox (hhandle, pchar (syserrormessage (getlasterror)), 'gerente de programa de serviço', mb_iconerror+mb_top mais);
HSCs: = CreateService (// Crie função de serviço
HSCM, // identificador de gerenciamento de controle de serviço
PCHA (nome de StrServicen), // Nome do serviço
Pchar (strDisplayName), // o nome do serviço exibido
Service_all_access, // direitos de acesso
Service_win32_own_process ou Service_Interactive_process, // Tipo de serviço Service_win32_share_process
Service_auto_start, // Tipo de inicialização
Service_error_ignore, // Tipo de controle de erro
Pchar (strfileName), // Programa de serviço
nil, // Nome do serviço de grupo
nil, // ID do grupo
nil, // Serviços dependentes
nil, // Inicie a conta de serviço
nil);
se hscs = 0, então exit; // messagebox (hhandle, pchar (syserrormessage (getlasterror)), pchar (appold.title), mb_iconerror+mb_top mais);
se atribuído (alterações, serpenconfig2), então
Começar
Desc: = cópia (strDescription, 1.1024);
GetMem (srvdesc, sizeof (tServicedDescription));
GetMem (srvdesc^.lpDescription, comprimento (desc) + 1);
tentar
StrpCopy (srvdesc^.lpDescription, desc);
ChangeServiceConfig2 (HSCS, Service_Config_Description, SRVDESC);
Finalmente
Freemem (srvdesc^.lpDescription);
Freemem (srvdesc);
fim;
fim;
lpServiceargvectors: = nil;
se não for startService (hscs, 0, lpServiceargvectors) então // inicie o serviço
Saída;
ClosservieHandle (HSCs);
Resultado: = true;
fim;
procedimento desinstallService (StrServicename: string);
var
Scmanager: sc_handle;
Serviço: SC_HANDLE;
Status: tServicestatus;
Começar
Scmanager: = OpenScManager (nil, nil, sc_manager_all_access);
se scmanager = 0 então saia;
tentar
Serviço: = OpenService (Scmanager, PChar (StrServicename), Service_all_Access);
ControlService (Service, Service_Control_Stop, Status);
DeleteService (serviço);
ClosseservieHandle (serviço);
Finalmente
ClosseservieHandle (Scmanager);
fim;
fim;
fim.
(5) Como fechar brutalmente um programa de serviço e realizar a função da nossa "NT Toolbox" anterior?
usa tlhelp32;
função killtask (exefilename: string): integer;
const
Process_terminate = $ 0001;
var
ContinuoLooP: Bool;
FSNAPSHOTHANDLE: THANDLE;
FprocessEntry32: tprocessentry32;
Começar
Resultados: = 0;
Fsnapshothandle: = createToolHelp32snapshot (th32cs_snapprocess, 0);
FprocessEntry32.dWSize: = sizeof (fprocessentry32);
Continuoloop: = process32first (fsnapshothandle, fprocessentry32);
enquanto inteiro (continuoLeloop) <> 0 do
Começar
if ((uppercase (extractFilename (fprocessentry32.szexefile)) =
Uppercase (exefilename)) ou (uppercase (fprocessentry32.szexefile) =
OUPERCASE (exefilename)) então
Resultado: = Inteiro (TermineProcess (
OpenProcess (Process_termine,
Bool (0),
Fprocessentry32.th32processid),
0));
Continuoloop: = process32Next (fsnapshothandle, fprocessentry32);
fim;
CloseHandle (fsnapshothandle);
fim;
No entanto, para o programa de serviço, ele solicitará "acesso negado".
função enabledebugprivilege: booleano;
função enableprivilege (htoken: cardeal; privname: string; benable: boolean): boolean;
var
TP: token_privileges;
Dummy: cardeal;
Começar
Tp.privileGecount: = 1;
LookupPrivileGeValue (nil, pchar (privname), tp.privileges [0] .luid);
Se for benable então
Tp.privileges [0] .Attributes: = SE_PRIVILEGE_ENABLED
else tp.privileges [0] .Attributes: = 0;
AjustTokenPrivileges (htoken, false, tp, sizeof (tp), nil, fictício);
Resultado: = getLasterRor = error_success;
fim;
var
Htoken: cardeal;
Começar
OpenProcessToken (getCurrentProcess, token_adjust_privileges, htoken);
Resultado: = enablePrivilege (htoken, 'sedebugprivilege', verdadeiro);
CloseHandle (htoken);
fim;
Como usar:
Enabledebugprivilege; // eleva as permissões
KillTask ('xxxx.exe'); // Fechar o programa de serviço.
-------------------------------------------------------- -------------------------------------------------------- -------------------------------------------------------- -------------------------------------------------------- -------------------------------------------------------- ------ ----------