以下为 Win2000 下我所理解的服务程序的源码,可以创建一个服务,并可以随时启动,停止和移除该服务。使用VC6编译,下面是使用方法简介。
需要安装 Service 的,打开 Dos 窗口,然后输入程序名字加上 -install 参数 例如:
#Simple_Service -install
如果需要删除 Service 的,在 Dos 窗口,输入程序名字加上 -remove 参数
#Simple_Service -Remove
也可以使用工具 SC.exe 来删除服务,在 Dos 窗口输入 sc delete _Simple_Service_08 即可
如果要启动或停止服务,请在计算机管理-> 服务那里启动 ,服务名称为 _Simple_Service_08
/////////////////////////////////////////////////////////////////////////////////////
该服务程序会生成调试用的日志文件,需要包含 RunTimeLog.h 和 RunTimeLog.cpp 这两个文件在这里 http://www.csdn.net/develop/Read_Article.asp?Id=17477
下面的程序对刚刚入门的伙伴可能有用,"高手"们就省省墨水,免得我又被臭骂了(面对像这样的中国人,我不得不学乖一点)。
以下是完整的源程序,文件名称是: WinMain.cpp,详细的说明待我组织过后再附上。
//******************************************************************************** //*************** FileName: WinMain.cpp ******************************** //******************************************************************************** // 最小 Link 包含: msvcrt.lib kernel32.lib user32.lib Advapi32.lib Shell32.lib #define WIN32_LEAN_AND_MEAN // Say No to MFC !! #define UNICODE
#include <windows.h> //#include <Winsvc.h> //#include <Shellapi.h>
#include "RunTimeLog.h" RunTimeLog log;
LPSTR MsgErr=NULL;
////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Define for Service
#define ServiceName "_Simple_Service_08" #define StrInstall TEXT("install") #define StrRemove TEXT("Remove")
void WINAPI service_ctrl(DWORD dwCtrlCode); void WINAPI service_main(DWORD dwArgc,LPTSTR *lpszArgv);
void WinMainCleanup(void);
SC_HANDLE schService=NULL, schSCManager=NULL; SERVICE_STATUS ssStatus; SERVICE_STATUS_HANDLE sshStatusHandle=NULL; HANDLE hServerStopEvent = NULL;
//////////////////////////////////////////////////////////////////////////
// End of Define for Service
char temp[1024]="Temp77 is Bad!";
//////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// void WinMainCleanup(void) { if(MsgErr){ LocalFree(MsgErr); MsgErr = NULL; } if( schService ) CloseServiceHandle( schService ); if(schSCManager) CloseServiceHandle(schSCManager); log.last(true); //log.showResult(1500); //log.write("after ShowResult!"); return; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Name: WinMain() // ------ ---------- ----------- --------- int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {
log.nobuff = true; log.write(ServiceName" WinMain start");
// 判断是否为 WinNT OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if( GetVersionEx(&osvi) ) { if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) log.write("WinNT 系统可用!"); else { log.write("非 WinNT 系统中,清场后退出"); WinMainCleanup(); return 1; } }else { log.write("Failed to GetVersionEx."); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr); WinMainCleanup(); return 1; }// End of if( GetVersionEx(&osvi) )
// 填充服务入口表 SERVICE_TABLE_ENTRY dispatchTable[] = { { TEXT(ServiceName), LPSERVICE_MAIN_FUNCTION(service_main) }, { NULL, NULL } };
// 取得命令行以观察 LPSTR cmdline = GetCommandLineA(); log.write("CommandLine by following."); log.write(cmdline); log.write("");
// 取得当前目录以观察 GetCurrentDirectoryA(1024,temp); log.write("CurrentDirectory by following."); log.write(temp); log.write("");
// 取得模块的文件名以观察 GetModuleFileNameA(NULL,temp,sizeof(temp)); log.write("Current Module FileName by following."); log.write(temp); log.write("");
for(int i1=lstrlenA(temp); i1>0; i1--) { if(temp[i1]=='\\') { temp[i1]=0;break; } } SetCurrentDirectoryA(temp); log.write("重新设置了当前目录的位置");
// 重新取得当前目录以观察 GetCurrentDirectoryA(1024,temp); log.write("CurrentDirectory by following."); log.write(temp); log.write("");
// 分离出参数组以访问 int NumArgsCount = NULL; LPWSTR * lpArgv = CommandLineToArgvW( GetCommandLineW(), &NumArgsCount ); log.numberwrite("NumArgsCount = ", (DWORD)NumArgsCount);
int i=0; for(i=0;i<NumArgsCount;i++) { log.numberwrite("命令行参数 ",i); WideCharToMultiByte(CP_ACP, NULL, lpArgv[i],-1,temp,sizeof(temp),NULL,NULL); log.write(temp); log.write(""); }
// 判断参数的操作 if(NumArgsCount>1) // 只有参数个数大于 1 的时候 { if( (lpArgv[1][0]==(WORD)'/') || (lpArgv[1][0]==(WORD)'-') ) { log.write("判断参数"); if(!_wcsicmp(StrInstall, lpArgv[1]+1)) { log.write("Install specify."); //CmdInstalService();
if(!GetModuleFileNameA(NULL,temp,sizeof(temp))) { log.write("GetMouduleFileName failed."); WinMainCleanup(); return 0; }
// SC_HANDLE schService=NULL, schSCManager=NULL; schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if(schSCManager) { log.write("OpenSCManager 成功"); // 打开成功才创建 schService = CreateServiceA( schSCManager, ServiceName, ServiceName"(Dsp)", SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,SERVICE_ERROR_NORMAL, temp,NULL,NULL,NULL,NULL,NULL ); if(schService) { log.write("CreateService "ServiceName" 成功"); CloseServiceHandle(schService); schService = NULL; } else { log.write("CreateService "ServiceName" failed.");
FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr); WinMainCleanup(); return 0; }
CloseServiceHandle(schSCManager); schSCManager = NULL; } else { log.write("OpenSCManager failed."); WinMainCleanup(); return 0; }
log.write(""); log.write("完成了服务的安装"); log.write("");
} else if(!_wcsicmp(StrRemove, lpArgv[1]+1)) { log.write("Remove specify."); //CmdRemoveService();
// SC_HANDLE schService=NULL, schSCManager=NULL; schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if(schSCManager) { log.write("OpenSCManager 成功"); // 打开成功才进行下一步 schService = OpenServiceA( schSCManager, ServiceName, SERVICE_ALL_ACCESS); if(schService) { log.write("OpenService "ServiceName" 成功");
QueryServiceStatus( schService, &ssStatus); if(ssStatus.dwCurrentState == SERVICE_STOPPED) log.write("Service already Stopped."); else { // try to Stop the Service log.write("try to Stop the Service");
if( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) { Sleep(50); while ( QueryServiceStatus( schService, &ssStatus)) { if( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) { Sleep(500); log.write("仍在停止 Service 中。。。"); } else break; }//End of while ( QueryServiceStatus( schService, &ssStatus)) }
}//End of if(ssStatus.dwCurrentState == SERVICE_STOPPED) else
// 如果已经停止了 Service ,那么就删除服务 if(ssStatus.dwCurrentState == SERVICE_STOPPED ) { Sleep(1000); if( DeleteService( schService) ) log.write("成功删除 "ServiceName" Service"); else log.write("删除 "ServiceName" 失败"); log.write(""); } else log.write("failed to Stop Service.");
CloseServiceHandle(schService); schService = NULL; } else { log.write("OpenService "ServiceName" failed.");
FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr);
WinMainCleanup(); return 0; } CloseServiceHandle(schSCManager); schSCManager = NULL; } else { log.write("OpenSCManager failed."); WinMainCleanup(); return 0; }
} } WinMainCleanup(); return 0; } // End of if(NumArgsCount>1) // 只有参数个数大于 1 的时候
log.write("");
if(StartServiceCtrlDispatcher(dispatchTable)) log.write("StartServiceCtrlDispatcher Complete."); else { log.write("StartServiceCtrlDispatcher failed."); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr); }
WinMainCleanup(); //ExitProcess(0); log.last(true); return NULL;
}
////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void WINAPI service_ctrl(DWORD dwCtrlCode) { // Handle the requested control code log.write(""); log.write("Go into service_ctrl Function."); log.write(""); int i2=0; switch(dwCtrlCode) { // Stop the Service case SERVICE_CONTROL_STOP: log.write("recive SERVICE_CONTROL_STOP"); ssStatus.dwCheckPoint = ssStatus.dwCheckPoint++; ssStatus.dwWin32ExitCode = NO_ERROR; ssStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(sshStatusHandle,&ssStatus);
SetEvent(hServerStopEvent); log.write("已经设置 Service 状态为 SERVICE_STOP_PENDING ,并将同步对象设置为激发状态.");
for(i2=0; i2<12; i2++) { QueryServiceStatus( schService, &ssStatus); if( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) Sleep(200); else break; } ResetEvent(hServerStopEvent); if(ssStatus.dwCurrentState == SERVICE_STOPPED ) { log.write("The Service is now Stoped"); ssStatus.dwCheckPoint = 0; ssStatus.dwWin32ExitCode = NO_ERROR; ssStatus.dwCurrentState = SERVICE_STOP; SetServiceStatus(sshStatusHandle,&ssStatus); } else log.write("Stoped Service Failed.");
return; break; case SERVICE_CONTROL_INTERROGATE: log.write("recive SERVICE_CONTROL_INTERROGATE"); break; default: log.numberwrite("recive CtrlCode = ",dwCtrlCode); break; }
//ssStatus.dwCurrentState = SERVICE_STOP_PENDING; ssStatus.dwCheckPoint = ssStatus.dwCheckPoint++; ssStatus.dwWin32ExitCode = NO_ERROR; SetServiceStatus(sshStatusHandle,&ssStatus);
return; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void service_mainCleanup(void) { log.write(""); log.write("service_mainCleanup!"); log.write("");
if(hServerStopEvent){ CloseHandle(hServerStopEvent); hServerStopEvent = NULL; }
ssStatus.dwWin32ExitCode = 0; ssStatus.dwCurrentState = SERVICE_STOPPED; ssStatus.dwWaitHint = 1000; if(SetServiceStatus(sshStatusHandle,&ssStatus)) { log.write("SetServiceStatus to SERVICE_STOPPED 成功!"); } else { log.write("SetServiceStatus to SERVICE_STOPPED 失败!"); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr); } //log.showResult(false); return; } //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////// void WINAPI service_main(DWORD dwArgc,LPTSTR *lpszArgv) {
// 注册我们的 Service 控制处理函数 sshStatusHandle = RegisterServiceCtrlHandlerA(ServiceName,service_ctrl); if(!sshStatusHandle) { FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr); log.write("Failed to RegisterServiceCtrlHandler"); service_mainCleanup(); }
log.write(""); log.write("We now Running in service_main."); log.write("Success to RegisterServiceCtrlHandler");
hServerStopEvent = CreateEvent(NULL,TRUE,false,NULL); if(hServerStopEvent) log.write("创建了同步对象"); else log.write("创建同步对象失败");
// 以下是测试同步信号的代码 DWORD dwWait = NULL;
dwWait = WaitForSingleObject(hServerStopEvent,200); { if(dwWait==WAIT_TIMEOUT) log.write("等待同步信号超时"); if(dwWait==WAIT_OBJECT_0) log.write("同步对象被触发了"); }
// 继续报告现在 Service 启动的进度 ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ssStatus.dwServiceSpecificExitCode = 0; ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP ;//| SERVICE_ACCEPT_PAUSE_CONTINUE; ssStatus.dwWaitHint = 1000;
// 设置以后放送 ssStatus.dwCheckPoint = 0; ssStatus.dwWin32ExitCode = NO_ERROR; ssStatus.dwCurrentState = SERVICE_START_PENDING;
if(SetServiceStatus(sshStatusHandle,&ssStatus)) { log.write("SetServiceStatus 成功!"); } else { log.write("SetServiceStatus 失败!"); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), NULL, (LPSTR)&MsgErr, 0, NULL ); log.write(MsgErr); }
Sleep(300);
// 设置以后放送 ssStatus.dwCheckPoint++; log.numberwrite("Progress = ",ssStatus.dwCheckPoint); ssStatus.dwWin32ExitCode = NO_ERROR; ssStatus.dwCurrentState = SERVICE_START_PENDING;
SetServiceStatus(sshStatusHandle,&ssStatus);
for(int i1=0; i1<6;i1++) {
Sleep(300); // 设置以后放送 //ssStatus.dwCheckPoint++; ssStatus.dwCheckPoint = ssStatus.dwCheckPoint + 20; log.numberwrite("Progress = ",ssStatus.dwCheckPoint); ssStatus.dwWin32ExitCode = NO_ERROR; ssStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(sshStatusHandle,&ssStatus);
}
Sleep(200);
// 设置以后放送 ssStatus.dwCheckPoint = 0; ssStatus.dwWin32ExitCode = NO_ERROR; ssStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(sshStatusHandle,&ssStatus); log.write("SetServiceStatus to SERVICE_RUNNING !");
Sleep(500);
// 放入代码运行服务
while (true) { dwWait = WaitForSingleObject(hServerStopEvent,1); { //if(dwWait==WAIT_TIMEOUT) log.write("等待同步信号超时"); if(dwWait==WAIT_OBJECT_0) { log.write("同步对象被触发了"); ResetEvent(hServerStopEvent); break; } } //////////////////////////////////////////////////////////////////////////
log.write("Doing Something..."); Sleep(100); // 假设要运行100毫秒的操作
//////////////////////////////////////////////////////////////////////////
}// End of while (true)
service_mainCleanup();
return; }

|