在 Delphi 中捕获 MSVCR120 丢失的错误消息

Catch MSVCR120 missing error message in Delphi

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

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

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

在屏幕截图上,我看到来自 csrss.exe 进程的模态 window 消息:

The program can't start because MSVCR120.dll is missing from your computer.

尽管有很多 try except 块和 Application.OnException 处理程序,window 还是出现了。

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

如何实现?

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

P.S。我通过将 DLL 复制到 app 文件夹解决了缺少 DLL 的问题,但我的问题是关于捕获此类错误。

为避免此错误,您可以使用 https://indy.fulgan.com/SSL/

上可用的 OpenSSL DLL

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

或者,使用 TNetHTTPClient

来自

TNetHTTPClient was introduced in Delphi XE8.

The most important benefit of TNetHTTPClient is that it allows your application to support HTTPS without having to provide your own support for SSL/TLS. TNetHTTPClient relies on the SSL/TLS support provided by the operating system.

利用 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.