Windows Delphi应用程序与偶尔会崩溃的程序通信-供应商指责我的Delphi应用程序
我已经编写了一个Delphi DLL,它通过COM与第三方程序通信。一些用户报告说,第三方程序偶尔会崩溃。其他以相同方式使用该软件的人从未经历过崩溃。发生此崩溃时,第三方程序在我的DLL应用程序中似乎变得不可用 供应商发誓这是Delphi DLL如何编码的问题,尽管他们没有看到源代码,也不能说出DLL是如何导致崩溃的,但他们知道这是“什么” 除了我认为第三方程序不应该因为我的DLL中的一些小问题而崩溃之外,让我们假设我的DLL中有一些东西需要修复Windows Delphi应用程序与偶尔会崩溃的程序通信-供应商指责我的Delphi应用程序,windows,performance,delphi,debugging,com,Windows,Performance,Delphi,Debugging,Com,我已经编写了一个Delphi DLL,它通过COM与第三方程序通信。一些用户报告说,第三方程序偶尔会崩溃。其他以相同方式使用该软件的人从未经历过崩溃。发生此崩溃时,第三方程序在我的DLL应用程序中似乎变得不可用 供应商发誓这是Delphi DLL如何编码的问题,尽管他们没有看到源代码,也不能说出DLL是如何导致崩溃的,但他们知道这是“什么” 除了我认为第三方程序不应该因为我的DLL中的一些小问题而崩溃之外,让我们假设我的DLL中有一些东西需要修复 我如何确定我的应用程序可能导致这种情况?有没有人
我如何确定我的应用程序可能导致这种情况?有没有人有过通过COM与这种超敏感程序通信的经验?是否有一些常见的东西可能会导致第三方程序崩溃?如果他们的程序在您使用他们发布的界面时崩溃,我很确定这是有问题的。证明这完全是另一回事 你能用一个小的Delphi应用程序可靠地复制这个问题吗?看到可重现的故障有助于说服他们需要进行修复。至少,这有助于查明他们认为你做得“不对”的地方,并告诉你如何做得“对” 您还可以尝试使用C#甚至VBScript复制故障
Loaded DLL
Started MyFunction1 with parameters: 1,4,hello
1
2
...
500
Ended MyFunction1
为了做到这一点,,,我设置了一些函数(在它们自己的单元中):
你可以这样称呼它:
function MyFunction1(Integer,Integer,String);
begin
try
Log('Loaded DLL');
//use inttostr and do some string concats to get the params
Log('Started MyFunction1 with parameters: 1,4,hello',true);
//Then every other line:
Log;
//this would increment a global variable FuncLine:Integer
//and write it to the file.
except
On E:Exception (Log('***'+E.Message));
end;
end;
except
on e: Exception do
begin
MadExcept.HandleException();
raise EOleSysError.Create('InitializeObject Failed',
ErrorNumberToHResult(1 + CODE_BASE), 1);
end;
try
raise exception.create('test');
except
//eat exception
end;
类似的东西应该有一个{$DEFINE}来启用这些日志功能,启用/禁用诊断日志
查看质量中心的58409报告 这是关于FPU掩码和Dll的 简而言之: FPU掩码的设置决定如何处理浮点异常 例如,如果您有一个应用程序_A(由其他人编码),它加载Dll_A(也由其他人编码)和Dll_B(由您编码),并且您的Dll更改了FPU掩码,则此更改也对应用程序_A和Dll_A有效 让我们举个例子: 您已经安装了WinZIP、SubVersion等,在windows文件资源管理器(鼠标右键单击弹出菜单)中注册了其他功能,现在您可以从application.exe内部调用TOpenDialog,那么这些附加功能可能会损害您的FPU设置 希望这有帮助。 (附加提示:使用Sysinternal查看应用程序加载了哪些dll)您考虑过使用吗?如果在接口方法中发现错误,则可以记录调用堆栈或向用户显示对话框,并将标准EOleSysError返回到调用exe 大概是这样的:
function MyFunction1(Integer,Integer,String);
begin
try
Log('Loaded DLL');
//use inttostr and do some string concats to get the params
Log('Started MyFunction1 with parameters: 1,4,hello',true);
//Then every other line:
Log;
//this would increment a global variable FuncLine:Integer
//and write it to the file.
except
On E:Exception (Log('***'+E.Message));
end;
end;
except
on e: Exception do
begin
MadExcept.HandleException();
raise EOleSysError.Create('InitializeObject Failed',
ErrorNumberToHResult(1 + CODE_BASE), 1);
end;
try
raise exception.create('test');
except
//eat exception
end;
如果应用程序挂起但未抛出和异常,则可以使用MadException实用程序madTraceProcess查看发生的情况。这将允许您为正在运行的应用程序生成调用堆栈。您的dll将不在主线程上,但您将能够看到您的调用堆栈。当挂起发生时,这是一个很好的方法来判断dll是否真的在做任何事情
我有一个COM dll,它可以与不使用MadExcept的exe进行交互,这种方法对我来说非常有效。如果我正确地理解了这种情况,那么如果dll没有崩溃,并且被调用的第三方程序停止响应,您就没有什么可以做的了。崩溃在他们的代码中,但仅由DLL调用它触发。调试日志确实应该在他们的应用程序中完成。
不过,您可以做的是使用参数和一些上下文信息记录DLL对此第三方程序的所有调用。
然后看看坠机前的最后一条线索可能会给你一些信息…我不知道MADEEXPECT是如何工作的,但我经常使用jclDebug.pas+JclHookExcept.pas(来自绝地JCL库)。它创建了一个Windows API挂钩,因此它可以捕获所有(!)异常,即使您创建了如下内容:
function MyFunction1(Integer,Integer,String);
begin
try
Log('Loaded DLL');
//use inttostr and do some string concats to get the params
Log('Started MyFunction1 with parameters: 1,4,hello',true);
//Then every other line:
Log;
//this would increment a global variable FuncLine:Integer
//and write it to the file.
except
On E:Exception (Log('***'+E.Message));
end;
end;
except
on e: Exception do
begin
MadExcept.HandleException();
raise EOleSysError.Create('InitializeObject Failed',
ErrorNumberToHResult(1 + CODE_BASE), 1);
end;
try
raise exception.create('test');
except
//eat exception
end;
通常你不会看到这个异常,因为它被“吃掉”。。。但有了钩子,你会得到所有的例外。例如:我有一次在Midas.dll中遇到了一个“灾难性的失败”,通过这个钩子,我在这个异常之前看到了dll中的一个“数据库连接丢失”错误,所以我知道发生了什么。(顺便说一句:JclHookExcept.pas=hook,jclDebug.pas=strack跟踪)
现在我看到JclHookExcept.pas还有一个“JclHookExceptionsInModule”过程,所以您可以强制(?)钩住特定库中的所有异常
一些演示代码:
procedure AnyExceptionNotify(ExceptObj: TObject; ExceptAddr: Pointer; OSException: Boolean);
begin
//log exception
end;
initialization
// Start Exception tracking
JclStartExceptionTracking;
JclTrackExceptionsFromLibraries;
JclStackTrackingOptions := [stStack, stRawMode, stAllModules];
// Assign notification procedure for hooked RaiseException API call. This
// allows being notified of any exception
JclAddExceptNotifier(AnyExceptionNotify);
我非常同意。我以前多次到过这个地方,最快的解决方案总是创建一个新的可重复测试程序,并将其提供给具有完整源代码的供应商。如果可能的话,记录与API的所有交互(传递的参数和返回的参数)。供应商说Dave的DLL是错误的。供应商是应该制定测试程序的人,而不是Dave,因为供应商才是真正看到问题的人。如果不是一个测试程序,那么至少有一个步骤列表来说明问题。我认为供应商没有看到这一点。我以为是戴夫的顾客。无论如何,我同意vendo