0

I want to import a function from the MS Visual Studio C runtime dll in order to call it from C# using P/Invoke. However, for the sake of robustness, I don't want to hard code the version of the runtime library in my DllImport attribute.

How do I list the versions of msvcrXXX.dll's loaded in the current process, preferably using C# code?

And, once I have the list of names, how do I load a particular function given the name of a dll, at runtime?

Phillip Ngan
  • 15,482
  • 8
  • 63
  • 79

1 Answers1

0

You can use below Win32 APIs:
EnumProcessModules: Get all modules in current process
GetModuleBaseName: Get the module basename, and find whether it match mscrtxxxx.dll
GetProcAddress: Get the function pointer in mscrtxxx.dll

Here is sample codes for you,

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);
}

Here is running output in my PC:
MSCRT VER: 11.0
test ret: 3.

ravin.wang
  • 1,122
  • 1
  • 9
  • 26