Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Probleme beim Empfangen mittels WM_COPYDATA (https://www.delphipraxis.net/209895-probleme-beim-empfangen-mittels-wm_copydata.html)

PitterS80 5. Feb 2022 16:14

Probleme beim Empfangen mittels WM_COPYDATA
 
Hallo!
Bis letzte Woche hatte ich noch Delphi 10.3 genutzt und bin jetzt auf 10.4 umgestiegen.
Leider funktioniert mein Quellcode jetzt nicht mehr so, wie er eigentlich sollte.
Ich will nur eine Instanz meiner Software zulassen und bei nochmaligem Aufruf einen String an die bestehende Instanz übergeben.

So sieht's beim Sender aus:
Delphi-Quellcode:
      // Parameter-String an Ur-Instanz senden
      Data.dwData := C_KEY;
      Data.cbData := (Length(Parms)+1) * SizeOf(Char);
      Data.lpData := PChar(Parms);
      MyHandle:=FindWindow(nil, PChar(APP_NAME));
      if MyHandle<>0 then SendMessage(MyHandle, WM_COPYDATA, LongInt(MyHandle), LongInt(@Data));
      CloseHandle(MyHandle);
Und so beim Empfänger:
Delphi-Quellcode:
procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
  sInput:  String;
begin
  try
    if Msg.CopyDataStruct.dwData = C_KEY then begin
      // Neue Daten empfangen
      sInput:=PChar(Msg.CopyDataStruct.lpData);
    end;
  except
    on E: Exception do
    Protokoll('WMCopyData;FEHLER;beim Einlesen des Strings - ' + E.Message);
  end;
end;
Im Protokoll habe ich hinterher immer folgende Fehlermeldung stehen:
WMCopyData;FEHLER;beim Einlesen des Strings - Zugriffsverletzung bei Adresse 0082EBC0 in Modul 'PushService7.exe'. Lesen von Adresse 00000000

Das Senden der Daten scheint ja schonmal nicht ganz verkehrt zu sein - zumindest C_KEY als Identifier kommt ja an.
Beim Senden werden auch keine Exceptions ausgelöst - nur beim Empfangen.

Irgendwie stehe ich jetzt gerade ein wenig auf dem Schlauch...
Hat einer von euch einen Tipp für mich?

Klaus01 5. Feb 2022 16:42

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
.. ist die neue Instanz schon beendet (der pointer auf den String also nicht mehr valide)wenn die Nachricht bei der alten Instanz ankommt?

Grüße
Klaus

PitterS80 5. Feb 2022 16:56

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Ja, die neue Instanz sendet den String und wird dann beendet.

Gausi 5. Feb 2022 17:01

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
In der (recht alten, aber funktionierenden) oneinst.pas, die ich dazu verwende, wird beim Aufbau der WM_COPYDATA-Message nicht nur einfach der Pointer zum String übergeben, sondern es werden explizit die Daten kopiert. Mich wundert ehrlich gesagt ein wenig, dass dein alter Code überhaupt funktioniert ...

Delphi-Quellcode:
Data.lpData := ParamStrToBlob(Data.cbData);

// mit

function ParamStrToBlob(out cbData: DWORD): Pointer;
var
  Loop: Integer;
  pStr: PChar;
begin
  cbData := Length(ParamStr(1)) * SizeOf(Char) + 4; { gleich inklusive #0#0 }
  for Loop := 2 to ParamCount do
    cbData := cbData + DWORD(Length(ParamStr(Loop)) * SizeOf(Char) + 2);
  Result := GetMemory(cbData);
  ZeroMemory(Result, cbData);
  pStr := Result;
  for Loop := 1 to ParamCount do
  begin
    lstrcpy(pStr, PChar(ParamStr(Loop)));
    pStr := @pStr[lstrlen(pStr) + 1];
  end;
end;
Ich hoffe, diese Variante funktioniert mit 10.4 weiter, wenn ich in den nächsten 30 Tagen umsteigen muss ...

BerndS 5. Feb 2022 17:33

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Ist denn der record als packed definiert? Wenn nicht sollte die Einstellung (Ausrichtung...) von 10.4 mit 10.3 übereinstimmen.
Die Daten sollten eigentlich beim Empfang noch gültig sein, da Sendmessage und nicht Postmessage verwendet wird.

PitterS80 5. Feb 2022 20:15

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Zitat:

In der (recht alten, aber funktionierenden) oneinst.pas, die ich dazu verwende, wird beim Aufbau der WM_COPYDATA-Message nicht nur einfach der Pointer zum String übergeben, sondern es werden explizit die Daten kopiert. Mich wundert ehrlich gesagt ein wenig, dass dein alter Code überhaupt funktioniert ...

Delphi-Quellcode:
Data.lpData := ParamStrToBlob(Data.cbData);

// mit

function ParamStrToBlob(out cbData: DWORD): Pointer;
var
  Loop: Integer;
  pStr: PChar;
begin
  cbData := Length(ParamStr(1)) * SizeOf(Char) + 4; { gleich inklusive #0#0 }
  for Loop := 2 to ParamCount do
    cbData := cbData + DWORD(Length(ParamStr(Loop)) * SizeOf(Char) + 2);
  Result := GetMemory(cbData);
  ZeroMemory(Result, cbData);
  pStr := Result;
  for Loop := 1 to ParamCount do
  begin
    lstrcpy(pStr, PChar(ParamStr(Loop)));
    pStr := @pStr[lstrlen(pStr) + 1];
  end;
end;
Ich hoffe, diese Variante funktioniert mit 10.4 weiter, wenn ich in den nächsten 30 Tagen umsteigen muss ...
Habe ich ausprobiert, funktioniert aber leider auch nicht. Immer noch die selbe Meldung. Irgendwie scheint es da irgendwo den Pointer zu schrotten...

Zitat:

Ist denn der record als packed definiert? Wenn nicht sollte die Einstellung (Ausrichtung...) von 10.4 mit 10.3 übereinstimmen.
Die Daten sollten eigentlich beim Empfang noch gültig sein, da Sendmessage und nicht Postmessage verwendet wird.
Kannst du mir da einen Tipp geben, wo ich das nachschauen kann? Hab in den letzten 20 Jahren nicht viel mit Delphi gemacht (war damals noch Delphi 4) und muss mich erstmal wieder reinfuchsen...

venice2 5. Feb 2022 21:31

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Hmmm..

Delphi-Quellcode:
var
  gCDS: COPYDATASTRUCT;
  gSOP: TSOP64; // my Record
const
  dwData_GetPluginName = 6;
64 Bit Anwendung..
Delphi-Quellcode:
function GetPluginDescription(WindowHandle: HWND): string;
begin
  SetLength(Result, SendMessage(WindowHandle, WM_GETTEXTLENGTH, 0, 0));
  if Result <> '' then
    SendMessage(WindowHandle, WM_GETTEXT, Length(Result) + 1, LPARAM(PWideChar(Result)));
end;

procedure SOP_GetPluginName;
begin

  if (gp.hSOPlugin <> 0) then
  begin
    gCDS.dwData := dwData_GetPluginName;
    gCDS.cbData := SizeOf(gSOP);
    gCDS.lpData := @gSOP;
    SendMessage(gp.hSOPlugin, WM_COPYDATA, WPARAM(gP.MainHandle), LPARAM(@gCDS));
  end;

  Description := GetPluginDescription(gP.MainHandle);
end;
32 Bit Anwendung..
Delphi-Quellcode:
function GetPluginName(handle: HVIS): PWideChar; stdcall;
begin

  Result := '';
  if handle <> 0 then
  begin
    Result := PWideChar(WideString(VisInfo^.VisPointer^.PluginName));
  end;
end;
Delphi-Quellcode:
var
  pCDS: PCopyDataStruct;
Delphi-Quellcode:
    WM_COPYDATA:
      begin
        pCDS := Pointer(lP); // LP pointer auf die CopyDataStruct
        case pCDS.dwData of

          dwData_GetPluginName:
            begin
              PluginName := GetPluginName(VisHandle);
              StrPCopy(aTemp, string(PluginName));
              SendMessage(wp, WM_SETTEXT, SizeOf(aTemp), LPARAM(@aTemp));
            end;
        end;
Nur als Denkanstoß.

Uwe Raabe 5. Feb 2022 21:55

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Zitat:

Zitat von Klaus01 (Beitrag 1501738)
.. ist die neue Instanz schon beendet (der pointer auf den String also nicht mehr valide)wenn die Nachricht bei der alten Instanz ankommt?

Das hier SendMessage verwendet wird, wartet der aufrufende Prozess auf die Abarbeitung der Message bevor er weitermacht.

himitsu 5. Feb 2022 23:09

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Egal, Zeiger in anderen Prozessen sind eh da düben nichts wert.

Darum gibt es ja WM_COPYDATA, welches einen angegebenen Speicherblock in den anderen Prozess kopiert, damit man ihn drüben lesen kann.


Alternatov GlobalAlloc und das Handle sharen
oder MemoryMappedFiles
oder Streams
oder ...

Zitat:

Zitat von PitterS80 (Beitrag 1501736)
Delphi-Quellcode:
      MyHandle:=FindWindow(nil, PChar(APP_NAME));
      ...
      CloseHandle(MyHandle);

Wieso versuchst du das "Handle" MyHandle (HWND nicht HANDLE) freizugeben, was vom FindWindow kommt?

Da du vom CloseHandle die Rückgabewerte nicht prüfst und so nicht mitbekommst, dass es dir einen Fehler um die Ohren versucht zu werfen

und da du zum Glück die falsche Funktion zum Freigeben von HWND benutzt, welche nämlich DestroyWindow (nicht CloseHandle) ist
...
eigentlich hättest du das Fenster gelöscht, wenn es funktioniert hätte.

PitterS80 6. Feb 2022 11:11

AW: Probleme beim Empfangen mittels WM_COPYDATA
 
Manchmal steht man einfach nur wie der Ochs' vor'm Berg...
Ich hatte eine bestehende, einwandfrei funktionierende Anwendung und wollte diese weiterentwickeln.
Dafür habe ich natürlich das Projekt kopiert.
Um dann aber die neue Anwendung parallel zur alten testen zu können, habe ich einerseits den myGUID für den Mutex neu generiert und den C_KEY als Identifier für WM_COPYDATA.
Bei letzterem habe ich wohl Mist gebaut...
Mit dem ursprünglichen Wert funktioniert es wieder.

Trotzdem vielen Dank für eure Hilfe!


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:23 Uhr.
Seite 1 von 2  1 2      

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