我有一个WPF应用程序,需要与另一个应用程序接口。
此应用程序具有大约20个自定义Windows消息(WM_USER + 50 ... WM_USER + 70)。
我要完成的工作摘要:
WPF应用程序-> SendMessage->第三方应用程序
我的问题是所有消息都是自定义消息。因此,我必须实现自己的数据封送处理。
请参见http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx
似乎我需要经历的过程是:
抢占进程并打开它以进行所有访问。User32.GetWindowThreadProcessId(windowHandle,out pId);
//以所有访问权限打开进程someprocess = OpenProcess((0x1F0FFF),false,(int)pId);
在进程中分配缓冲区:IntPtr缓冲区= VirtualAllocEx(hProcess,IntPtr.Zero,1024,0x1000,0x04);
填满某种要写入#2中创建的缓冲区的结构?
将#3复制到远程缓冲区是#2吗? WriteProcessMemory ??
发送自定义消息(SendMessage(windowhandle,customMsg,0,#2的缓冲区?)
将结构从远程进程缓冲区读回本地缓冲区
将数据编组为托管类型。 (这是一个C#.Net应用程序)
我真的可以利用一些见解。到目前为止,我还没有很多运气。我认为我最坚持的部分是发送到WriteProcessMemory的结构类型是什么?
WM_COPYDATA
绝对是最简单的方法。 WM_COPYDATA
使您可以将两个不同的数据项发送到另一个进程-DWORD值和任意大小的数据块。因此,对于您的实现,您可能会执行以下操作:
COPYDATASTRUCT cds;
cds.dwData = WM_USER + 50; // the "message" you want to send
cds.cbData = sizeof(MyDataForMessage50); // the size of the chunk of data
cds.lpData = lpMessage50Data; // a pointer to the chunk of data
SendMessage(hwndTarget, WM_COPYDATA, reinterpret_cast<WPARAM>(hwndSender),
reinterpret_cast<LPARAM>(&cds));
注意,hwndTarget
是另一个过程中的目标窗口,hwndSender
是send过程中的窗口。目标窗口接收相同的参数,因此可以使用wParam
了解谁发送了消息,因此可以根据需要发送回复。
在接收端的WndProc中:
if (uMsg == WM_COPYDATA)
{
HWND hwndSender = reinterpret_cast<HWND>(wParam);
LPCOPYDATASTRUCT pcds = reinterpret_cast<LPCOPYDATASTRUCT>(lParam);
DWORD dwCustomMsg = pcds->dwData;
LPVOID pCustomData = pcds->lpData;
DWORD dwCustomDataSize = pcds->cbData;
// do something with the custom message
// return TRUE to indicate message received
return TRUE;
}
也请注意WM_COPYDATA
文档中的重要说明:
接收应用程序应将数据视为只读数据。的lParam参数仅在处理消息期间有效。接收方应用程序不应释放由其引用的内存帕拉姆如果接收应用程序必须在之后访问数据SendMessage返回,必须将数据复制到本地缓冲区中
发送消息的示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
public const int WM_COPYDATA = 0x4A;
public const UInt32 WM_COMMAND = 0x0111;
public const UInt32 IDM_MENU_SECUREDISCONNECT = 305;
public const UInt32 PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpData;
}
[DllImport("User32.dll", EntryPoint = "SendMessage", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
private const string MARKER = "MARKER\n";
static void Main(string[] args)
{
IntPtr destWnd = (IntPtr)int.Parse(args[0]);
string packedargs = DAZZLE_MARKER + String.Join("\n", args[1]);
/
byte[] sarr = System.Text.Encoding.Unicode.GetBytes(packedargs);
int len = sarr.Length;
COPYDATASTRUCT CopyDataStruct;
CopyDataStruct.dwData = (IntPtr)100;
CopyDataStruct.cbData = (len + 1) * 2;
CopyDataStruct.lpData = packedargs;
int result = SendMessage(destWnd, WM_COPYDATA, 0, ref CopyDataStruct);
}
}
}