EnumProcesses / EnumProcessModules API 사용 시 주의점
관련 도움말을 보면,
EnumProcessModules
; https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocessmodules
분명히 지원 운영체제가 Windows XP/2003 이상이라고 나옵니다. 하지만 실제로 사용해 보면, Windows 7/2008 R2 이상에서만 해당 API들이 (실행 시) 정상적으로 import됩니다.
그 이유는, 최근의 Windows SDK에 있는 psapi.h 파일이 다음과 같이 매크로 정의로 "K32..." API로 우회하고 있기 때문입니다.
#define EnumProcesses K32EnumProcesses
#define EnumProcessModules K32EnumProcessModules
원래 EnumProcesses / EnumProcessModules API들은 psapi.dll에 있는데, K32... API들은 kernel32.dll로 옮겨졌습니다. 즉, Windows XP/2003/Vista/2008까지는 psapi.dll에 포함되어 있지만 그 이후의 버전에는 psapi.dll의 것들은 껍데기이고 kernel32.dll에 있는 API로 우회하도록 되어 있습니다.
아울러, 최근의 Windows SDK들은 psapi.dll의 껍데기를 호출하지 않고 곧바로 kernel32.dll에 있는 K32EnumProcesses / K32EnumProcessModules API들을 호출할 수 있도록 저렇게 macro 정의를 하고 있는 것입니다.
그렇기 때문에 Visual Studio 구 버전에서 빌드하면 API를 담고 있는 DLL/EXE들이 잘 사용이 되는 반면, 동일한 소스 코드를 최신 버전의 Visual Studio에서 빌드하면 해당 DLL/EXE는 다음과 같은 식으로 K32... 류의 API와 바인딩되어 있기 때문에,
XP/2003/Vista/2008에서는 실행할 수 없게 되는 것입니다.
이를 해결하려면, 명시적으로 EnumProcesses 이름 그대로 사용해야 하는데 방법은 PSAPI_VERSION 버전을 낮춰주면 됩니다.
#undef PSAPI_VERSION
#define PSAPI_VERSION 1
#include <Psapi.h>
#pragma comment(lib, "psapi.lib")
참고로, 이런 식으로 매핑된 API들이 몇 개 있기 때문에 사용에 주의를 요합니다.
#if (PSAPI_VERSION > 1)
#define EnumProcesses K32EnumProcesses
#define EnumProcessModules K32EnumProcessModules
#define EnumProcessModulesEx K32EnumProcessModulesEx
#define GetModuleBaseNameA K32GetModuleBaseNameA
#define GetModuleBaseNameW K32GetModuleBaseNameW
#define GetModuleFileNameExA K32GetModuleFileNameExA
#define GetModuleFileNameExW K32GetModuleFileNameExW
#define GetModuleInformation K32GetModuleInformation
#define EmptyWorkingSet K32EmptyWorkingSet
#define QueryWorkingSet K32QueryWorkingSet
#define QueryWorkingSetEx K32QueryWorkingSetEx
#define InitializeProcessForWsWatch K32InitializeProcessForWsWatch
#define GetWsChanges K32GetWsChanges
#define GetWsChangesEx K32GetWsChangesEx
#define GetMappedFileNameW K32GetMappedFileNameW
#define GetMappedFileNameA K32GetMappedFileNameA
#define EnumDeviceDrivers K32EnumDeviceDrivers
#define GetDeviceDriverBaseNameA K32GetDeviceDriverBaseNameA
#define GetDeviceDriverBaseNameW K32GetDeviceDriverBaseNameW
#define GetDeviceDriverFileNameA K32GetDeviceDriverFileNameA
#define GetDeviceDriverFileNameW K32GetDeviceDriverFileNameW
#define GetProcessMemoryInfo K32GetProcessMemoryInfo
#define GetPerformanceInfo K32GetPerformanceInfo
#define EnumPageFilesW K32EnumPageFilesW
#define EnumPageFilesA K32EnumPageFilesA
#define GetProcessImageFileNameA K32GetProcessImageFileNameA
#define GetProcessImageFileNameW K32GetProcessImageFileNameW
#endif
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]