【发布时间】:2019-12-11 06:15:09
【问题描述】:
我正在通过 WPF 中的HwndSource 实现与另一个进程的通信。
我希望我的程序(我们称之为 A)与 Windows 上另一个进程上的我的程序(也称为 A)进行通信。
下面的图片将帮助我解释我一直在做什么以及我想要实现什么。
两个窗口是完全相同的程序(只是背景颜色不同),并且它们彼此完全知道它们的句柄。如果我注意到两个进程具有相同的标题,那么我调用 sendMessage,它在 user32.dll 中定义,带有 Message -Raw 输入消息常量,可以全局泵送消息 -0x0100WM_KEYDOWN。
// if same program - but different process
IntPtr lpData = Marshal.StringToHGlobalAnsi("Hi, Im Sender");
MessageBox.Show(Marshal.PtrToStringAnsi(lpData));
DisplayAnotherProcessHandle.Text = p.MainWindowHandle.ToString();
SendMessage(p.MainWindowHandle, WM_RawInput_key, IntPtr.Zero, lpData);
我成功地将WM_RawInput_Key、IntPtr.Zero传递给对手程序。但我对 lParam 有疑问。我无法获取 lParam 数据。我试图用Marshal.StringToBSTR 或Marshal.StringToAuto 来编组c# string ...但在下面的方法中我只得到Empty.String。
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg != WM_RawInput_key) return IntPtr.Zero;
if (wParam == IntPtr.Zero) // <-- opponent process hit this conditional syntax nicely.
{
var str = Marshal.PtrToStringAnsi(lParam); // but I'm failed pass lParam, or Marshalling lParam I don't know ...
MessageBox.Show(str);
DisplaySucceedOrNot.Text = str;
}
return IntPtr.Zero;
}
不知道IntPtr lParam表示的是哪个内存参数。我什至不知道这种技术是否有效。我需要你的帮助。感谢阅读
以下源代码是我的示例程序的完整源代码。
<Window x:Class="wndProc_IPC_WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:wndProc_IPC_WPF"
mc:Ignorable="d"
Title="WndProc-IPC-WPF" Height="450" Width="800">
<StackPanel>
<Button Name="AddHandler" Width="Auto" Height="100" Content="Add Handler to This Handle" Click="AddHandler_Click"></Button>
<Button Name="CreateNewProcess" Width="Auto" Height="100" Content="Create New Process Window" Click="CreateNewProcess_Click"></Button>
<Button Width="Auto" Height="100" Content="SendMessage To Another Process" Name="SendMessageBtn" Click="SendMessage_Click"></Button>
<StackPanel Orientation="Horizontal">
<TextBlock Text="MyHandle : "></TextBlock>
<TextBlock x:Name="DisplayMyProcessHandle" Margin="50 0 0 0"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Another Handle : "></TextBlock>
<TextBlock x:Name="DisplayAnotherProcessHandle" Margin="50 0 0 0"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Succed?"></TextBlock>
<TextBlock x:Name="DisplaySucceedOrNot" Margin="50 0 0 0"></TextBlock>
</StackPanel>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
private static extern bool SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
string AppName;
public static UInt32 WM_RawInput_key = 0x0100;
public MainWindow()
{
InitializeComponent();
AppName = this.Title;
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg != WM_RawInput_key) return IntPtr.Zero;
if (wParam == IntPtr.Zero)
{
var str = Marshal.PtrToStringAnsi(lParam);
MessageBox.Show(str);
DisplaySucceedOrNot.Text = str;
}
return IntPtr.Zero;
}
private void CreateNewProcess_Click(object sender, RoutedEventArgs e)
{
if (Process.GetProcessesByName(AppName).Length > 1)
{
MessageBox.Show("Already 2 Process Exist.");
return;
}
var path = (System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
Process p = new Process();
p.StartInfo.FileName = path;
p.Start();
}
private void SendMessage_Click(object sender, RoutedEventArgs e)
{
foreach (var p in Process.GetProcessesByName(AppName))
{
if (p.MainWindowHandle == Process.GetCurrentProcess().MainWindowHandle) continue;
{
IntPtr lpData = Marshal.StringToHGlobalAnsi("Hi, Im Sender");
MessageBox.Show(Marshal.PtrToStringAnsi(lpData));
DisplayAnotherProcessHandle.Text = p.MainWindowHandle.ToString();
SendMessage(p.MainWindowHandle, WM_RawInput_key, IntPtr.Zero, lpData);
}
}
}
private void AddHandler_Click(object sender, RoutedEventArgs e)
{
HwndSource source = HwndSource.FromHwnd(Process.GetCurrentProcess().MainWindowHandle);
source.AddHook(new HwndSourceHook(WndProc));
}
}
【问题讨论】: