Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi 12 und SendMessage (https://www.delphipraxis.net/214670-delphi-12-und-sendmessage.html)

EscapedFromMatrix 19. Feb 2024 08:19

Delphi 12 und SendMessage
 
Hallo,

ich habe ein Programm unter Delphi 12 kompiliert und nun funktioniert SendMessage mit WM_COPYDATA nicht mehr.
Die Zielanwendung(en) erhalten keine Nachricht.
Das Handle der Zielanwendung(en) passt.
Die Anwendungen haben unterschiedliche Architekturen (x64 und x86).
Was wurde denn da von D11 auf D12 geändert?

Gruß Andreas

himitsu 19. Feb 2024 08:57

AW: Delphi 12 und SendMessage
 
Per se sollte es ja gehn, auch zwischen x68 und x64.

Erstmal das Einfachste prüfen:

* Dein Code, welchen wir nicht kennen, ist wirklich korrekt?

* Du prüfst auch die Parameter/Rückgabewerte?
z.B. FindWindow usw. finden das Ziel auch

Ja, bei WM_COPYDATA steht nur war vom Result und nichts bezüglich weiterer Auswertungen, wie z.B. GetLastError, aber versuchen kann man's ja mal.
Delphi-Quellcode:
SetLastError(ERROR_CURRENT_DIRECTORY); // es ginge auch SetLastError(NO_ERROR), aber so haben wir war zur verifications, ob GetLastError hier wirklich nichts bewirkt
if not BOOL(SendMessage(DestWindowHandle, WM_COPYDATA , WPARAM(Self.Handle), LPARAM(@MyCopyDataStruct)) then // oder besser SendMessageTimeout
  RaiseLastORError;
* Die Prozesse laufen nicht mit unterschiedlichen Rechten?
z.B. eine Restricted App versucht nciht was an eine Admin-App zu schicken?

* Am einfachsten laufen beide im selben Nutzeraccount?
Nicht vieleicht in unterschiedlichen Sessions oder Dergleichen.



Es gab noch irgendwie was, womit man "gesperrte" Messages aus anderen Prozessen erlauben kann, aber ich finde da nichts zu, vor allem nicht bezüglich WM_COPYDATA (welches als Austauschformat, vermutlich eh nicht gesperrt wird)

EscapedFromMatrix 19. Feb 2024 10:08

AW: Delphi 12 und SendMessage
 
Das Handle der Zielanwendung passt. Selber Account, gleiche Rechte.

Also auf das einfachste reduziert sieht es aus wie folgt.

In Delphi <=11 kann ich das unter x86 und x64 kompilieren und es klappt mit Zielanwendungen beider Architekturen.
In Delphi 12 kann ich es nur noch unter x86 kompilieren, sonst ist es ohne Funktion.


Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Send_Quickdata('DTprjno;123456');
end;



function TForm1.Send_Quickdata(msg:string):boolean;
var
  aCopyData: TCopyDataStruct;
  hTargetWnd: HWND;
begin
  hTargetWnd := FindWindowEx(0, 0, nil, Pchar ('QuickData'));
  if hTargetWnd <> 0 then
  begin
      with aCopyData do
      begin
        dwData := 0;
        cbData := (StrLen(Pchar(msg)) + 1)* SizeOf(Char);
        lpData := Pchar (msg);
      end;
      // Search window by the window title
      // Fenster anhand des Titelzeilentext suchen
      SendMessage(hTargetWnd, WM_COPYDATA, Longint(Handle), Longint(@aCopyData));
      result:=true;
  end
  else result:=false;
end;

Kas Ob. 19. Feb 2024 11:29

AW: Delphi 12 und SendMessage
 
Hi,

Just an idea, i don't have Delphi 12, but form what i read there is change in default Integer and NativeInt...

So please check the size of TCopyDataStruct in both Delphi 11 and 12, may be something broke there with dwData,
It would be nice if you shared with us the SizeOf(TCopyDataStruct) in the 4 cases Delphi 11 and Delphi 12 for application with 32bit and 64bit.

EscapedFromMatrix 19. Feb 2024 12:23

AW: Delphi 12 und SendMessage
 
Da gibt es Abweichungen.


showmessage(inttostr(sizeof(aCopyData)));

D11
x64=24
x86=12

D12
x64=8
x86=4

EscapedFromMatrix 19. Feb 2024 12:32

AW: Delphi 12 und SendMessage
 
Ich mache noch weitere Tests, aber so scheint es zu klappen:
Delphi-Quellcode:
SendMessage(hTargetWnd, WM_COPYDATA, NativeUInt(Handle), NativeInt(@aCopyData));

DeddyH 19. Feb 2024 12:54

AW: Delphi 12 und SendMessage
 
Und so?
Delphi-Quellcode:
SendMessage(hTargetWnd, WM_COPYDATA, wParam(Handle), lParam(@aCopyData));

EscapedFromMatrix 19. Feb 2024 13:00

AW: Delphi 12 und SendMessage
 
Das klappt auch.
Wenn man die Definitionen für wParam und lParam verfolgt, landet man ja letztendlich bei NativeUInt und NativeInt.

himitsu 19. Feb 2024 13:04

AW: Delphi 12 und SendMessage
 
Das im Post #5 (für D12) kann eigentlich nicht stimmen.
Wie ist denn TCopyDataStruct deklariert? (Strg+Linkklick aka "Deklaration suchen")

Kas Ob. 19. Feb 2024 13:06

AW: Delphi 12 und SendMessage
 
Zitat:

Zitat von EscapedFromMatrix (Beitrag 1533647)
Da gibt es Abweichungen.

showmessage(inttostr(sizeof(aCopyData)));

D11
x64=24
x86=12

D12
x64=8
x86=4

That can't be right.

First i put SizeOf(TCopyDataStruct) not sizeof(aCopyData), why it is important because 8 and 4 are the size of single and simple pointer, not a record (struct), and 8 and 4 looks like a pointer something like PCopyDataStruct not TCopyDataStruct, or you just used @aCopyData by mistake.
Second as rule of thumb, never ever use with SendMessage, PostMessage... parameters other than WPARAM and LPARAM, or just cast them.

EscapedFromMatrix 19. Feb 2024 13:18

AW: Delphi 12 und SendMessage
 
[QUOTE=Kas Ob.;1533652]
Zitat:

Zitat von EscapedFromMatrix (Beitrag 1533647)
First i put SizeOf(TCopyDataStruct) not sizeof(aCopyData)...

Sorry, my mistake:

showmessage(inttostr(sizeof(TCopyDataStruct)));
D11, x86= 12
D11, x64= 24

D12, x86= 12
D12, x64= 24

himitsu 19. Feb 2024 16:01

AW: Delphi 12 und SendMessage
 
SizeOf(Variable) ist nicht falsch.
Der Typ und die Variable müssten sowieso gleich groß sein, da die Variable ja den "selben" Typ hätte.

Das sieht mehr wie ein Pointer aus (4 Byte = 32 Bit und 8 Byte = 64 Bit)
z.B. PCopyDataStruct statt TCopyDataStruct
aber auch da wären
Delphi-Quellcode:
SizeOf(PCopyDataStruct)
und
Delphi-Quellcode:
SizeOf(Variable) // var Variable: PCopyDataStruct;
gleich.

Kas Ob. 20. Feb 2024 08:19

AW: Delphi 12 und SendMessage
 
Zitat:

Zitat von himitsu (Beitrag 1533659)
SizeOf(Variable) ist nicht falsch.
Der Typ und die Variable müssten sowieso gleich groß sein, da die Variable ja den "selben" Typ hätte.

Das sieht mehr wie ein Pointer aus (4 Byte = 32 Bit und 8 Byte = 64 Bit)
z.B. PCopyDataStruct statt TCopyDataStruct
aber auch da wären
Delphi-Quellcode:
SizeOf(PCopyDataStruct)
und
Delphi-Quellcode:
SizeOf(Variable) // var Variable: PCopyDataStruct;
gleich.

You are right, but for best practice i prefer never to use variable, to avoid situations like the following
Code:
type
  PMyRecord = ^TMyRecord;

  TMyRecord = record
    Buffer: array[0..31] of Byte;
  end;

  TMyClass = class
  public
    Rec1: TMyRecord;
    Rec2: PMyRecord;
  end;
var
  C:TMyClass;
begin
  Writeln(IntToStr(SizeOf(C.Rec1)));  // 32 
  Writeln(IntToStr(SizeOf(C.Rec2)));  // 4 on 32bit, 8 on 64bit
  Readln;
end.
This thing will be dangerous or more impactful when TMyRecord is small like 4 or 8 and pass on one platform to fail on the other, can happen when updating legacy code or just redesigning data structures.

dummzeuch 20. Feb 2024 08:37

AW: Delphi 12 und SendMessage
 
Zitat:

Zitat von Kas Ob. (Beitrag 1533664)
You are right, but for best practice i prefer never to use variable, to avoid situations like the following
Code:
type
  PMyRecord = ^TMyRecord;

  TMyRecord = record
    Buffer: array[0..31] of Byte;
  end;

  TMyClass = class
  public
    Rec1: TMyRecord;
    Rec2: PMyRecord;
  end;
var
  C:TMyClass;
begin
  Writeln(IntToStr(SizeOf(C.Rec1)));  // 32 
  Writeln(IntToStr(SizeOf(C.Rec2)));  // 4 on 32bit, 8 on 64bit
  Readln;
end.
This thing will be dangerous or more impactful when TMyRecord is small like 4 or 8 and pass on one platform to fail on the other, can happen when updating legacy code or just redesigning data structures.

Unfortunately that opens the possibility for a different kind of error:
You check the size of the type you are using at some time and later on change the variable declaration to a different type. SizeOf(VariableName) will then automatically reflect that change while SizOf(TOldType) will still return the size of the original type. If you don't catch that, your code will be wrong. That's the reason I prefer using the variable instead of the type.

Kas Ob. 20. Feb 2024 09:30

AW: Delphi 12 und SendMessage
 
Zitat:

Zitat von dummzeuch (Beitrag 1533665)
Zitat:

Zitat von Kas Ob. (Beitrag 1533664)
You are right, but for best practice i prefer never to use variable, to avoid situations like the following
Code:
type
  PMyRecord = ^TMyRecord;

  TMyRecord = record
    Buffer: array[0..31] of Byte;
  end;

  TMyClass = class
  public
    Rec1: TMyRecord;
    Rec2: PMyRecord;
  end;
var
  C:TMyClass;
begin
  Writeln(IntToStr(SizeOf(C.Rec1)));  // 32 
  Writeln(IntToStr(SizeOf(C.Rec2)));  // 4 on 32bit, 8 on 64bit
  Readln;
end.
This thing will be dangerous or more impactful when TMyRecord is small like 4 or 8 and pass on one platform to fail on the other, can happen when updating legacy code or just redesigning data structures.

Unfortunately that opens the possibility for a different kind of error:
You check the size of the type you are using at some time and later on change the variable declaration to a different type. SizeOf(VariableName) will then automatically reflect that change while SizOf(TOldType) will still return the size of the original type. If you don't catch that, your code will be wrong. That's the reason I prefer using the variable instead of the type.

Well, you are right if the target is the variable itself not what it does represent, like in case data serialization against passing data between threads in the same process using thread safe list.
But for more accurate example :
We all familiar with Windows API's that takes structures (records), and many of them do need special initialization with cbSize or the very popular dwOSVersionInfoSize in https://learn.microsoft.com/en-gb/wi...osversioninfoa
Now if that record initially declared as local var with T, then it will not matter for using SizeOf the var itself, but in future change the code need to switch to dynamic allocated record to save it for future use, here the var will be a pointer and that function will fail.
Also and i witnessed this a lot, structure stack allocated then later the code needed to be multithreaded or just will save for future use, the var will be pointer, and will fail too.

I was talking about the best practice, but if the var itself is point (the needed) then using the type is useless here.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz