【问题标题】:Catch MSVCR120 missing error message in Delphi在 Delphi 中捕获 MSVCR120 缺少错误消息
【发布时间】:2018-10-27 07:11:22
【问题描述】:

我编写了一个不需要用户交互的无人值守 HTTPS 上传客户端。

在我盲目地将它部署到我没有远程桌面访问权限的远程系统之前,一切都完美无缺。该工具在日志中报告 SSL 库丢失。

好的,我将LIBEAY32.dllSSLEAY32.dll 部署到远程系统上的应用程序文件夹,但随后该工具挂起,直到我编写了一个制作远程屏幕截图的工具,我才弄清楚发生了什么。

在屏幕截图中,我看到来自csrss.exe 进程的模态窗口,其中包含一条消息:

程序无法启动,因为您的计算机中缺少 MSVCR120.dll。

尽管有很多 try except 块和 Application.OnException 处理程序,但仍出现了窗口。

我希望在这种情况下应用程序不会被阻止,以便它可以向其日志报告失败。

如何做到这一点?

在当前的实现中,TIdHttp.Post 调用只是挂起。

附:我通过将 DLL 复制到 app 文件夹解决了它的缺失问题,但我的问题是关于捕获此类错误。

【问题讨论】:

  • iirc 有一些 OpenSSL DLL 版本具有这种依赖性,而另一些则没有。你是从 indy.fulgan.com 下载的吗?
  • @mjn42:我只是从以前的开发人员那里继承了它们。你的意思是模态窗口调用只是内置在 SSL 库中吗?
  • @David Heffernan:谁知道其他一些 Windows 安装可能还缺少什么。我不知道所有的依赖关系。我花了一周的时间才弄清楚远程系统上发生了什么,并且计划安装 200 个,它们都是远程的。
  • @Paul 了解依赖关系是您的工作。 Windows 安装中没有丢失这些文件。您的软件部署中缺少它们。您绝对需要了解软件的依赖关系。
  • @Paul 您有责任了解您部署的可执行文件的依赖关系。在部署之前很容易获得此信息。至于手头的问题,由于 Indy 在运行时动态加载 OpenSSL,您可以通过在加载 DLL 之前调用 Win32 API Set(Thread)ErrorMode() 函数来禁用弹出对话框。 .

标签: delphi ssl exception-handling msvcr120.dll


【解决方案1】:

为避免此错误,您可以使用https://indy.fulgan.com/SSL/ 上提供的 OpenSSL DLL

他们对 MSVCRT 没有这种依赖性。

或者,使用TNetHTTPClient

来自this answer

TNetHTTPClient 是在 Delphi XE8 中引入的。

TNetHTTPClient 最重要的好处是它允许你 应用程序来支持 HTTPS,而无需提供您自己的 支持 SSL/TLS。 TNetHTTPClient 依赖于 SSL/TLS 支持 由操作系统提供。

【讨论】:

    【解决方案2】:

    使用 Remy Lebeau 评论中的信息,我在 Delphi 6 中试验了SetErrorMode 函数。

    设置由三个项目组成:

    • 宿主应用程序,动态链接调用者 DLL,
    • 调用者 DLL,静态链接工作 DLL,
    • 和一个工作 DLL。

    首先我将两个 DLL 都放在主机应用程序文件夹中,测试一切正常,然后删除工作 DLL 并在没有它的情况下进行测试。

    这里有一些代码:

    宿主应用程序

    program MyHost;
    
    uses
      Windows, SysUtils;
    
    var
      hLib: HMODULE;
    
    procedure Box(msg: WideString);
    begin
      MessageBoxW(0, PWideChar(msg), 'MyHost Message', 0);
    end;
    
    procedure ShowLastError();
    begin
      Box('LastError: ' + SysErrorMessage(GetLastError()));
    end;
    
    type
      TDoWork = procedure();
    
    var
      DoWork: TDoWork;
    
    begin
      SetErrorMode(SEM_FAILCRITICALERRORS);
      try
        {Without SetErrorMode it displays modal dialog.
         No exception is generated.
         After clicking at [Ok], it goes to "if hLib = 0".
         With SetErrorMode it just goes to "if hLib = 0"}
        hLib := LoadLibrary('CallerLib.dll');
        if hLib = 0 then begin
          ShowLastError();
          Halt(1);
        end;
        try
          @DoWork := GetProcAddress(hLib, 'DoWork');
          if @DoWork <> nil then DoWork();
        finally
          FreeLibrary(hLib);
        end;
      except
        on ex: Exception do Box(ex.ClassName + ': ' + ex.Message);
      end;
    end.
    

    调用者 DLL

    library CallerLib;
    
    uses
      Windows;
    
    //Static linking
    procedure Function1(); stdcall; external 'MyLib.dll';
    procedure Function2(); stdcall; external 'MyLib.dll';
    
    //To be dynamically linked
    procedure DoWork(); stdcall; export;
    begin
      Function1();
      Function2();
    end;
    
    exports
      DoWork;
    
    end.
    

    工作 DLL

    library MyLib;
    
    uses
      Windows;
    
    procedure Function1(); stdcall; export;
    begin
      MessageBox(0, 'MyDLL.Function1', 'MyDLL', 0);
    end;
    
    procedure Function2(); stdcall; export;
    begin
      MessageBox(0, 'MyDLL.Function2', 'MyDLL', 0);
    end;
    
    exports
      Function1, Function2;
    
    end.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-21
      相关资源
      最近更新 更多