您的位置:首页 > 移动开发 > Objective-C

如何“干净地”终止 Win32 中的应用程序

2010-11-02 15:43 197 查看
在 Win32
下,操作系统可保证在进程关闭时清除进程所拥有的资源。但是,这并不意味着进程本身将有机会对磁盘执行任何最后的信息刷新或通过远程连接执行任何最后的通信,也不意味着进程的
DLL 将有机会执行其 PROCESS_DETACH 代码。这就是通常最好避免在 Windows 95 和 Windows NT
下终止应用程序的原因。

如果你必须关闭进程,请按照下列步骤操作:

向你打算关闭的进程所拥有的所有顶级窗口发送一条 WM_CLOSE 消息。许多 Windows
应用程序会通过关闭它自身来响应此消息。

注意:控制台应用程序对 WM_CLOSE 的响应取决于它是否安装了控制处理程序。

使用 EnumWindows() 找到目标窗口的句柄。在回调函数中,检查该窗口的进程 ID 是否与要关闭的进程相匹配。你可以通过调用
GetWindowThreadProcessId() 来执行此操作。确定匹配项后,使用 PostMessage() 或
SendMessageTimeout() 向该窗口发送 WM_CLOSE 消息。

使用 WaitForSingleObject() 等待进程的句柄。确保你使用超时值等待,因为在很多情况下 WM_CLOSE
不会关闭应用程序。记住,应使超时值足够长(通过 WaitForSingleObject() 或 SendMessageTimeout()),以便用户可以响应为了
处理 WM_CLOSE 消息而创建的任何对话框。

如果返回值为 WAIT_OBJECT_0,则应用程序已干净地将其自身关闭。如果返回值为 WAIT_TIMEOUT,则必须使用
TerminateProcess() 关闭应用程序。

注意:如果从 WaitForSingleObject() 得到的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,则应使用

GetLastError() 找出原因。

函数说明:

1.EnumWindows

这个函数列出屏幕上所有的顶级窗口,传递他们的指针给程序定义的回调函数.这个函数会一直工作到列出所有窗口,或者回调函数返回FALSE.

BOOL EnumWindows(

 WNDENUMPROC lpEnumFunc,  // pointer to callback function

 LPARAM lParam            // application-defined value

);

参数

lpEnumFunc        指向程序定义的回调函数的指针.

lParam               传递给回调函数的值,由程序自己定义的.

返回值               如果函数成功了,返回一个非0值.如果失败了,返回0.



 该函数不会列出子窗口.该函数比GetWindow更可靠.调用GetWindow的函数执行时可能会陷入死循环中,或者使用一个已经被销毁的窗口句柄.

EnumWindowsProc

这个函数是程序自己定义的回调函数.它获得顶级窗口的句柄.

BOOL CALLBACK EnumWindowsProc(

  HWND hwnd,      // handle to parent window

  LPARAM lParam   // application-defined value

);

参数

hwnd           顶级窗口的句柄.

lParam        EnumWindows传过来的参数

返回值         要继续枚举,函数必须返回TRUE,要停止枚举必须返回FALSE.

通过执行上述这些步骤,你便完全有可能干净地关闭应用程序(无需 IPC 或用户干预)。

例子:

#include   "stdafx.h "

#include   <windows.h>

#include   <conio.h>

#define   PAUSE   printf( "/npress   any   key   to   exit ");   getch();

//注册回调函数

BOOL   CALLBACK   EnumWindowsProc(

    HWND   hwnd,             //   handle   to   parent   window

    LPARAM   lParam       //   application-defined   value

)

{

ULONG pid;

char   szClassName[255];

char   szTitle[255];

GetClassName(   hwnd,   szClassName,   255   );   //获取类名

GetWindowText(   hwnd,   szTitle,   255   );   //获取窗口名字

if(   strcmp(   szClassName,   "#32770 "   )   ==   0   )

{

HWND   hQQBar   =   FindWindowEx(   hwnd,   NULL,   "Tencent_QQBar ",   NULL   );   //找到应用程序句柄

GetWindowThreadProcessId(hQQBar,&pid);  //获取程序PID号

 

HANDLE hToolHelp = ::CreateToolhelp32Snapshot()获取当前进程快照

PROCESSENTRY32 process;

Process32First(hToolHelp, &process);

while(process.szExeFile != "QQ2010")

  Process32Next(hToolHelp, &process);

 

//检查该窗口的进程 ID 是否与要关闭的进程相匹配

if(   pid == process.th32ProcessID   )

{

printf( "%x:%s(%s)/n ",   hQQBar   ,   szClassName,   szTitle   );

PostMessage(   hQQBar   ,   WM_CLOSE,   0,   0   );

DWORD dw = WaitForSingleObject(hQQBar   , 5000); //等待一个进程结束

switch (dw)

{

   case WAIT_OBJECT_0:

     
// hProcess所代表的进程在5秒内结束

      
break;

   case WAIT_TIMEOUT:

     
// 等待时间超过5秒

      
break;

 
  case WAIT_FAILED:

     
// 函数调用失败,比如传递了一个无效的句柄

      
break;

}

}

}

return   TRUE;

}

int   main(int   argc,   char*   argv[])

{

EnumWindows(   EnumWindowsProc,   0   );

PAUSE;

return   0;

}

这个程序能够关闭当前的QQ窗口
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息