转自: http://blog.youkuaiyun.com/anycell/archive/2008/12/12/3505864.aspx
前两天遇到同样的问题,特转载。
-------------------------------------------
今天客户打来电话说我们公司的服务器程序在新装的64位Windows 2003上以系统服务方式启动不起来。初步怀疑是我们的32位服务程序哪个地方在64位机上不兼容了。结果忙活了一上午,终于找到了问题所在。程序里有一段代码是用来判断程序是以服务方式启动还是以窗口形式启动:在应用程序初始化时获得父进程的句柄。然后通过句柄获得父进程的执行程序全路径。如果全路径中存在"service.exe"字符串,则程序以服务方式启动。伪代码如下:
- HANDLE hParentProc; //Parent proccess handle initialize
- BOOL bRet; //Check if we should run it as service
- if(GetModuleFileNameEx(hParentProc, NULL, pszPath, MAX_PATH))
- {
- if(strstr(pszPath, "services.exe") != NULL)
- {
- bRet = TRUE;
- }
- }
于是我Google了一下,终于找到答案了:
当我们调用GetModuleFileNameEx的API函数时,为了获得指定进程的全路径,它内部需要访问进程的PEB头(process environment block),将PEB中的信息设置到一个叫 PROCESS_BASIC_INFORMATION 的结构体中。结构体声明如下
- typedef struct _PROCESS_BASIC_INFORMATION {
- NTSTATUS ExitStatus;
- PPEB PebBaseAddress;
- ULONG_PTR AffinityMask;
- KPRIORITY BasePriority;
- ULONG_PTR UniqueProcessId;
- ULONG_PTR InheritedFromUniqueProcessId;
- } PROCESS_BASIC_INFORMATION;
如果你的32位应用程序是运行在Windows XP或者以上的操作系统上的,推荐的解决方案是使用GetProccessImageFileName来替代GetModuleFileNameEx来取得进程的全路径,这个函数内部的内部操作不会像GetModuleFileName那样麻烦,只返回一个全路径字符串而已。但是返回的全路径是DOS格式的盘符路径( /Device/HarddiskVolumeX),因此需要自己再转换一下。
出了GetModuleFileNameEx之外,还有EnumProcessModule和 EnumProcessModuleEx 也会出现这样的问题,都是因为访问64位进程的PEB头的原因。 CreateToolHelpSnapshot调用失败原因也与上面的原理类似。
参考:http://winprogger.com/?p=26