【发布时间】:2021-05-05 05:08:50
【问题描述】:
编辑:我把它修好了,这是我的工作完整代码,可以为新朋友树立榜样,我原来的问题也在下面。
在代码之前,让我向您介绍一些文档(按顺序):
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#message-only-windows
https://docs.microsoft.com/en-us/windows/win32/dataxchg/using-data-copy
http://pinvoke.net/default.aspx/Structures/COPYDATASTRUCT.html
C#程序
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Program
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern long SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr FindWindow(string classname, string windowname);
[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
public uint dwData;
public int cbData;
public IntPtr lpData;
}
public static IntPtr IntPtrAlloc<T>(T param)
{
IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, retval, false);
return (retval);
}
public static void IntPtrFree(IntPtr preAllocated)
{
if (IntPtr.Zero == preAllocated) throw (new Exception("Go Home"));
Marshal.FreeHGlobal(preAllocated); preAllocated = IntPtr.Zero;
}
const int WM_COPYDATA = 0x004A;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread.Sleep(3000);
string message = "This is a test";
IntPtr hWnd = FindWindow("MyClass", "MyTitle");
if (hWnd == IntPtr.Zero)
{
MessageBox.Show("couldn't find the window");
}
else
{
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = message.Length + 1;
cds.lpData = Marshal.StringToHGlobalAnsi(message);
IntPtr cdsBuffer = IntPtrAlloc(cds);
SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cdsBuffer);
IntPtrFree(cds.lpData);
IntPtrFree(cdsBuffer);
}
}
}
}
C++ 程序
#include <iostream>
#include <Windows.h>
using namespace std;
LRESULT CALLBACK WindProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_COPYDATA)
{
PCOPYDATASTRUCT data = (PCOPYDATASTRUCT)lParam;
MessageBoxA(hWnd, (LPSTR)data->lpData, "info", 0); // The character set depends on the characters you send
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
int main(){
WNDCLASSEX wcx = { 0 };
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpfnWndProc = WindProc;
wcx.hInstance = GetModuleHandle(NULL);
wcx.lpszClassName = TEXT("MyClass");
RegisterClassEx(&wcx);
HWND hWnd = CreateWindowEx(0, TEXT("MyClass"), TEXT("MyTitle"), 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
MSG message;
for(int i = 0; i < 1000; i++)
{
std::cout << "working" << std::endl;
Sleep(2 * 1000);
if(PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE))
{
break;
}
}
int x;
cout<<"got it!";
cin>>x;
return 0;
}
原始问题:
我有一个 C# 应用程序,我想与我在 C# 应用程序中创建的 c++ 进程进行通信。
我手里有一个我想应该可以工作的代码,但它没有。该消息根本不是由 c++ 应用程序获取的。
我的 C# 程序:
namespace ScannerGUI
{
public partial class Form1 : Form
{
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
public uint dwData;
public int cbData;
public IntPtr lpData;
}
public static IntPtr IntPtrAlloc<T>(T param)
{
IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, retval, false);
return (retval);
}
public static void IntPtrFree(IntPtr preAllocated)
{
if (IntPtr.Zero == preAllocated) throw (new Exception("Go Home"));
Marshal.FreeHGlobal(preAllocated); preAllocated = IntPtr.Zero;
}
const int WM_COPYDATA = 0x004A;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//creating child process
var prcsInfo = new ProcessStartInfo
{
UseShellExecute=true,
CreateNoWindow = false,
FileName = "main.exe",
};
Process myProcess = Process.Start(prcsInfo);
ChildProcessTracker.AddProcess(myProcess);
Thread.Sleep(3000);
string message = "This is a test";
IntPtr hWnd = myProcess.Handle;
if (hWnd == IntPtr.Zero)
{
MessageBox.Show("couldn't find the process");
}
else
{
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = message.Length + 1;
cds.lpData = Marshal.StringToHGlobalAnsi(message);
IntPtr cdsBuffer = IntPtrAlloc(cds);
PostMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cdsBuffer);
IntPtrFree(cds.lpData);
IntPtrFree(cdsBuffer);
}
}
}
}
我的 c++ 应用程序(main.exe):
int main(){
MSG message;
for(int i = 0; i < 1000; i++)
{
std::cout << "working" << std::endl;
Sleep(2 * 1000);
if(PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE))
{
break;
}
}
int x;
cout<<"got it!";
cin>>x;
return 0;
}
当我启动 c# 程序时。没有错误,没有什么。 与 c++ 相同,没有错误,没有任何东西,但永远不会破坏 for 循环:(
感谢大家的宝贵时间。
【问题讨论】:
-
hWnd = myProcess.Handle你认为这是窗口? -
我是这么认为的。如果不是,我可以使用 myProcess 获取窗口句柄吗?顺便说一句,我的 C++ 应用程序有窗口吗?我的意思是它会弹出一个命令提示符,但它被视为窗口吗?编辑:我尝试将其链接到 hWnd = myProcess.MainWindowHandle;但没有用。谢谢
-
我是否必须在我的 c++ 中创建一个窗口才能实现 IPC (PostMessage/PeekMessage)?
-
你的 C++ 程序是否真的有一个窗口,我看你没有创建一个。
MainWindowHandle真的有价值吗?public uint dwData;应该是ulong,因为它被定义为ULONG_PTR -
不要将
PostMessage与WM_COPYDATA一起使用。参见例如Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?。
标签: c# c++ winapi ipc sendmessage