抑制或拦截来自其他dll的CRT实例的CRT检查

|| 我的程序加载了几个dll并调用了它们的函数。 dll可以使用不同版本的CRT。 当C运行时检查参数的有效性并发现问题时,它将调用无效的参数句柄,依次使用或不使用“发送-不发送”对话框来关闭应用程序。 我尝试调用* _set_invalid_parameter_handler *,但只有在错误的dll中调用它时,它才有效。我尝试了SetErrorMode,但是我要做的就是在没有对话框的情况下杀死进程。 有什么办法可以处理这些异常?我不在乎某些资源是否受到损害。我只想允许用户保存配置。如果出现对话框,则单击该对话框并终止进程。 编辑 事实证明,加载所有版本的CRT或枚​​举所有DLL的解决方案均失败。为了清楚起见,下面是一个小示例: 这将是我的主要应用程序(我们将其称为文件application.c):
#include <windows.h>

void myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) {
   wprintf(L\"Invalid parameter detected in function %s. File: %s Line: %d\\n\", function, file, line);
   wprintf(L\"Expression: %s\\n\", expression);
}

void fixMyProblem() {
}

int main(int argc, char **argv) {
    HMODULE hModule = LoadLibrary(\"extension.dll\");
    void (WINAPI *function)() = GetProcAddress(hModule, \"function\");
    fixMyProblem();
    function();
}
该应用程序加载了一个执行不良操作的dll(不是我开发的,因此我不会接受任何解决方案告诉我修复那里的错误)。让我们将该文件扩展名命名为c。
#include <stdio.h>

__declspec(dllexport) void function() {
    printf(\"do bad stuff\");
    fopen(NULL, \"r\");
}
要进行编译,请执行以下操作:
cl extension.c /link /OUT:extension.dll /DLL
cl application.c
问题是我该如何在fixMyProblem()函数中执行操作,以便在XP上不会出现“发送/不发送”对话框,或者应用程序已在7上停止工作。 根据David Gladfelter的说法,我应该做
void fixMyProblem() {
    _set_invalid_parameter_handler(myInvalidParameterHandler);
}
并针对每个可用的CRT版本执行此操作。事实证明,即使使用一个单一版本的CRT(我对exe和dll都使用相同的版本),它仍然不起作用。它们都使用相同的CRT版本,但是似乎它们并不使用相同的CRT。 如果是这种情况,我假设我必须更改的内容在DLL内部。当然,它不会导出* _set_invalid_parameter_handler *。 但公平地说,这是他的解决方案的实现:
#include <Psapi.h>
#pragma comment(lib, \"Psapi.lib\")
void fixMyProblem() {
    HANDLE hProcess = GetCurrentProcess();
    HMODULE *hModules;
    DWORD requiredSize = 0;
    DWORD secondRequiredSize = 0;
    if (!EnumProcessModules(hProcess, NULL, 0, &requiredSize)) {
        printf(\"oops\\n\");
        return;
    }
    hModules = malloc(requiredSize);
    if (EnumProcessModules(hProcess, hModules, requiredSize, &secondRequiredSize)) {
        int i;
        int loadedModules = min(requiredSize, secondRequiredSize) / sizeof(HMODULE);
        for (i = 0; i < loadedModules; i++) {
            void *(WINAPI *_set_invalid_parameter_handler_function)(void *) = (void *(WINAPI *)(void *)) GetProcAddress(hModules[i], \"_set_invalid_parameter_handler\");
            if (_set_invalid_parameter_handler_function != NULL) {
                _set_invalid_parameter_handler_function(myInvalidParameterHandler);
                printf(\"fixed dll %d\\n\", i);
            }
        }
    } else {
        printf(\"oops\\n\");
    }
    free(hModules);
}
对于我的实际应用程序(不是此测试),我得到了1个固定的dll(msvcp90.dll)。它仍然不能解决我的问题。 对于解决此问题,我将不胜感激。     
已邀请:
如果dll是使用静态链接的CRT构建的,则CRT的状态和功能将在该dll实例本地。 我假设CRT使用的无效参数处理程序正在从OS调用“ 5”函数,以显示错误的“ nice”对话框。 您可以尝试钩住
UnhandledExceptionFilter
或ѭ7functions之类的函数,从而使dll使用您自己的函数代替。您可以通过分析已加载的dll的导入地址表,搜索您感兴趣的函数名称并更改地址以指向您的函数来执行此操作。     
您始终可以枚举过程中的模块,如果它是C运行时,则可以通过调用GetProcAddress来获取无效的参数处理程序。 但是,最好是从根本上修复bug。试图忽略此类问题通常只会导致进一步的问题,因为内存已损坏等等。     
您可以创建另一个DLL,该DLL使用与导致无效参数处理程序被调用的DLL使用的CRT版本相同的版本,并将无效参数处理程序注册到该新DLL中。无效的参数处理程序对于流程/ CRT版本组合是全局的。 如果您不知道DLL使用的是哪个版本,也无法弄清楚,最坏的情况是您创建多个DLL,每个CRT版本一个: VS 6静态/动态/多线程/单线程 VS.NET静态/动态/多线程/单线程 VS 2003静态/动态/多线程/单线程 VS 2005静态/动态 VS 2008静态/动态 VS 2010静态/动态 您可能将它们创建为静态.lib文件,并将它们全部链接到一个(非常混乱的)DLL中。     

要回复问题请先登录注册