很多时候,我们都会遇到编写后台运行程序的问题。编写后台运行程序的主要工作并不在接口上,而是在其作为服务器程序所完成的实际工作上。由于编写过不少后台工作程序,最初总是为程序的后台工作接口而苦恼不已。在这里,我贴出相关的代码,相信根据此设计,读者可以轻易地把它应用到自己的后台程序中去。
假设程序名称为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;
}