c++ - 如何根据windows版本正确加载GetMappedFileName

标签 c++ windows winapi windows-7 windows-xp

MSDN的备注部分,描述here ,特别提到以下函数的加载类型之间存在差异。

由于我的模块是可移植的并且动态加载模型,所以我不允许/不能使用任何预处理器命令:

#if (PSAPI_VERSION == 2)
            (GetProcAddress("kernel32.dll", OBFUSCATE(L"K32GetMappedFileNameW")));
#elif (PSAPI_VERSION == 1)
            (GetProcAddress("psapi.dll", OBFUSCATE(L"GetMappedFileNameW")));
#endif

此外——

Kernel32.dll on Windows 7 and Windows Server 2008 R2; Psapi.dll (if PSAPI_VERSION=1) on Windows 7 and Windows Server 2008 R2; Psapi.dll on Windows Server 2008, Windows Vista, Windows Server 2003, and Windows XP

并没有更清楚地说明 Windows 版本如何与 PSAPI 版本完全协调。

最佳答案

GetMappedFileName() documentation具体说:

Starting with Windows 7 and Windows Server 2008 R2, Psapi.h establishes version numbers for the PSAPI functions. The PSAPI version number affects the name used to call the function and the library that a program must load.

If PSAPI_VERSION is 2 or greater, this function is defined as K32GetMappedFileName in Psapi.h and exported in Kernel32.lib and Kernel32.dll. If PSAPI_VERSION is 1, this function is defined as GetMappedFileName in Psapi.h and exported in Psapi.lib and Psapi.dll as a wrapper that calls K32GetMappedFileName.

Programs that must run on earlier versions of Windows as well as Windows 7 and later versions should always call this function as GetMappedFileName. To ensure correct resolution of symbols, add Psapi.lib to the TARGETLIBS macro and compile the program with -DPSAPI_VERSION=1. To use run-time dynamic linking, load Psapi.dll.

如果静态链接不适合您,并且您需要在运行时动态加载函数而不使用 #ifdef 语句,那么只需无条件地检查两个 DLL,例如:

typedef DWORD WINAPI (*LPFN_GetMappedFileNameW)(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, DWORD nSize);

HINSTANCE hPsapi = NULL;
LPFN_GetMappedFileNameW lpGetMappedFileNameW = NULL; 

...

lpGetMappedFileNameW = (LPFN_GetMappedFileNameW) GetProcAddress(GetModuleHandle("kernel32.dll"), L"K32GetMappedFileNameW"));
if (lpGetMappedFileNameW == NULL)
{
    hPsapi = LoadLibraryW(L"psapi.dll");
    lpGetMappedFileNameW = (LPFN_GetMappedFileNameW) GetProcAddress(hPsapi, L"GetMappedFileNameW");
}

// use lpGetMappedFileNameW() as needed ...

if (hPsapi)
    FreeLibrary(hPsapi);

或者,按照文档中的说明操作 - 完全忽略 kernel32 并在所有 Windows 版本上单独使用 psapi.dll。在 Windows 7 及更高版本上,psapi.GetMappedFileNameW()kernel32.K32GetMappedFileNameW() 的包装器。

typedef DWORD WINAPI (*LPFN_GetMappedFileNameW)(HANDLE hProcess, LPVOID lpv, LPWSTR lpFilename, DWORD nSize);

HINSTANCE hPsapi = NULL;
LPFN_GetMappedFileNameW lpGetMappedFileNameW = NULL;

...

hPsapi = LoadLibraryW(L"psapi.dll");
lpGetMappedFileNameW = (LPFN_GetMappedFileNameW) GetProcAddress(hPsapi, L"GetMappedFileNameW");

// use lpGetMappedFileNameW() as needed ...

FreeLibrary(hPsapi);

关于c++ - 如何根据windows版本正确加载GetMappedFileName,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29369597/

相关文章:

c++ - 使用多个显示器 - XOpenDisplay(NULL) 有时会无法获取窗口的当前显示吗?

c++ - 文件输入的访问冲突读取位置

windows - initdb : could not execute command, postgres.exe"--boot -x1 -F ": 没有错误

java - 摆脱 Windows 典型样式?

c++ - 如何为 UNC 路径制作长 Unicode 版本?

C++:声明、定义和调用返回模板类对象的函数?

c++ - 如何在 Windows 上记录击键 [C++]

c++ - 从热键启动时 SendInput 到 Ctrl+C 文本不起作用

C++ 设置动态创建数组的值失败

无法在 Windows 7 x64 上编译 C