小心,进程句柄!

//=====================================================================
//TITLE:
//    小心,进程句柄!
//AUTHOR:
//    norains
//DATE:
//    Friday  20-August-2010
//Environment:
//    NULL
//=====================================================================

 

    最近在调试一个跨平台的界面库,突然发现,一直显示得很好的图片,居然在Windows CE6.0里面哑火了!出问题的是这行代码:

 

    

 

    调用GetLastError,根据返回的数值确认是句柄有误。句柄有误?奇了怪了。要知道,这行代码已经已经在Windows CE 5.0和Windows XP这两个架构不同的系统测试过,完全是正常的,怎么一到Windows CE 6.0就哑火了?再仔细查看,发现问题出在于GetModuleHandle函数!

 

    在说这问题之前,我们先看看程序的入口函数WinMain:

 

 

    我们只需要注意第一个形参hInstance,这个是进程的句柄。问题点就来了,在Windows CE 5.0和Windows XP中,调用GetModuleHandle(NULL)的返回值,和hInstance的数值是完全相同的;而对于Windows CE 6.0,情况就截然相反,返回的是一个不知道从哪里来的数值,该数值和hInstance根本扯不上边。如果将GetModuleHandle(NULL)用hInstance的数值代替,比如:

 

 

    那么在Windows CE 6.0中就能正常。

 

 那么,究竟Windows CE 6.0中,GetModuleHandle(NULL)返回的是个什么东西?查看MSDN,发现有这么一段描述:If this parameter is NULL, GetModuleHandle returns the process identifier of the calling process.
  
 如果是Windows CE 5.0,则是另外的解释:If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process.

 

    结果很明显,在Windows CE 5.0中,当GetModuleHandle的形参为NULL时,返回的是进程的实例句柄,而在Widows CE 6.0,返回的却是进程的ID!似乎一切都迎刃而解了,但实际上还没完。在Windows CE 6.0中,虽然说返回的是进程ID,但这个ID却不知道用在何处!因为如果直接将这返回值赋予OpenProcess,那么函数调用失败,因为GetModuleHandle的返回值和GetProcessID返回的截然不同,而后者却是能用于OpenProcess中!那么,究竟在Windows CE 6.0中的GetModuleHandle(NULL)返回值有何作用?我也不知道。如果读者大人您知道,麻烦一定要告诉我。

 

    先不讨论GetModuleHandle(NULL)的作用,我们还是先想想如何获得进程的实例句柄吧。难道我们一定要在WinMain函数中用一个全局变量保存hInstance数值,然后在整个程序中都用该全局变量?其实可以不用那么复杂,我们只要用GetCurrentProcessId替代就好。比如,之前的图片读取,可以如此:

 

 

    但是这行代码只能在Windows CE 5.0和Windows CE 6.0中运行,如果是放到Windows XP中则又是一个哑火,因为GetCurrentProcessId在Windows XP中的返回值并不是hInstance所代表的数值。

 

    最后,让我们以如下列表看看不同函数在不同系统中调用的迥异吧:

代码

WINCE5.0

WINCE6.0

WINXP

hInstance

0x63ab5fbe

0x050d001a

0x00400000

hGetModuleHandle =

GetModuleHandle(NULL)

0x63ab5fbe

0x00000042

0x00400000

hGetCurrentProcess =

GetCurrentProcess()

0x00000042

0x00000042

0xffffffff

dwGetCurrentProcessId =

GetCurrentProcessId()

0x63ab5fbe

0x050d001a

0x00001768

hOpenProcess_GetModuleHandle =

OpenProcess(0,

FALSE,

(DWORD)hGetModuleHandle)

0x63ab5fbe

0x00000000

0x00000000

hOpenProcess_GetCurrentProcessId =

OpenProcess(0,

FALSE,

dwGetCurrentProcessId)

0x63ab5fbe

0x004d4103

0x00000000

 

    该表格的测试代码如下:

 

    当然,还少不了实际调试时的IDE截图。

 

    首先是Windows CE 6.0:

  其次是Windows CE 5.0:

  

    最后是Windows XP:

 

 

    最后的最后,还是再一次看看LoadBitmap的调用。其实对于Windows CE 6.0,我们设置可以不用实例句柄,直接用NULL即可:

 

 

   不过呢,这样的调用方式在不同系统又有不同表现哦,如下表所示:
  

系统

LoadBitmap(NULL,MAKEINTRESOURCE(IDB_BITMAP1))

Windows XP

返回NULLerror code1814,找不到映像文件中指定的资源名。

Windows CE 5.0

返回NULLerror code6,句柄无效。

Windows CE 6.0

调用成功,能够正常获得图像句柄

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Delphi是一种集成开发环境(IDE),用于创建Windows应用程序。在Delphi中,可以使用编程语言(如Object Pascal)编写代码来处理各种任务,包括操作系统进程的管理。 要结束一个进程,可以使用Delphi中的一些函数和类来实现。其中一个方法是使用`TerminateProcess`函数,该函数会终止指定进程的执行。可以使用进程进程ID(PID)来标识要结束的进程。 以下是在Delphi中结束进程的简单示例代码: ```pascal {$APPTYPE CONSOLE} uses SysUtils, Windows; procedure TerminateProcessByName(const AProcessName: string); var ProcessID: DWORD; ProcessHandle: THandle; begin // 根据进程名称查找进程ID ProcessID := GetProcessByName(AProcessName); // 打开进程句柄 ProcessHandle := OpenProcess(PROCESS_TERMINATE, False, ProcessID); if ProcessHandle <> 0 then begin // 终止进程 TerminateProcess(ProcessHandle, 0); // 关闭进程句柄 CloseHandle(ProcessHandle); WriteLn('进程已成功终止!'); end else WriteLn('找不到该进程!'); end; begin try // 结束名为"zishen.exe"的进程 TerminateProcessByName('zishen.exe'); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. ``` 上述代码中,`TerminateProcessByName`过程接收进程名称作为参数,通过`GetProcessByName`函数查找进程ID,然后使用`OpenProcess`打开进程句柄。接着,`TerminateProcess`函数用于终止进程,`CloseHandle`关闭进程句柄。最后,显示终止结果。 需要注意的是,在使用`TerminateProcess`函数时需要小心,因为它会强制终止进程而不会进行任何清理工作。因此,建议在终止进程之前先和相关进程通信,并进行必要的资源释放。此外,必须谨慎使用这种操作,以防止意外关闭系统关键进程或其他危险情况的发生。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值