前些天搞了个×××面的后台应用程序,以前从来没有接触过,网上查找资料,都是零零散散的,比较少全面一点的介绍。这里把自己的创建过程大概记录一下,给自己留个底儿。

1.如何创建×××面后台应用

一般可以选择用控制台方式隐藏窗口,或者用对话框模式隐藏窗口,我这里用的是对话框模式。

在VC6.0上新建一个对话框应用程序CMfcNoDialogAppApp,其实只是借了个它的外壳。CMfcNoDialogAppDlg的OnPaint()方法中做个处理,代码如下:

 

 
  
  1. void CMfcNoDialogAppDlg::OnPaint()  
  2. //  if (IsIconic()) 
  3. //  { 
  4. //      CPaintDC dc(this); // device context for painting 
  5. //  
  6. //      SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
  7. //  
  8. //      // Center icon in client rectangle 
  9. //      int cxIcon = GetSystemMetrics(SM_CXICON); 
  10. //      int cyIcon = GetSystemMetrics(SM_CYICON); 
  11. //      CRect rect; 
  12. //      GetClientRect(&rect); 
  13. //      int x = (rect.Width() - cxIcon + 1) / 2; 
  14. //      int y = (rect.Height() - cyIcon + 1) / 2; 
  15. //  
  16. //      // Draw the icon 
  17. //      dc.DrawIcon(x, y, m_hIcon); 
  18. //  } 
  19.     m_hThread = (HANDLE)_beginthreadex(NULL, 
  20.         0, 
  21.         ThreadEntry, 
  22.         this
  23.         0, 
  24.         &m_hThreadID); 
  25.     static int i = 2; 
  26.     if (i <= 2) 
  27.     { 
  28.         ShowWindow(SW_HIDE); 
  29.         i--; 
  30.     } 
  31.     else 
  32.     { 
  33.         CDialog::OnPaint(); 
  34.     } 

如上代码中被注释掉的是程序自动生成的有关窗口绘制的内容,在下面创建一个自己需要的线程,用来实现自己的功能。

后面用了一个方法内静态变量

	static int i = 2;
if (i <= 2)
{
ShowWindow(SW_HIDE);
i--;
}
else
{
CDialog::OnPaint();
}


设置为i<=2时,窗口将不显示。

这样一个简单的后台应用就出来了,运行之后,在进程管理中可以看到它的进程,并且在任务管理的应用程序栏中没有图标,在任务栏也没有图标。有一点不太好的是,直接双击运行这个应用程序,会闪一下他的窗口。

2.后台应用的启动和关闭

启动可以直接调用API方法CreateProcess,如下:

 
  
  1. PROCESS_INFORMATION pi; 
  2. STARTUPINFO si; 
  3.  memset(&si,0,sizeof(si)); 
  4.  si.cb=sizeof(si);  
  5.  si.wShowWindow=SW_SHOW; 
  6. si.dwFlags=STARTF_USESHOWWINDOW; 
  7. bool ret = CreateProcess("E:\\testandlearn\\MfcNoDialogApp\\Debug\\MfcNoDialogApp.exe"
  8.         NULL, 
  9.         NULL, // process security attributes 
  10.         FALSE, // primary thread security attributes 
  11.         NULL, // handles are inherited 
  12.         NULL, // creation flags 
  13.         NULL, // use parent\'s environment 
  14.         NULL, // use parent\'s current directory 
  15.         &si, // startupinfo pointer 
  16.         &pi); // receives process_information 

进程启动成功后,pi.hProcess就是他的进程句柄。

关闭进程:

关掉进程不能使用ExitProcess,这个是用来停掉自己的。应该使用TerminateProcess,但是他需要一个参数,ExitCode。可以通过GetExitCodeProcess方法获取。关闭进程的代码如下:

 

 
  
  1. DWORD lpExitCode ;  
  2. GetExitCodeProcess(hProcess,&lpExitCode);//获取退出码 
  3. TerminateProcess( hProcess, lpExitCode);//关掉进程 
  4. CloseHandle( hThread );//关掉进程的主线程句柄 
  5. CloseHandle( hProcess );//关掉进程句柄 

这样就可以完全控制一个后台进程的生死了。

TerminateProcess是没有任何提示的强制干掉一个进程,所以调用前要确保他的工作已经完成,内存已经释放。