Access violation on shutdown from hidden TWebBrowser - delphi

Scenario:
A TPageControl with two TTabSheets
A TWebBrowser on the non-visible tab sheet
WebBrowser->Navigate called during form creation
If the user simply runs the form and exits, then during application shutdown, an access violation is generated:
First chance exception at $507C1413. Exception class $C0000005 with message 'access violation at 0x507c1413: read of address 0x00000010'. Process Project1.exe (3464)
The call stack in the debugger contains only a single entry, which suggests that the call stack is being corrupted:
:507c1413 ; C:\Program Files (x86)\Embarcadero\Studio\16.0\bin\vcl220.bpl
(Another application shows the call stack as having a single entry of IsFormSizeStored.)
Switching to the browser's tab sheet, either in code or in the UI, avoids the problem. Not calling Navigate avoids the problem.
Observed in XE4 and XE8.
What's the best way of fixing this?

Following #TOndrej's suggestion, I added a FormClose event handler to delete the TWebBrowser control before the application shuts down.
This issue has been logged on the RAD Studio Quality Portal.

Related

Why do datasource of database-controls dissapear when Delphi crashes

I'm using Delphi 10.4.1 Enterprise and wrote a VCL program using an SQLite database.
As I suspect a OneDrive issue, I mention that the source code folder is part of the zone managed by OneDrive.
At times, whilst debugging, my Delphi program hangs for unknown reasons, and Delphi quits without further notice. Whenever this happens, the connections between the MainForm and the DataModule (DM1) are lost: in the Object Inspector of the MainForm, all DataSource assignments, ie connections to DataSources in the DataModule, are gone. Moreover, when I reload the program, there is the error message
Access violation at address 500C3553 in module 'rtl270.bpl'. Read of address 00000008
Code-checking gives no errors, but when compiling the following message/request appears:
Module 'MainForm' links to module 'DM1' which cannot be found in the current project. Do you wish to remove/redirect the links to another module?
The weird thing is that the DataModule design form in the IDE can no longer be made visible, only its code remains. Therewith, from within the MainForm the DataModule neither is visible, since dropdowns in the DataSource connectors of the DB-controls remain empty. Last, but not least, when I try to save the MainForm, it says:
Module "*MainForm" references another module and cannot be saved until DM1 is loaded
Whatever I tried to get it back to normal, it was unsuccessful.
However, in the OneDrive root folder, I see a file named ".849C9593-D756-4E56-8D6E-..etc..", which seems to be associated with my program, because of its file date. It can only be deleted or modified when I close OneDrive, but it revives after restart.
I am stuck, for many days already.
Does anyone have an idea what is going on, and can give me a hint on how to proceed?
I found out what has caused the Access Violation that showed up after I tried to bring the datasource connections back in place. I did that by editing the DFM-file of the Mainform, rather than direct in the Object Inspector.
I normally do editing in dfm-files, but adding lines with datasource assignments appears not to be allowed. This was quite a tough lesson for me!
I am happy to have the program running again. Thank you all for your time, #Remy in particular.
Thanks,
JGMS

DELPHI: Crash when unloading DLL if context help is shown

We have a complex Delphi application with a main exe and several dlls.
In main form (contained in application exe) we have menubar.
On selecting a menu the corresponding dll is loaded and a form conatained in the dll is shown modal.
The scenario is as follows:
Press F1 and the context help for the modal form is open.
Close the modal form (without closing the context help).
in the source code we have:
result := FreeLibrary(MH);
And the whole application crashes with the following windows error:
ERROR_ALLOCATE_BUCKET
602 (0x25A)
The bucket array must be grown. Retry transaction after doing so.
If we first close the context help and then close the modal form everything is ok.
The strangest thing is that we have 3 dlls crashing and 3 not crashing.
The flow goes thru the same code.
There is nothing in the Windows Event Log.
I thought as a workaround I could force close the context help on closing the modal form before unloading the dll but I cannot find pid or some task identifier which I could kill.
There is no child processes of the application pid.
In Task Manager 'Processes' tab I see the name of our application and the name of chm-file (without .chm) like a subtask (at least seems like so) and I can right-click 'Stop task' but programatically I cannot find this...
P.S:
We use .chm file and do not have HtmlHelpViewer in uses of any module.
We have associated specific help topic to controls in forms so they automatically display the corresponding help topic when the user focuses it and presses F1. So in fact we do not use Application.HelpCommand(.....) to show the help
**** edited ****
Currently we use Delphi Tokyo. The product is stared 15 years ago in Delphi7. It has several dll-s (some of them are extra product modules) with plenty of forms and frames.
**** edited ****
**LU RD's answer solved my problem:**
Application.HelpCommand(HELP_QUIT, 0);
P.S:
I cannot mark the answer as accepted. I do not know why.
"I thought as a workaround I could force close the context help on closing the modal form before unloading the dll but I cannot find pid or some task identifier which I could kill. There is no child processes of the application pid".
In order to close the context help, add this line in the modal form OnClose() event:
Application.HelpCommand(HELP_QUIT, 0);
Application.HelpCommand: Provides access to any of the Help commands in the application programming interface (API) of native Help handling functions HTMLHelp, WinHelp, or other.
See Vcl.Forms.TApplication.HelpCommand for further details.

Tab order in a console app with a single VCL form

I have a Windows console app created with Embarcadero XE 6 (in fact converted from a Borland C++Builder5 project). It has a single form with a few buttons and edit controls. All these controls have set TabStop=True and appropriate TabOrder's. However, pressing Tab in runtime when the form is shown does not do anything (it just produces a sound when a cursor/focus is in an Edit control and does nothing when a button is focused).
I have read in docs that Tab order would not work unless the Parent of the form is set. However, this is the only VCL form (the other windows are the console and the GLUT window), so there is no VCL parent AFAIK. I tried to set
Parent=Application->MainForm;
in the Form's constructor, but the Application->MainForm is also NULL. Any ideas?
Your problem is that you don't have a message loop. This is because console applications are not expected to have windows and do not come with message loops by default.
You can run a message loop by calling:
Application->Run();
However this will probably stop the console part of your application from working properly. How can your main thread service the console synchronously and the asynchronous GUI message loop at the same time?
I suspect you will need to have a more serious re-think of your application design.
Regarding your update, it seems that you do have a message loop, but it is the message loop for the GLUT framework. The VCL framework requires its message loop to handle dialog messages like TAB key presses.
It's plausible that running the VCL message loop in place of the GLUT message loop would give better results. But it's quite likely that would just break the GLUT part of the app.
Trying to run two incompatible GUI frameworks out of a single message loop is hard to get right. There's probably no quick fix here. You'll need to dig deeper. Perhaps it would be best to give up on the VCL and stick to the one GUI framework.

How to supress EAccessViolation Finalization exception (mshtml.dll)

We use TWebBrowser in our application.
on some of my customers computers (IE9/Win7) after my app terminates, it throws an Exception: "Access violation at address XXXX in module 'mshtml.dll'. Read of address XXXX" with endless loop of exception messages... very ugly :/
this only happens on very few computers (so far with only IE9/Win7).
I cannot reproduce this exception on my PC.
I also use JclDebug which is the last unit defined in my main dpr uses clause - it is not catching this exception.
How to completely supress this Exception?
The application is written in D5.
Wild guess... there is a callback (event) from IE when your Application is in the destructor and your TWebBrowser is (at least partially) destroyed.
You can try to explicitly Free the TWebBrowser earlier, see if you have any event handler that could mess around, make sure you use Release on the form that holds it...
Hard to tell without having the code.

Prevent Delphi COM component from showing MessageBox()

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?
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.
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.
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
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.
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.

Resources