全局變量和函數聲明
//第一個服務
void WINAPI ServiceMain();
void WINAPI ServiceHandler(DWORD dwOpcode);
TCHAR szServiceName[] = _T("ServiceTest");
//第二個服務
void WINAPI ServiceMain1();
void WINAPI ServiceHandler1(DWORD dwOpcode);
TCHAR szServiceName1[] = _T("ServiceTest1");
//
BOOL bInstall;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS status;
DWORD dwThreadID;
一、服務程序實現:
對於Service程序來說,它一般又由以下三部分組成:main(),ServiceMain()和Handler()
如果有多個服務,則必須要有多對的ServiceMain()和Handler()對應函數
1、main()
服務程序的入口與普通程序一樣也是從main()開始,但不同的是服務程序的main極爲簡單,因爲它只
負責創建分派表並啓動控制分派機,其代碼如下:
void main()
{
SERVICE_TABLE_ENTRY st[] =
{
{ szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ szServiceName1, (LPSERVICE_MAIN_FUNCTION)ServiceMain1 },
{ NULL, NULL } //最好必須以{NULL, NULL}結尾
};
//啓動服務的控制分派機線程
if (!::StartServiceCtrlDispatcher(st))
{
……
}
}
main()是服務程序的主線程,當servie control manager開始一個Service進程時,它總是等待這個
服務程序去調用StartServiceCtrlDispatcher()函數。當執行服務時main()時將會調用ServiceMain
函數,當ServiceMain執行完畢或者發生錯誤時StartServiceCtrlDispatcher函數返回,然後主進程終止。
2. ServiceMain():服務的真正入口
ServiceMain()是服務程序的真正入口點,它主要完成以下功能,首先註冊一個Handler去處理控制程序
或控制面板,服務的控制要求,比如 啓動,停止,暫停,重啓等,其次就是實現我們的功能操作,其實
現代碼如下:
VOID WINAPI ServiceMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
DWORD status = 0;
DWORD specificError = 0xfffffff;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
//調用RegisterServiceCtrlHandler()註冊一個ServiceHandler函數用來處理程序對Service的
//控制要求
hStatus = RegisterServiceCtrlHandler("ServiceName",(LPHANDLER_FUNCTION)ServiceHandler);
if (hStatus==0)
return;
// Handle error condition
status = GetLastError();
if (status!=NO_ERROR)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
ServiceStatus.dwWin32ExitCode = status;
ServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// Initialization complete - report running status
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);
//啓動自己的工作線程,mainfun:自己要實現的功能的線程函數
HANDLE hThread=CreateThread(NULL,0,mainfun,NULL,0,NULL);
if(hThread==NULL)
return;
}
在ServiceMain中通過RegisterServiceCtrlHandler註冊一個ServiceHandler函數用來處理程序對服
務的控制
3.ServiceHandler()
當你打開服務管理器,啓動或停止一個服務的時候,對你的操作進行響應的就是ServiceHandler()函
數,它會判斷你的操作然後做出響應,其實現代碼如下:
VOID WINAPI ServiceHandler(DWORD fdwControl)
{
switch(fdwControl)
{
case SERVICE_CONTROL_PAUSE:
ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus,&ServiceStatus);
return ;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
SetServiceStatus(hStatus,&ServiceStatus);//設置狀態
return ;
}
二、安裝和卸載服務實現:
以上是服務程序的實現,但是,上面的服務程序僅僅是一個服務而已,我們還沒有啓動這個服務,所
以下面我們來處理啓動服務部分啓動服務程序和服務程序可以結合在一起作爲一個文件,也可以像下
面這樣,另外寫一個啓動程序。
OpenSCManager: 用於打開服務控制管理器(servie control manager);
CreateService: 用於創建服務;
OpenService: 用於打開已有的服務,返回該服務的句柄;
ControlService: 則用於控制已打開的服務狀態,這裏是讓服務停止後才刪除;
DeleteService: 用於刪除指定服務。
1、安裝服務程序
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>
main()
{
char name[100];
char info[200];
char path[300];
printf("請輸入服務名/n/n");
scanf ("%s",&name);
printf("請輸入服務描述/n/n");
scanf ("%s",&info);
printf("請輸入程序路徑/n/n");
scanf ("%s",&path);
SC_HANDLE manager=NULL;
SC_HANDLE service=NULL;
if((manager=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE))==NULL)
{
printf("OpenSCManager Error");
}
service=CreateService(
manager,name,info,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
path, 0, 0, 0, 0, 0 );
if(service)
printf("服務創建成功/n/n");
else
printf("服務創建失敗/n/n");
CloseServiceHandle(service);
CloseServiceHandle(manager);
}
CreateService該函數用來創建服務,
第五個參數爲SERVICE_WIN32_SHARE_PROCESS或者SERVICE_WIN32_OWN_PROCESS
如果僅僅創建一個服務的話,第五個參數用SERVICE_WIN32_SHARE_PROCESS
但是如果要創建多個服務的話:
例如,啓動兩個服務:
CreateService(……);
CreateService(……);
如果第五個參數爲:
SERVICE_WIN32_OWN_PROCESS: 每個服務都有自己的一個獨立進程
此時,打開任務管理器可以看到有兩個ServiceTest.exe的進程,
SERVICE_WIN32_SHARE_PROCESS:表示多個服務共享一個進程
此時,打開任務管理器可以看到只有一個ServiceTest.exe的進程,同時可以看到比
SERVICE_WIN32_OWN_PROCESS方式的線程數多一個
2、刪除服務程序
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>
void main()
{
char name[100];
SC_HANDLE scm;
SC_HANDLE service;
SERVICE_STATUS status;
printf("請輸入要刪除的服務名/n/n");
scanf ("%s",&name);
if((scm=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE))==NULL)
{
printf("OpenSCManager Error/n");
}
service=OpenService(scm,name,SERVICE_ALL_ACCESS|DELETE);
if (!service)
{
printf("OpenService error!/n");
return;
}
BOOL isSuccess=QueryServiceStatus(service,&status);
if (!isSuccess)
{
printf("QueryServiceStatus error!/n");
return;
}
if ( status.dwCurrentState!=SERVICE_STOPPED )
{
isSuccess=ControlService(service,SERVICE_CONTROL_STOP,&status);
if (!isSuccess )
printf("Stop Service error!/n");
Sleep( 500 );
}
isSuccess=DeleteService(service);
if (!isSuccess)
printf("刪除服務失敗!/n");
else
printf("刪除服務成功!/n");
CloseServiceHandle(service );
CloseServiceHandle(scm);
}
SERVICE_STATUS:該結構體的一些變量可自行查找資料瞭解,本文只是簡單介紹服務程序實現。
備註:服務執行順序爲先啓動服務,最好才運行服務程序本身,如果服務未調用CreateService啓動,
就調用StartServiceCtrlDispatcher來啓動服務的控制分派機線程
參考文章:
http://www.vckbase.com/document/listdoc.asp?mclsid=13&sclsid=1319
http://www.hongke-vip.com/read.php?tid-34125.html
附加測試程序源碼(由http://www.vckbase.com/document/listdoc.asp?mclsid=13&sclsid=1319資源修改)
http://download.csdn.net/source/2495451