在 Delphi 中捕获 MSVCR120 丢失的错误消息
Catch MSVCR120 missing error message in Delphi
我写了一个无人值守的 HTTPS 上传客户端,它不需要用户交互。
一切都很完美,直到我盲目地将它部署到一个我没有远程桌面访问权限的远程系统。该工具在日志中报告缺少 SSL 库。
好的,我将LIBEAY32.dll
和SSLEAY32.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.
我写了一个无人值守的 HTTPS 上传客户端,它不需要用户交互。
一切都很完美,直到我盲目地将它部署到一个我没有远程桌面访问权限的远程系统。该工具在日志中报告缺少 SSL 库。
好的,我将LIBEAY32.dll
和SSLEAY32.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.