Linux/Unix下服务程序写了很多个了。也就是最终转换为后台的daemon就可以(run in the background),当然在这之前你一定要明白什么是进程,进程组,子进程,父进程等等相关的进程概念! 以前写这种东西的时候还是一个个的fork(), exit(), 但后来发现既然有一个daemon()函数,要想看更多的信息就查man daemon吧。 这次我主要想说的是怎么写Windows下的服务程序,本人对VC用的不是很熟悉,就用哪个cl.exe, link.exe, nmake, makefile来个最原始的。 在这之前我看了一下 http://www.vckbase.com/document/viewdoc/?id=1474 这篇文章。 自己来实践一下。 用普通的文本编辑器就可以完成的。 我的环境: Microsoft Windows 2000 [Version 5.00.2195] (C) 版权所有 1985-2000 Microsoft Corp. C:\>echo %PATH% C:\oracle\ora81\bin;C:\Program Files\Oracle\jre\1.1.7\bin;C:\WINNT\system32;C:\WINNT;C:\WINNT\System32\Wbem;C:\Program Files\SecureCRT;C:\Program Files\Microsoft Visual Studio\VC98\Bin;C:\gan\windmp\dmp\bin;C:\Program Files\Microsoft Visual Studio\Common\Tools\WinNT;C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin;C:\Program Files\Microsoft Visual Studio\Common\Tools;C:\Program Files\Microsoft Visual Studio\VC98\bin 所有的测试我全部在: c:\gan\ts\svc下测试的。文件名为main.c ============================================
/** * Author: Gan * Date: 2007-9-27 * Name: main.c */ # include < stdio. h> # include < windows. h> # define SVC_SLEEP_TIME 1000 # define SVC_LOG_FILENAME "c:\\svc.log" SERVICE_STATUS svc_st; SERVICE_STATUS_HANDLE svc_hd; void ServiceMain( int argc, char * * argv) ; void ControlHandler( DWORD request) ; int svc_init( void ) ; /** * Write Log file */ int svc_write_log( const char * str) { FILE * fp; fp = fopen ( SVC_LOG_FILENAME, "a+" ) ; if ( fp = = NULL ) { printf ( "file open error! \n" ) ; return ( - 1) ; } fprintf ( fp, "%s\n" , str) ; fclose ( fp) ; return ( 0) ; } /** * Initialize Service */ int svc_init( void ) { int ret; printf ( "svc_init called. \n" ) ; ret = svc_write_log( "svc_init called, started. " ) ; return ( ret) ; } void ControlHandler( DWORD request) { switch ( request) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: printf ( "Monitoring Started.\n" ) ; svc_write_log( "Monitoring started." ) ; svc_st. dwWin32ExitCode = 0; svc_st. dwCurrentState = SERVICE_STOPPED; SetServiceStatus( svc_hd, & svc_st) ; return ; default : break ; } SetServiceStatus( svc_hd, & svc_st) ; } /** * Service Main Function */ void ServiceMain( int argc, char * * argv) { char str[ 32] ; MEMORYSTATUS mem; svc_st. dwServiceType = SERVICE_WIN32; svc_st. dwCurrentState = SERVICE_START_PENDING; svc_st. dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; svc_st. dwWin32ExitCode = 0; svc_st. dwServiceSpecificExitCode = 0; svc_st. dwCheckPoint = 0; svc_st. dwWaitHint = 0; printf ( "ServiceMain Called. \n" ) ; svc_hd = RegisterServiceCtrlHandler( "MemoryStatus" , ( LPHANDLER_FUNCTION) ControlHandler) ; if ( svc_hd = = ( SERVICE_STATUS_HANDLE) 0) { printf ( "RegisterServiceCtlHandler error. \n" ) ; return ; } if ( svc_init( ) ) { svc_st. dwCurrentState = SERVICE_STOPPED; svc_st. dwWin32ExitCode = 0; SetServiceStatus( svc_hd, & svc_st) ; return ; } svc_st. dwCurrentState = SERVICE_RUNNING; SetServiceStatus( svc_hd, & svc_st) ; while ( svc_st. dwCurrentState = = SERVICE_RUNNING) { GlobalMemoryStatus( & mem) ; sprintf ( str, "%d" , mem. dwAvailPhys) ; printf ( str) ; if ( svc_write_log( str) ) { svc_st. dwCurrentState = SERVICE_STOPPED; svc_st. dwWin32ExitCode = - 1; SetServiceStatus( svc_hd, & svc_st) ; return ; } Sleep ( SVC_SLEEP_TIME) ; } } int main( int argc, char * argv[ ] ) { SERVICE_TABLE_ENTRY svc_tab[ 2] ; printf ( "Main Test started.\n" ) ; svc_tab[ 0] . lpServiceName = "MemoryStatus" ; svc_tab[ 0] . lpServiceProc = ( LPSERVICE_MAIN_FUNCTION) ServiceMain; svc_tab[ 1] . lpServiceName = NULL ; svc_tab[ 1] . lpServiceProc = NULL ; StartServiceCtrlDispatcher( svc_tab) ; return 0; }
==================================
编译该程序[你可以看到cl在这可以直接使用是因为我自己修改了PATH环境变量,本来cl.exe link.exe全部是在VC中使用的工具]:
C:\gan\ts\svc>cl advapi32.lib main.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
main.c
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/out:main.exe
advapi32.lib
main.obj
------
这地方编译的时候需要advapi32.lib的哦。如果没有结果就是:
C:\gan\ts\svc>cl main.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
main.c
Microsoft (R) Incremental Linker Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/out:main.exe
main.obj
main.obj : error LNK2001: unresolved external symbol __imp__SetServiceStatus@8
main.obj : error LNK2001: unresolved external symbol __imp__RegisterServiceCtrlHandlerA@8
main.obj : error LNK2001: unresolved external symbol __imp__StartServiceCtrlDispatcherA@4
main.exe : fatal error LNK1120: 3 unresolved externals
-------
在连接(link.exe)的时候就找不到相关的函数了。
==================================
接下来就是安装服务:
C:\gan\ts\svc>sc create MemoryStatus binpath= c:\gan\ts\svc\main.exe
[SC] CreateService SUCCESS
==================================
如果不需要可以删除服务:
C:\gan\ts\svc>sc delete MemoryStatus
[SC] DeleteService SUCCESS