How to send / receive data using Sendmessage or Postmessage API?

2

I need to send several data to another process, the detail and the two processes are dlls, and I have customized my message. The message I get sends and receives it but when trying to treat the data coming from WParam of the violated access.

My data structure would be this:

type
  TMyStruct = packed record
    lpHandle: HWND;
    lpProcessid: DWORD;
  end;

var
  MyData: TMyStruct;

MyData.lpHandle:= handleprocess;
MyData.lpProcessid:= GetCurrentThreadId;
SendMessage(HWND_BROADCAST, WM_SHUTDOWN_THREADS, 0, LongInt(@MyData));

To receive:

type
  PMyStruct=^TMyStruct;
  TMyStruct = packed record
    lpHandle: HWND;
    lpProcessid: DWORD;
  end;

procedure TWinProc.WndProcedure(var _msg: TMessage);
var
  MyStruct: PMyStruct;
begin
  if _msg.Msg = WM_SHUTDOWN_THREADS then
  begin
    MyStruct:= PMyStruct(_msg.LParam);
    if (MyStruct^.lpBrowser = 0) then
      TerminaProcesso(MyStruct^.lpProcid)
    else
    if (not IsWindow(Wndthread)) then
    begin
      Fhandle:= MyStruct^.lpHandle;
      Wndthread:= CreateThread(nil, 0, @CallProcedure, nil, 0, WndthreadID);
    end;
  end
  else
    _msg.Result:= DefWindowProc(WinProc.WndProcHandle, _msg.Msg, _msg.WParam, _msg.LParam);
end;

If anyone knows how I can correct this communication, I will be grateful.

    
asked by anonymous 05.02.2015 / 00:53

1 answer

2

You are passing the data through lParam , wParam arrives at the other empty process.

SendMessage(HWND_BROADCAST, WM_SHUTDOWN_THREADS, 0, LongInt(@MyData));
                                                 ↑

If I understand what you want to do, you will have a problem with the current code, because it is trying to pass the address from one structure to another process, an address only has meaning within a single process.

Because a process is a set of threads, all running in a single address space, each process has at least one thread, the main thread. Only threads of the same process can do share of resources, such as accessing any valid address in #

You can do what the Vinícius Gobbo A. de Oliveira said in comment , use named pipes . Here have one article explaining about inter-process communication through named pipes in>, applicable for Delphi and .NET.

An alternative is to map the file to memory using the CreateFileMapping to create the mapping, OpenFileMapping to open the file and MapViewOfFile to read the contents of the file.

Another (somewhat simpler ) alternative that can be used is the Data Backup feature (#

Data Copy that allows you to send data from one application to another.

To use it you will have to send the message WM_COPYDATA through the function PostMessage or SendMessage (to send to a thread of the same process can be used %

Data must be passed to a structure PostThreadMessage .

The example below will send a structure that will contain the Handle and the PID of the process that will send the message.

type
  TMyStruct = packed record  // Estrutura que vai ser enviada a outro processo
    lpHandle: HWND;
    lpProcessid: DWORD;
end;

procedure PostData;   // Método responsável por enviar
var
  H: HWND;
  MyStruct: TMyStruct;
  copyDataStruct: TCopyDataStruct;
Begin
Try
  MyStruct.lpHandle := Application.Handle;       // Pega a handle da aplicação
  MyStruct.lpProcessid := GetCurrentProcessId(); // Pega o PID

  copyDataStruct.cbData := SizeOf(MyStruct);     // Tamanho em bytes dos dados apontados em lpdata
  copyDataStruct.lpData := @MyStruct;            // Dados que serão enviados a outro processo

  H := FindWindow(nil, 'Form2');                 // Pega a handle da janela que tenha o Form2 no título
  if IsWindow(h) then                            // Se for uma janela existente
    SendMessage(h, WM_COPYDATA, 0, Integer(@copyDataStruct)); // Envia a mensagem
Except
End;
end;

To receive the message (application you will receive):

type
  TMyStruct = packed record   // Estrutura que vai receber os dados do outro processo
    lpHandle: HWND;
    lpProcessid: DWORD;
  end;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
    protected
     procedure WMCopyData(var Msg : TWMCopyData); message WM_COPYDATA; // Quando a aplicativo receber essa mensagem
  public
    { Public declarations }
  end;
// .....
procedure TForm1.WMCopyData(var Msg: TWMCopyData); // Método que vai tratar a mensagem WM_COPYDATA
var
  MyStruct: TMyStruct;
  TempHandle, TempProcessID: string;
Begin
  MyStruct := TMyStruct(Msg.CopyDataStruct.lpData^); // Coloca em MyStruct o que foi recebido
  TempHandle := Inttostr (MyStruct.lpHandle);        // Coloca em TempHandle a handle recebida de outro proceso
  TempProcessID := Inttostr( MyStruct.lpProcessid);  // Coloca em TempProcessID o PID do outro processo

  // Daqui em diante fazer algo...
  ShowMessage(Format('Dados do outro processo:'#13'Handle %s ProcessID %s', [TempHandle, TempProcessID]));
end;

The above example was done with forms, some things will not work for a console or for a DLL , you will have to adapt it according to your need.

You have a good article that explains about this in:

09.02.2015 / 18:21