很多时候,我们都会遇到编写后台运行程序的问题。编写后台运行程序的主要工作并不在接口上,而是在其作为服务器程序所完成的实际工作上。由于编写过不少后台工作程序,最初总是为程序的后台工作接口而苦恼不已。在这里,我贴出相关的代码,相信根据此设计,读者可以轻易地把它应用到自己的后台程序中去。
假设程序名称为startup,那么程序启动的接口为:
Startup: 启动该程序
Startup -v: 查看该程序的版本
Startup -d: 启动该程序,并将调试信息打印到debug文件中
Startup -h: 以后台方式启动应用程序
Startup -k: 停止后台应用程序的运行
Startup -l: 重新读取应用程序的配置文件
配置文件(startup.ini)的格式如下:
[SERVER]
DEBUG = 1
完整的实现如下:
Startup.h
#ifndef _STARTUP_H_
#define
_STARTUP_H_
#define
MAX_MSG_SIZE 1500
#define
MAX_BUFFER_LEN 1024
#define
MIN_BUFFER_LEN 256
#define
MAX_FILE_NAME_LEN MAX_BUFFER_LEN
#define
CFG_PATH "Startup.ini"
void
loadConfig();
void
mprintf(
const
char
*
pszFormat,...);
#endif
Startup.cpp
#include
"
Startup.h
"
#include
<
stdlib.h
>
#include
<
Windows.h
>
#include
<
iostream
>
using
namespace
std;
HANDLE hExitHandle
=
0
;
HANDLE hLoadHandle
=
0
;
int
nDbgInfoPrt
=
0
;
int
main(
int
argc,
char
*
argv[])
...
{
if
(argc
>
2
)
...
{
cout
<<
"
Error, print "Startup -help" for usage.
"
<<
endl;
return
0
;
}
if
(argc
==
2
&&
strcmp(argv[
1
],
"
-help
"
)
==
0
)
...
{
cout
<<
"
Usage: Startup for starting up test.
"
<<
endl;
cout
<<
"
-------------------------------------------
"
<<
endl;
cout
<<
"
Startup: Start the application.
"
<<
endl;
cout
<<
"
Startup -v: View the version.
"
<<
endl;
cout
<<
"
Startup -d: Start the application in debug mode.
"
<<
endl;
cout
<<
"
Startup -h: Start the application in hide mode.
"
<<
endl;
cout
<<
"
Startup -k: Stop the application running in hide mode.
"
<<
endl;
cout
<<
"
Startup -l: Reload the config when running in hide mode.
"
<<
endl;
return
0
;
}
if
(argc
==
2
&&
strcmp(argv[
1
],
"
-v
"
)
==
0
)
...
{
cout
<<
"
Startup v1.0 for starting up test
"
<<
endl;
return
0
;
}
if
(argc
==
2
&&
strcmp(argv[
1
],
"
-d
"
)
==
0
)
...
{
nDbgInfoPrt
=
true
;
mprintf(
"
Run application in debug mode!
"
);
}
if
(argc
==
2
&&
strcmp(argv[
1
],
"
-h
"
)
==
0
)
...
{
//
Run the program background
char
szPath[MAX_PATH]
=
...
{
0
}
;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(
&
si,
sizeof
(si));
si.cb
=
sizeof
(si);
ZeroMemory(
&
pi,
sizeof
(pi));
GetModuleFileName(NULL, (LPWCH)szPath, MAX_PATH);
if
(
!
CreateProcess(NULL,
//
No module name (use command line).
(LPWSTR)szPath,
//
Command line.
NULL,
//
Process handle not inheritable.
NULL,
//
Thread handle not inheritable.
FALSE,
//
Set handle inheritance to FALSE.
CREATE_NO_WINDOW,
//
No creation flags.
NULL,
//
Use parent's environment block.
NULL,
//
Use parent's starting directory.
&
si,
//
Pointer to STARTUPINFO structure.
&
pi)
//
Pointer to PROCESS_INFORMATION structure.
)
...
{
cout
<<
"
Failed in starting application, error code:
"
<<
GetLastError()
<<
endl;
}
return
0
;
}
if
(argc
==
2
&&
strcmp(argv[
1
],
"
-k
"
)
==
0
)
...
{
hExitHandle
=
OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR)
"
StartupKill
"
);
if
(NULL
==
hExitHandle)
...
{
mprintf(
"
Can't open kill event
"
);
return
0
;
}
SetEvent(hExitHandle);
return
0
;
}
if
(argc
==
2
&&
strcmp(argv[
1
],
"
-l
"
)
==
0
)
...
{
hLoadHandle
=
OpenEvent(EVENT_ALL_ACCESS, FALSE, (LPCWSTR)
"
StartupLoad
"
);
if
(NULL
==
hLoadHandle)
...
{
mprintf(
"
Can't open load event
"
);
return
0
;
}
SetEvent(hLoadHandle);
return
0
;
}
hExitHandle
=
CreateEvent(NULL, TRUE, FALSE, (LPCWSTR)
"
StartupKill
"
);
if
(NULL
==
hExitHandle)
...
{
mprintf(
"
Can't create kill event
"
);
return
0
;
}
hLoadHandle
=
CreateEvent(NULL, TRUE, FALSE, (LPCWSTR)
"
StartupLoad
"
);
if
(NULL
==
hLoadHandle)
...
{
mprintf(
"
Can't create load event
"
);
return
0
;
}
if
(GetLastError()
==
ERROR_ALREADY_EXISTS)
...
{
cout
<<
"
Application has already started.
"
<<
endl;
return
0
;
}
//
load the configure information
loadConfig();
for
( ; ; )
...
{
if
(WaitForSingleObject(hExitHandle,
0
)
!=
WAIT_TIMEOUT)
...
{
break
;
}
if
(WaitForSingleObject(hLoadHandle,
0
)
!=
WAIT_TIMEOUT)
...
{
loadConfig();
}
//
TODO: do something here
mprintf(
"
The program is alive!
"
);
Sleep(
1000
);
}
CloseHandle(hExitHandle);
CloseHandle(hLoadHandle);
return
0
;
}
/**/
///////////////////////////////////////////////////
//
//
Description: load the configure from .ini file
//
//
Parameter:
//
void ==
//
//
Return:
//
void ==
//
/**/
///////////////////////////////////////////////////
void
loadConfig()
...
{
//
Get the configure info from Startup.ini
nDbgInfoPrt
=
GetPrivateProfileInt((LPCWSTR)
"
SERVER
"
, (LPCWSTR)
"
DEBUG
"
,
0
, (LPCWSTR)CFG_PATH);
}
/**/
///////////////////////////////////////////////////
//
//
Description: print the msg
//
//
Parameter:
//
const char *pszFormat ==
//
//
Return:
//
void ==
//
/**/
///////////////////////////////////////////////////
void
mprintf(
const
char
*
pszFormat,...)
...
{
if
(
!
nDbgInfoPrt)
...
{
return
;
}
va_list vaArg;
va_start(vaArg, pszFormat);
char
szDbgInfo[MAX_BUFFER_LEN
+
1
]
=
...
{
0
, }
;
vsprintf_s(szDbgInfo, pszFormat, vaArg);
va_end(vaArg);
cout
<<
szDbgInfo
<<
endl;
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1472147