How to destroy the Tchromium (Delphi) component dynamically created? - delphi

How to destroy the Tchromium component dynamically created ? I'm using in a DLL , the component necessary to create and destroy it several times without deallocate the DLL, the problem is that is not releasing memory and is unable to clear the cache folder. If I use CefShutDown problems occur in time to recreate the browser again. I'm using the latest version of DCEF3 .
Create dynamically like this:
crm := TChromium.Create(Form1);
crm.SetParentComponent (Panel2);
crm.Align := alClient;
to destroy tried in several ways:
FreeAndNil(crm);
crm.free;
crm := nil;
CefShutDown;
The CefShutDown resolved in time to destroy , the problem is occurring by the time I try again recreate the component without deallocate my DLL.
Also solve another problem I'm having with the UserAgent can not change the recreation of the browser.
I appreciate any suggestions to solve my problem.

This behaviour is as designed. Issue 1237 on the Chromium issue tracker is identical to your issue. The relevant excerpt is:
CefInitialize/CefShutdown cannot be called multiple times in the same process. You can create/destroy multiple browser windows without re-initializing CEF.
You will have to refrain from calling CefShutDown.

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

How to stay logged in browser CEF4Delphi, without all browser history?

In CEF4Delphi it is possible to maintain the browser session with
GlobalCEFApp.PersistSessionCookies := True;
GlobalCEFApp.Cache := 'cache_folder';
thanks to this, one can keep embeed browser logged in, for example, mail. Unfortunately, this solution saves the entire cache of the browser, including attachments etc., which makes the cache folder very large after a while. In the previous version (CEF3) was an option to manage only a component that took up very little on the disk:
CookieManager := TCefCookieManagerRef.Global(nil);
CookieManager.FlushStore(nil);
but I have not found a similar solution for CEF4, while the command
GlobalCEFApp.PersistUserPreferences := True;
GlobalCEFApp.UserDataPath := 'User_Data_folder';
does not save any information in the created folder at all.
Is there any method to keep logging only without saving the entire cache? Or maybe some philosophy which i did not figured out yet, for example deleting some specific folders with a saved cache?
Note: My version of CEF4Delphi uses CEF 86.0.21 which includes Chromium 86.0.4240.183; i'm using TChromium component.
If you are using Global Cookie manager you should also set GlobalCEFApp.PresistSessionCookies to True
CEF4Delphi also has two properties which you can use to delet od cache or cookies upon CEF application initialization. These are DeleteCache and DeleteCookies.

What is the correct way to isolate cookies/users in Chromium embedded browser?

I have searched for days with no solution in sight.
I need multiple Chromium instances in one single application and each of this instance logins to the same site with different account (ex: outlook.com).
I tried this solution but there's no "OnGetCookieManager" event in DECF3 new version. Apparently there was a related bug and event onGetCookieManager was removed in the 1547 CEF3.
I tried this but it doesn't work too.
Is this really possible? How?
I'm using DCEF3 (revision: 0cc175e7a629) and Delphi XE3.
Here's what CEF3 maintainer told me:
"Cookies can be stored globally, per request context or something else entirely. It depends on whether you pass a CefRequestContext to CreateBrowser*() and what you return from CefRequestContextHandler::GetCookieManager."
I'm not entirely sure how CreateBrowser is exposed in Delphi (I only use the C++ API), but I can confirm that GetCookieManager still exists in trunk (as the only method of CefRequestContextHandler).

Launching application from a database

I have many users using my application. However if I do some update, which I put on the server, not all of them are willing to update it (they sometimes afraid of changes they do not want to accustom).
So I speculate, how to force them to launch the latest application. There are surely several ways how to do it, but I have heard, that it is possible to launch an application stored in a blob field of a database.
Does anybody knows how it can be accomplished? (I am using MySQL database)
thanx
Without judging on meaningful or nonsense ....
You could use uExecFromMem .....
There is a Memoryleak in this unit which can be fixed by adding:
ResumeThread(PI.hThread);
Result := PI.hThread;
FreeMem(pFile); // added here
end;
an example call using a TBlobField would be
var
ms:TMemoryStream;
begin
ms:=TMemoryStream.Create;
try
TBlobField(YouDBBlobField).SaveToStream(ms);
ms.Position := 0;
ExecuteFromMem(Application.ExeName,'',ms.Memory); // pointing to an existing executable
finally
ms.Free;
end;
end;
My advice is to use libraries.
You can have a small main executable file (some kind of "launcher"), which won't do nothing but launch external .dll fields. Just like a kernel does load modules at runtime (think about how Windows or Linux work).
Then you download an updated version of a .dll, stop and unload the old one, then load and initialize the new version.
Of course, your code has to be "clean", with proper startup and shutdown functions for each .dll.
But I suspect it would be much less error prone than ExecuteFromMem(). In this respect, good old load + execute of an .exe file (as Remy suggested) sounds like a much better option to me.

TObjectList.Clear access violation

I'm running into a very weird problem with a large application. I make heavy use of TObjectList storing a custom object on them. On large lists im experiencing weird crashes with "Access violation at address.. read of address.. " "privileged instruction" and others, when I use the CLEAR method. I've tracked this to happen exactly when attempting to delete the last item in the list. I've checked this by logging the contained objects deletion from their destroy proc, and also trying to deleting them on my own (for a := olist.count-1 downto 0 do.. debugmsg('deleting '+inttostr(a)).. olist.delete(a) ), both ways I get the access violation right when deleting the LAST remaining item in the list.
This doesnt happen always, cause I use clear in other areas, and also a few different (smaller) lists, but at a very specific point in my app this happens.
I've no clue what might be wrong, there's nothing trying to access the list during the clear, and the cointained objects do not have access to their parent objectlist, there has to be something screwing up in the TObjectList.delete/clear methods when it comes to clearing the last item.
Any suggestions? Using Delphi XE.
That sounds to me like you're freeing objects that have already been freed. To track this down, download the full version of FastMM, add FullDebugMode to the Conditional Defines line under Project Options->Delphi Compiler and the Map File option under Linking set to Detailed, and rebuild. (Build, not Compile.) Then copy the FullDebugMode DLL to the same folder as your EXE and run it. It'll watch your memory as you allocate and free and when you try to free the same object for a second time, it'll catch that and give you some very detailed debug data as to where the problem is coming from.
Are you sure the last object is valid and not already deleted? It could be in the list twice e.g. due to other bugs.

Resources