Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.
If you find these projects useful please consider becoming a sponsor with Patreon, GitHub or Liberapay.

How can get data from html to delphi

Post Reply
dinko
Posts: 15
Joined: Mon Jan 28, 2019 8:44 am

How can get data from html to delphi

Post by dinko »

Hello, continue from this thread:

https://github.com/salvadordf/CEF4Delph ... -458157616

I noticed that when I have subprocess

GlobalCEFApp.BrowserSubprocessPath := 'ChromeProcess64.exe';

it doesn't registers the extension. Do I have to include the same code and OnWebKitInitialized in the sub process too?

I choosed to create subprocess because I want to make my app run only one instance. And when I add Mutex protection it blocks the second, third etc instance of the same app. I found out that when a second instance runs it adds a parameter --type=gpu-process or --type=renderer. So maybe another solution is to ignore Mutex check --type=* found on ParamStr(1).

What's the best way?
User avatar
salvadordf
Posts: 4565
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: How can get data from html to delphi

Post by salvadordf »

dinko wrote: Mon Jan 28, 2019 3:39 pm I noticed that when I have subprocess
GlobalCEFApp.BrowserSubprocessPath := 'ChromeProcess64.exe';
it doesn't registers the extension. Do I have to include the same code and OnWebKitInitialized in the sub process too?
Yes. You need to add the code to the OnWebKitInitialized in the subprocess too.
dinko wrote: Mon Jan 28, 2019 3:39 pm I choosed to create subprocess because I want to make my app run only one instance. And when I add Mutex protection it blocks the second, third etc instance of the same app. I found out that when a second instance runs it adds a parameter --type=gpu-process or --type=renderer. So maybe another solution is to ignore Mutex check --type=* found on ParamStr(1).
What's the best way?
That's the easiest and fastest way.

Chromium creates several processes automatically using those parameters and it can be complicated to make it work correctly in some Delphi applications that already have code in the DPR file.

There's only one problem : Some antivirus programs give a false positive in the subprocess EXE.

As you know, this has been an issue with Delphi applications for years and sometimes you can avoid it by signing your application, asking the antivirus maker to white-list your application or just telling your clients to add your application to the white-list locally.
dinko
Posts: 15
Joined: Mon Jan 28, 2019 8:44 am

Re: How can get data from html to delphi

Post by dinko »

Thanks!

Regarding the issue with apps with lot of code on the dpr file, I have noticed that only the first instance runs on the check of

Code: Select all

if GlobalCEFApp.StartMainProcess then
...
so maybe the whole DPR code has to be added inside this block or maybe execute that code when the ParamStr(1) doesn't contain --type=*
That will make the trick to create "clean" subprocess of the same app.

About AntiVirus, thanks for the advices.

Now, I have find something really weird. Let's open the JSRTTIExtension example application and add:

Code: Select all

private
    procedure WMCopyData(var Msg : TWMCopyData) ; message WM_COPYDATA;

Code: Select all

procedure TJSRTTIExtensionFrm.WMCopyData(var Msg: TWMCopyData) ;
var
  s : string;
begin
  s := PChar(Msg.CopyDataStruct.lpData) ;
  ShowMessage(s);
end;
Now add a Button on form and write the following code on the OnClick

Code: Select all

var
  DataStruct : TCopyDataStruct;
  s: String;
begin
  s := 'Hello this is a message sent by SendMessage';
  DataStruct.dwData := 0;
  DataStruct.cbData := 1 + Length(s) ;
  DataStruct.lpData := PChar(s) ;
  SendMessage(Handle, WM_COPYDATA, Integer(Handle), Integer(@DataStruct));
Now run app and click button. You will see a MessageBox with the correct string

https://monosnap.com/file/4pJxtcQemnTzW ... YxEjE50uuT

Now, let's go to the Chromium1ProcessMessageReceived function and inside

Code: Select all

if (message.Name = MOUSEOVER_MESSAGE_NAME) then
just before or after

Code: Select all

StatusBar1.Panels[0].Text := message.ArgumentList.GetString(0);
write the same code as on Button1 Click

Run again the app and right click and enable mouse over event. And then mouse over on any element. You will see that string is being truncated

https://monosnap.com/file/CbSVwyWDhrckn ... tM8JMPRjcU

I tried to follow your instruction "It's safer to store the results and send a message to the main thread to show them." to send a message to the main thread but it looks like that I cannot really send a message as it is truncated. Is it bug or am I doing something wrong?
User avatar
salvadordf
Posts: 4565
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: How can get data from html to delphi

Post by salvadordf »

dinko wrote: Tue Jan 29, 2019 9:38 am Regarding the issue with apps with lot of code on the dpr file, I have noticed that only the first instance runs on the check of

Code: Select all

if GlobalCEFApp.StartMainProcess then
...
so maybe the whole DPR code has to be added inside this block or maybe execute that code when the ParamStr(1) doesn't contain --type=*
That will make the trick to create "clean" subprocess of the same app.
Yes. That's the way to use the same EXE for all the browser processes but it can be complicated depending on the code you already have in the DPR.
Read this post for more details about the DPR code :
https://www.briskbard.com/forum/viewtop ... =302#p1228
dinko wrote: Tue Jan 29, 2019 9:38 am Now, I have find something really weird. Let's open the JSRTTIExtension example application and add:

Code: Select all

private
    procedure WMCopyData(var Msg : TWMCopyData) ; message WM_COPYDATA;

Code: Select all

procedure TJSRTTIExtensionFrm.WMCopyData(var Msg: TWMCopyData) ;
var
  s : string;
begin
  s := PChar(Msg.CopyDataStruct.lpData) ;
  ShowMessage(s);
end;
Now add a Button on form and write the following code on the OnClick

Code: Select all

var
  DataStruct : TCopyDataStruct;
  s: String;
begin
  s := 'Hello this is a message sent by SendMessage';
  DataStruct.dwData := 0;
  DataStruct.cbData := 1 + Length(s) ;
  DataStruct.lpData := PChar(s) ;
  SendMessage(Handle, WM_COPYDATA, Integer(Handle), Integer(@DataStruct));
Now run app and click button. You will see a MessageBox with the correct string

https://monosnap.com/file/4pJxtcQemnTzW ... YxEjE50uuT

Now, let's go to the Chromium1ProcessMessageReceived function and inside

Code: Select all

if (message.Name = MOUSEOVER_MESSAGE_NAME) then
just before or after

Code: Select all

StatusBar1.Panels[0].Text := message.ArgumentList.GetString(0);
write the same code as on Button1 Click

Run again the app and right click and enable mouse over event. And then mouse over on any element. You will see that string is being truncated

https://monosnap.com/file/CbSVwyWDhrckn ... tM8JMPRjcU

I tried to follow your instruction "It's safer to store the results and send a message to the main thread to show them." to send a message to the main thread but it looks like that I cannot really send a message as it is truncated. Is it bug or am I doing something wrong?
The problem is that Msg.CopyDataStruct.lpData has a pointer to a local variable that is out of scope. WMCopyData is showing a string from a memory location that might be used for other purposes.

In this case I would suggest to store the string in a class field protected by a critical section.

The ResponseFilterBrowser demo has a similar solution with FStream (TMemoryStream) and FStreamCS (TCriticalSection)
https://github.com/salvadordf/CEF4Delph ... rowser.pas
Post Reply