Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
防止Delphi COM组件显示MessageBox()_Delphi_Com_Isapi - Fatal编程技术网

防止Delphi COM组件显示MessageBox()

防止Delphi COM组件显示MessageBox(),delphi,com,isapi,Delphi,Com,Isapi,我们有一个Delphi2007 COM组件正在从ISAPI应用程序执行。COM组件挂起应用程序,因为它正试图显示MessageBox()。对MessageBox()的调用必须发生在Delphi RTL中,因为它不在我们的用户代码中 应用程序当然会挂起,因为服务器上没有人登录以清除MessageBox() 我们如何配置我们的Delphi项目,使Delphi RTL不会尝试在异常时显示MessageBox()?我不知道Delphi中有任何直接的方法,但您可以做的是在AutoIT/AutoHotKey

我们有一个Delphi2007 COM组件正在从ISAPI应用程序执行。COM组件挂起应用程序,因为它正试图显示MessageBox()。对MessageBox()的调用必须发生在Delphi RTL中,因为它不在我们的用户代码中

应用程序当然会挂起,因为服务器上没有人登录以清除MessageBox()


我们如何配置我们的Delphi项目,使Delphi RTL不会尝试在异常时显示MessageBox()?

我不知道Delphi中有任何直接的方法,但您可以做的是在AutoIT/AutoHotKey中编写一个小脚本,并使该脚本在系统托盘中运行,以便它将自动关闭MessageBox

相信我,这很简单


HTH

消息框上写了什么?我想这是个例外。为什么不在COM组件中的代码周围放置一个异常处理程序,并以不同的方式记录异常?(例如,使用事件日志)。和/或首先修复导致异常的问题。

编写自己的异常处理程序并将其附加到Application.OneException事件。若存在OneException事件处理程序,应用程序将不会使用其默认MessageBox例程。签名的定义如下:

TExceptionEvent = procedure (Sender: TObject; E: Exception) of object;

如果这是一台服务器,您可能希望将异常信息写入日志,并可能向用户返回一些错误。

我已经创建了一个单元来钩住MessageBox/MessageDlg调用(通过绕行),因此我可以在Windows服务中抑制这些调用(以避免“挂起”)因为其他人的一些愚蠢代码中有messagebox调用)。
如果您需要,我可以搜索此单元并将其发送给您。

是否可以将该应用程序编译为控制台应用程序?我不确定您是否可以这样做,并且仍然让它包含COM对象,我确定这将阻止显示消息对话框



只是一个想法。

假设应用程序有一个桌面。可能不是这样。我不认为它是一个非桌面应用程序。海报是在Delphi中开发的,Delphi目前只生成桌面应用程序。没有桌面,也没有GUI。它是从ISAPI dll调用的COM组件。您当然可以在Delphi中开发非“桌面应用程序”。该建议不能解决问题,但可能是防止挂起的一种解决方法。+1这是处理异常的最佳方法。如果您是从服务进行日志记录,请确保IIS进程对您的日志记录位置具有完全权限。这很好,但如果它是COM组件且不使用表单单元,则您甚至没有应用程序引用。我有很多用Delphi编写的进程内DLL COM服务器,它们不显示任何UI。好吧,基本原理还是一样的。在外部循环的某个地方,您有一个默认的异常处理程序,它捕获所有内容并显示一个消息框。也许它不是一个应用程序变量。也许这只是控制台应用程序使用的一个简单的try块。不管它是什么,您都必须找到它并替换它的功能。因为COM组件既不使用表单也不使用SvcMgr单元,所以没有应用程序对象。(SvcMgr单元中的应用程序对象(我们在写入事件日志时使用该对象)没有OneException事件)messagebox在初始化期间显示在RTL源中的某个位置。能否在COM组件单元的初始化部分使用try/except构造,并将其包装在Factory.Create()调用中?(看起来答案是肯定的)当然。你几乎可以用try块包住任何东西。这里没有“魔法”。如果可以在调试器中重现引发异常的条件,那么就这样做,并跟踪堆栈展开,直到找到处理异常的位置。(当然,在调试DCU打开的情况下构建。)找到将此转换为对话框的异常处理程序,并将您自己的异常处理程序放置在该点之前的某个位置以拦截它。除非你的COM服务器是以一种非常奇怪的方式构造的,否则你应该只需要在找到合适的位置时放置一个。不知道messagebox上说了什么。无法查看,因为没有人登录。是的,这是一个异常处理程序,因为这些是RTL中唯一的MessageBox()调用。我的第一个想法是与Jim一起,确保您不是显示消息框的人。下一件事是确保所有COM方法都正确地标记了
safecall
。这样,在方法期间引发的任何异常都会被隐式添加到方法中的try-catch捕获,并且该异常会作为E_FAIL HRESULT返回……因为COM的规则是,不能处理异常。当您将方法标记为safecall时,编译器会为您完成工作,并将代码包装为try-except,然后在隐式hresult返回值中返回异常。但是,在我们的COM组件的方法中没有发生异常。它在RTL的启动代码中。异常发生在System.pas中的InitUnits中,然后调用FinalizeUnits,然后引发。当引发异常时,RTL显示MessageBox。根据帮助,{$APPTYPE CONSOLE}在.dll中没有任何意义$APPTYPE指令仅在程序中有意义。不应在图书馆、单位或包裹中使用。您的电子邮件是什么,我可以发送给您?netrate.com的Kbyngton感谢您,在不支付10000美元许可费的情况下使用Microsoft detour工具合法吗?我给你发了一封电子邮件。它不使用MS Detouring,因此您无需支付许可费:-)您可以在回答中发布代码吗?如果没有,请访问inedo.com的apapadimoulis。