tags:

views:

549

answers:

5

We have a Delphi 2007 COM component being executed from an ISAPI app. The COM component is hanging the app because it is attempting to display a MessageBox(). The call to MessageBox() must be occurring in the Delphi RTL becase it is not in our user code.

The app hangs, of course, because there is no one logged in at the server to clear the MessageBox().

How do we configure our Delphi project so that the Delphi RTL does not attempt to display MessageBox() on exception?

+1  A: 

I don't know of any direct way in Delphi but what you can do is write a small script in AutoIT/AutoHotKey and keep that script running in system tray, so that it will automatically close the MessageBox.

Believe me it is very simple.

http://www.autoitscript.com/autoit3/index.shtml

http://www.autohotkey.com/

HTH

Yogi Yang 007
That assumes the app has a desktop. This might not be the case.
Mihai Limbășan
I love Autohotkey .
Toby Allen
I don't think it is a non Desktop application.The poster is developing in Delphi and Delphi generates Desktop Apps only at present.
Yogi Yang 007
There's no desktop and no GUI. It's a COM component that is invoked from an ISAPI dll.You most certainly _can_ develop non-'Desktop Apps' in Delphi.The suggestion doesn't solve the issue, but might be a workaround to prevent hangs.
Ken Byington
+2  A: 

What does the messagebox say? I'm assuming it's an exception. Why don't you put an exception handler around the code in the COM component, and log the exception in a different way? (E.g., using the Event Log). And/or fix the problem that's leading to the exception in the first place.

Jim
No clue what the messagebox says. No way to view it since there no one logged in. Yes, it is an exception handler since those are the only MessageBox() calls in the RTL.
Ken Byington
My first thought was with Jim, make sure you're not the one showing a message box. Next thing is to ensure that you properly have all your COM methods tagged with `safecall`. This way **any** exception thrown during the method is caught by a try-catch implicitly added to the method, and the exception is returned as a E_FAIL HRESULT.
Ian Boyd
...because a rule of COM is that exceptions cannot be thown. And when you mark your methods as safecall, they compiler does your job for you, and wraps your code in a try-except and returns the exception in the implicit hresult return value.
Ian Boyd
But the exception doesn't happen in one of our COM component's methods. It's in the RTL's startup code. The exception occurs in InitUnits in System.pas which then calls FinializeUnits and then raise. When the exception is raised the RTL shows the MessageBox.
Ken Byington
+3  A: 

Write your own exception handler and attach it to the Application.OnException event. If an OnException event handler is present, Application won't use its default MessageBox routine. The signature is defined as:

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

If this is a server, you'll probably want to write the exception information to a log, and possibly return some error to the user.

Mason Wheeler
+1 This is the best way to handle the exception. If you are logging from a service, make sure that the IIS process has full rights to the location your logging to.
skamradt
That's all well and good, but if it's a COM component and it doesn't use the Forms unit, you don't even HAVE an Application reference. I have lots of in-process DLL COM servers, written in Delphi, that display no UI whatsoever.
Jim
Well, the basic principle is still the same. Somewhere in an outer loop you've got a default exception handler that's catching everything and displaying a message box. Maybe it's not an Application variable. Maybe it's just a simple try block like console applications use. Whatever it is, you have to find it and replace its functionality.
Mason Wheeler
There's no Application object since the COM component doesn't use either the Forms or SvcMgr unit. (And the Application object in the SvcMgr unit, which we use when we want to write to the event log, doesn't have an OnException event)The messagebox is being shown during initialization, somewhere in the RTL source. Can you use a try/except construct in the Initialization section of a COM component unit and wrap it around the Factory.Create() call? (Looks like the answer is yes)
Ken Byington
Sure. You can wrap a try block around pretty much anything. There's no "magic" going on here. If you can reproduce the conditions that raise the exception in the debugger, then do that, and trace through the stack unwinding until you find where it's being handled. (Build with debug DCUs on, of course.) Find the exception handler that's turning this into a dialog box, and place your own exception handler somewhere before this point to intercept it. Unless your COM server is structured in a very strange way, you should only have to place one if you find the right place to put it.
Mason Wheeler
If all else fails, you could change the RTL unit that's handling the exception. CodeGear doesn't recommend doing this, of course, since it makes upgrades a hassle, but it can be done if it's the only way, and it'll work.
Mason Wheeler
+1  A: 

I've created a unit to hook MessageBox/MessageDlg calls (via detouring), so I can suppress these calls in a Windows Service (to avoid "hanging" of my service dll because of some stupid code of someone else with a messagebox call in it). If you want it, I can search this unit and send it to you.

André
Yes, I'd like to see the code.
Ken Byington
what's your email, so I can send it to you?
André
kbyington at netrate dot comthanksIs it legal to use the Microsoft detour stuff without paying the $10,000 license fee?http://www.microsoft.com/iplicensing/productDetail.aspx?productTitle=Detours
Ken Byington
I send you an email.It does not use MS Detouring so you don't have to pay a license fee :-)
André
Could you please post the code in your answer? If not, apapadimoulis at inedo dot com.
Alex Papadimoulis
A: 

Is it possible to compile the application as a Console app? I'm not sure if you can do this and still have it contain COM object, this would prevent message dialogs from being shown I'm sure.

Just a thought.

Toby Allen
According to help, {$APPTYPE CONSOLE} has no meaning in a .dll.'The $APPTYPE directive is meaningful only in a program. It should not be used in a library, unit, or package.'
Ken Byington