如何正确加载基于Windows版本的GetMappedFileName

MSDN的备注部分, 在这里描述,具体提到有以下函数的加载types之间的区别。

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

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

此外 –

Windows 7和Windows Server 2008 R2上的Kernel32.dll; Windows 7和Windows Server 2008 R2上的Psapi.dll(如果PSAPI_VERSION = 1); Windows Server 2008,Windows Vista,Windows Server 2003和Windows XP上的Psapi.dll

Windows版本如何与PSAPI版本完全协调,并没有让它变得更清晰。

GetMappedFileName()文档具体说:

从Windows 7和Windows server 2008 R2开始,Psapi.h为PSAPI函数建立版本号。 PSAPI版本号会影响用于调用函数的名称和程序必须加载的库

如果PSAPI_VERSION为2或更大,则此函数在Psapi.h中定义为K32GetMappedFileName,并在coreel32.lib和coreel32.dll中导出 。 如果PSAPI_VERSION是1,则此函数在Psapi.h中定义为GetMappedFileName,并作为调用K32GetMappedFileName的包装器导出到Psapi.lib和Psapi.dll中

必须在早期版本的Windows以及Windows 7和更高版本上运行的程序应始终将此函数作为GetMappedFileName调用。 为了确保符号的正确解析,将Psapi.lib添加到TARGETLIBS宏,并使用-DPSAPI_VERSION = 1编译程序。 要使用运行时动态链接,请加载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(GetmoduleeHandle("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);