Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Text (Pfadangabe) per Windows Message verschicken (https://www.delphipraxis.net/133736-text-pfadangabe-per-windows-message-verschicken.html)

himitsu 8. Mai 2009 09:17

Re: Text (Pfadangabe) per Windows Message verschicken
 
ich würd es am Einfachsten so machen ... auf jedenfall mußt du data verschicken, der andere Prozess holt sich dann über diesen globalen Wert in data selber per GlobalLock die Daten in seinen Arbeitsspeicher und kann dann daraus lesen.
Delphi-Quellcode:
Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size);
try
  DataPtr := GlobalLock(Data);
  try
    CopyMemory(DataPtr, PChar(aText), Size);
  finally
    GlobalUnlock(Data);
  end;
  SendMessage(aWnd, WM_TSOPLAYFILE, data, 0);
finally
  GlobalFree(Data);
end;
PS: hiermit INTEGER(dataptr^) versendest du nur die ersten 4 Byte direkt im Parameter.

lbccaleb 8. Mai 2009 13:22

Re: Text (Pfadangabe) per Windows Message verschicken
 
Ich dachte ich kann die Daten dann in der Message des Empfängers einfach per Pointer auslesen! Muss ich dort auch mit GlobalAlloc arbeiten?

Im Empänger sieht es so aus:

Delphi-Quellcode:
var
  MSGFile: PChar;


    WM_TSOPLAYFILE:
      begin;
        MSGFile := PChar(@wParam);
            MessageBox(0, MSGFile, 'param', MB_OK or MB_ICONWARNING);
//mit deinem Code bekomme ich jetzt hier eine endlos lange Message...
        if FileExists(MSGFile) then
          begin;
            PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON2, BN_CLICKED), 0);
            if Succeeded(CheckFile(MSGFile)) then
              PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON1, BN_CLICKED), 0)
          end;
      end;

Wie muss das hier aussehen? Also wie lese ich den Speicher mit GlobalAlloc?


Edit:
Achja, ist PostMessage in dem Fall nicht besser als SendMessage in deinem Code?
@himitsu

himitsu 8. Mai 2009 13:31

Re: Text (Pfadangabe) per Windows Message verschicken
 
Einfach so mit einem Pointer geht das nicht ... wie auch, da beide Programme ihren eigenen virtuellen Arbeitsspeicher haben.


Delphi-Quellcode:
DataPtr := GlobalLock(wParam);
try
  s := PChar(DataPtr); // oder sonstwas
finally
  GlobalUnlock(wParam);
end;
mit GloablAlloc wird Speicher außerhalb deiner Anwendung reserviert
und mit GlobalLock wird dieser Speicher in den Adreßraum deiner Anwendung verschoben
danach mit GlobalUnlock wieder aus dem Adreßraum deiner anwendung entfernt
und nun kann sich die andere Anwendung diesen Speicher auch mal in ihren Adreßraum legen und diesen so auslesen.

lbccaleb 8. Mai 2009 13:44

Re: Text (Pfadangabe) per Windows Message verschicken
 
Erstmal danke für deine Erklärung :thumb:

Hab das ganze nun erstmal wieder in eine Funktion gepackt, die es dann auslesen soll (sonnst seh ich bald gar nicht mehr durch^^)

Delphi-Quellcode:
function GetAllocFileName(wParam: WPARAM): PChar;
var
  DataPtr: Pointer;
  begin;
    Result := '';
    DataPtr := GlobalLock(wParam);
    try
      Result := PChar(DataPtr); // oder sonstwas
    finally
      GlobalUnlock(wParam);
    end;
  end;


Delphi-Quellcode:
    WM_TSOPLAYFILE:
      begin;
        MSGFile := GetAllocFileName(wParam);//PChar(@wParam);
            MessageBox(0, MSGFile, 'param', MB_OK or MB_ICONWARNING);
        if FileExists(MSGFile) then
          begin;
            PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON2, BN_CLICKED), 0);
            if Succeeded(CheckFile(MSGFile)) then
              PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON1, BN_CLICKED), 0)
          end;
      end;
Aber ich bekomme schon wieder nur 3x Cryptisches Zeug angezeigt??

Das aber ne schwere Geburt mit mir und GlobalAlloc :lol:

himitsu 8. Mai 2009 13:49

Re: Text (Pfadangabe) per Windows Message verschicken
 
Zitat:

Zitat von lbccaleb
Achja, ist PostMessage in dem Fall nicht besser als SendMessage in deinem Code?

nee, SendMessage wertet, bis das andere Programm fertig ist
und das hab ich hier mal ausgenutzt, damit die Speicher reservierung und Freigabe in einer Hand (Programm) bleibt.

Delphi-Quellcode:
Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size);
If Data <> 0 Then Begin
  Try
    DataPtr := GlobalLock(Data);
    If DataPtr <> nil Then Begin
      Try
        CopyMemory(DataPtr, PChar(aText), Size);
        If SendMessage(aWnd, WM_TSOPLAYFILE, Data, 0) = 0 Then {Fehler};
      Finally
        GlobalUnlock(Data);
      End;
    End Else {Fehler};
  Finally
    GlobalFree(Data);
  End;
End Else {Fehler};
da die Speicherverwaltung des Strings aber Delphi übernimmt und PChar intern für einen vorhandenen Speicher sorgt, kann eigentlich keine Exception entstehen (es sei den du hast irgendwo anders ein großes Problem)
Delphi-Quellcode:
Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Length(aText) + 1);
If Data <> 0 Then Begin
  DataPtr := GlobalLock(Data);
  If DataPtr <> nil Then Begin
    CopyMemory(DataPtr, PChar(aText), Length(aText) + 1);
    If SendMessage(aWnd, WM_TSOPLAYFILE, Data, 0) = 0 Then {Fehler};
    GlobalUnlock(Data);
  End Else {Fehler};
  GlobalFree(Data);
End Else {Fehler};
und die andere Seite hatte ich ja schon geschrieben
Delphi-Quellcode:
DataPtr := GlobalLock(wParam);
If DataPtr = nil Then Begin
  Try
    s := PChar(DataPtr); // oder sonstwas
  Finally
    GlobalUnlock(wParam);
  End;
End Else {Fehler};

Tyrael Y. 8. Mai 2009 14:07

Re: Text (Pfadangabe) per Windows Message verschicken
 
Zitat:

Zitat von himitsu
nee, SendMessage wertet, bis das andere Programm fertig ist
und das hab ich hier mal ausgenutzt, damit die Speicher reservierung und Freigabe in einer Hand (Programm) bleibt.

SendMessage wartet auf den Empfang der WindowMessage.
Eine WindowMessage gilt als empfangen, wenn die WndProc des Empgängers verlassen wurde.

Eine Verarbeitung im WndProc ist daher sehr bedenklich, da das andere Programm solange blockiert wird.

Besser wäre die Variable im anderen Programm solange gültig zu halten bis eine "Verarbeitung-Beendet" Message zurück kommt.

Zitat:

Programm_A -> Daten -> Programm B
Programm_A hält Variable im Speicher
ProgrammB Verarbeitung();
ProgrammB -> Nachricht über Ende -> Programm A gibt Variable frei

lbccaleb 16. Mai 2009 18:18

Re: Text (Pfadangabe) per Windows Message verschicken
 
Sorry, ist schon ne Weile her, hatte aber nicht viel Zeit :(

Aufjedenfall habe ich immer noch das Problem, das nichts ankommt, sieht vllt irgendjemand noch nen Fehler??
Ich bin schon tierisch am Verzweifeln :(

und das verstehe ich auch nicht so:

Delphi-Quellcode:
If DataPtr = nil Then Begin
  Try
    s := PChar(DataPtr); // oder sonstwas
  Finally
    GlobalUnlock(wParam);
  End;
Wieso soll der Ptr nil sein?? muss der nicht auf ne Addresse zeigen?

himitsu 16. Mai 2009 18:24

Re: Text (Pfadangabe) per Windows Message verschicken
 
ups ... <> nil natürlich :oops:

im Fehlerfall liefert GlobalLock ein NIL zurück.

lbccaleb 16. Mai 2009 18:31

Re: Text (Pfadangabe) per Windows Message verschicken
 
OK, aber wenn ich auf ungleichheit Prüfe kommt bei mir der Fehler, also ist GlobalLock fehlgeschlagen, aber wieso??


Meine Funktionen:

Senden:
Delphi-Quellcode:
procedure GlobalAllocFileName(aWnd: HWND; aText: String);
var
  Data: THandle;
  DataPtr: Pointer;
  Size: Integer;
  oldWND: HWND;
begin
{  Size := Length(aText) + 1;
  Data := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Size);
  try
    DataPtr := GlobalLock(Data);
    try
      CopyMemory(DataPtr, PChar(aText), Size);
    finally
      GlobalUnlock(Data);
    end;
    SendMessage(aWnd, WM_TSOPLAYFILE, data, 0);
  finally
    GlobalFree(Data);
  end; }
  Data := GlobalAlloc({GMEM_MOVEABLE or GMEM_DDESHARE}GHND, Length(aText) + 1);
  If Data <> 0 Then Begin
    DataPtr := GlobalLock(Data);
    If DataPtr <> nil Then Begin
      CopyMemory(DataPtr, PChar(aText), Length(aText) + 1);
      If SendMessage(aWnd, WM_TSOPLAYFILE, Data, 0) = 0 Then {Fehler}
        begin
          MessageBox(0, 'senden fehlgeschlagen', 'fehler', MB_OK or MB_ICONWARNING);
          GlobalUnlock(Data);
        end;
    End Else {Fehler}
      MessageBox(0, 'dataptr leer', 'fehler', MB_OK or MB_ICONWARNING);
    GlobalFree(Data);
  End Else {Fehler}
    MessageBox(0, 'data leer', 'fehler', MB_OK or MB_ICONWARNING);
  end;
Empfangen:
Delphi-Quellcode:
function GetAllocFileName(wParam: WPARAM): PChar; //wparam ist nicht 0
var
  DataPtr: Pointer;
  begin;
    Result := '';
    DataPtr := GlobalLock(wParam); //aber hier gibts nen "nil" ich vermute das hier irgendwo mein Fehler steckt
    If DataPtr <> nil Then Begin
      Try
        Result := PChar(DataPtr); // oder sonstwas
        MessageBox(0, 'get - pointer nil', 'fehler', MB_OK or MB_ICONWARNING);
      Finally
        GlobalUnlock(wParam);
      End;
    End Else {Fehler}
      MessageBox(0, 'get - dataptr leer', 'fehler', MB_OK or MB_ICONWARNING);
  end;

Nachrichtenschleife vom Hauptprogramm:
Delphi-Quellcode:
    WM_TSOPLAYFILE:
      begin;
        MSGFile := GetAllocFileName(wParam);//PChar(@wParam);
        MessageBox(0, MSGFile, 'param', MB_OK or MB_ICONWARNING);

        if FileExists(MSGFile) then
          begin;
            PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON2, BN_CLICKED), 0);
            if Succeeded(CheckFile(MSGFile)) then
              PostMessage(HWND_TOPMOST, WM_COMMAND, MAKELONG(IDC_BMPBUTTON1, BN_CLICKED), 0)
          end;
        Result := 1;
      end;
initialization abschnitt von der Anwendung:
Delphi-Quellcode:
initialization
  begin;
    if paramcount > 0 then
      Param := paramstr(1);
    tMutex := CreateMutex(nil, True, ClassName);
    if GetLastError = ERROR_ALREADY_EXISTS then
      begin;
        if fileexists(Param) then
          begin;
            if (FindWindow(ClassName, AppName) > 0) then
              GlobalAllocFileName(FindWindow(ClassName, AppName), Param)
//            PostMessage(FindWindow(ClassName, AppName), WM_TSOPLAYFILE, INTEGER(@Param), 0)
          end
        else
          MessageBox(0, 'The Program is already running.', ClassName, MB_OK or MB_ICONWARNING);
        Halt;
      end;
  end;

Sorry für nen bissel viel Code :)

Muetze1 17. Mai 2009 00:03

Re: Text (Pfadangabe) per Windows Message verschicken
 
Dein Problem derzeit ist, dass der Sender den Speicher noch immer gelockt hat. Du hast derzeit beim Sender folgenden Ablauf:

1. Speicher alloziieren
2. Speicher locken, Pointer holen
3. Speicher befüllen (Pointer beschreiben)
4. Nachricht versenden mit dem Handle von 1.
5. Speicher unlocken
6. Speicher freigeben.

Wenn du an Stelle 4. bist, dann empfängt dieser das Handle von 1. und versucht nun ebenfalls mit GlocalLock ein exklusiven Lock zu bekommen, was ihm aber von Windows verwehrt wird, da das Handle derzeit von deinem Sender noch gelockt ist.

Also, der korrekte Ablauf sollte anhand der Nummerierung von zuvor wie folgt sein: 1., 2., 3., 5., 4., 6.

Also vorher unlocken, nur im ungelockten Zustand kann Windows den speicher virtuell zwischen den Prozessen verschieben. So lange einer den glockt hat, hat er den Finger drauf und Windows ist machtlos.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:37 Uhr.
Seite 2 von 3     12 3      

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