代码中列出msvcrXXX.dll的版本

本文关键字:dll 版本 msvcrXXX 代码 | 更新日期: 2023-09-27 18:19:21

我想从MS Visual Studio C运行时dll中导入一个函数,以便使用p/Invoke从c#调用它。但是,为了健壮性,我不想在我的DllImport属性中硬编码运行时库的版本。

我如何列出当前进程中加载的msvcrXXX.dll的版本,最好使用c#代码?

并且,一旦我有了名称列表,我如何在运行时加载给定dll名称的特定函数?

代码中列出msvcrXXX.dll的版本

您可以使用以下Win32 api:
获取当前进程中的所有模块
GetModuleBaseName:获取模块basename,并查找是否与mscrtxxxx.dll匹配
GetProcAddress:获取mscrtxxx.dll

中的函数指针

这里是示例代码,

HANDLE hProcess = GetCurrentProcess();
DWORD numBytesRequried = 0;
if(!EnumProcessModules(hProcess, NULL, 0, &numBytesRequried))
    return -1;
HMODULE* phModules = new HMODULE[numBytesRequried/sizeof(HMODULE)];
if (!EnumProcessModules(hProcess, phModules, numBytesRequried, &numBytesRequried))
{
    delete [] phModules;
    return -1;
}
int mscrtver = -1;
MODULEINFO mscrtModuleInfo;
HMODULE hModuleMSVCRT = NULL;
TCHAR szModuleBaseName[MAX_PATH];
for(int i=0;i<numBytesRequried/sizeof(HMODULE);i++)
{
    if (GetModuleBaseName(hProcess, phModules[i], szModuleBaseName, _countof(szModuleBaseName)) == 0)
        continue;
    _tcsupr_s(szModuleBaseName, MAX_PATH);
    TCHAR* szFileName = _tcsrchr(szModuleBaseName, _T(''''));
    if (szFileName != NULL)
        szFileName++;
    else
        szFileName = szModuleBaseName;
#ifdef _DEBUG
    if (_stscanf_s(szFileName, _T("MSVCR%dd.dll"), &mscrtver) == 1)
#else
    if (_stscanf_s(szFileName, _T("MSVCR%d.dll"), &mscrtver) == 1)
#endif
    {
        hModuleMSVCRT = phModules[i];
        break;
    }
}
delete [] phModules;
phModules = NULL;
if (mscrtver < 0 || hModuleMSVCRT == NULL)
    return -1;
printf("MSCRT VER: %d.%d'r'n", mscrtver/10, mscrtver%10);
typedef size_t (*funcptr_strlen)(const char*);
funcptr_strlen funcptr_test = (funcptr_strlen)GetProcAddress(hModuleMSVCRT, "strlen");
if (funcptr_test != NULL) 
{
    int test_ret = funcptr_test("abc");
    printf("test ret: %d.'r'n", test_ret);
}

这是在我的电脑上运行的输出:
MSCRT server: 11.0
3.