C# IPC具有WndProc覆盖的本机SendMessage不工作

C# IPC具有WndProc覆盖的本机SendMessage不工作,c#,.net,ipc,native,wndproc,C#,.net,Ipc,Native,Wndproc,我有一个WPF应用程序,启动时没有参数或标志。在App.xaml.cs中,我添加了一个OnStartUp处理程序,如果应用程序的另一个实例使用参数执行,则该处理程序将尝试对其执行一些IPC。例如,我的主应用程序可以通过简单地执行mainApp来启动,这将加载主窗口。然后,我可能稍后执行mainApp msg bob some_message,它将在OnStartUp中传递条件,并将“msg bob some_message”发送到正在运行的应用程序,以在其WndProc覆盖中进行处理 App.x

我有一个WPF应用程序,启动时没有参数或标志。在
App.xaml.cs
中,我添加了一个
OnStartUp
处理程序,如果应用程序的另一个实例使用参数执行,则该处理程序将尝试对其执行一些IPC。例如,我的主应用程序可以通过简单地执行
mainApp
来启动,这将加载主窗口。然后,我可能稍后执行
mainApp msg bob some_message
,它将在
OnStartUp
中传递条件,并将“msg bob some_message”发送到正在运行的应用程序,以在其
WndProc
覆盖中进行处理

App.xaml.cs中的代码:

private void OnStartUp(object sedner, StartupEventArgs e)
{
   Process localProcess = Process.GetCurrentProcess();

   foreach (Process process in Process.GetProcessesByName(localProcess.ProcessName))
   {
      if (process.Id != localProcess.Id)
      {
         NativeMethods.SendMessage(process.MainWindowHandle, NativeMethods.HWND_IPC, IntPtr.Zero, IntPtr.Zero);
         Environment.Exit(0);
      }
   }
}
主窗口中的代码代码隐藏:

public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr iParam, ref bool handled)
{
   if (msg == NativeMethods.HWND_IPC)
   {
      MessageBox.Show("Message Received!");
   }

   return IntPtr.Zero;
}

internal class NativeMethods
{
   public const int HWND_BROADCAST = 0xffff;
   public const int HWND_IPC = 0xfffe;
   public static readonly int WM_IPC = RegisterWindowMessage("WM_IPC");
   public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
   [DllImport("user32")]
   public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
   [DllImport("user32.dll")]//, CharSet = CharSet.Auto, SetLastError = true)]
   public static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
   [DllImport("user32")]
   public static extern int RegisterWindowMessage(string message);
}
我已经尝试过使用PostMessage、SendMessage、static int messages、实际调用RegisterWindowMessage等多种方法。似乎什么都不管用


此外,我希望不仅能够指定特定消息,还能够指定其他动态详细信息,如用户名和一些消息文本。

我认为您需要覆盖,尽管我不确定它是否存在于WPF视图中:

试试这个:

protected override void WndProc( etc...
[更新] 不能以这种方式重写WPF窗口类中的WndProc

将说明您需要一个挂钩:

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
        source.AddHook(WndProc);
    }
综合起来:

在App.xml.cs中,您将初始化应用程序启动参数。创建一些静态属性是最容易的。保持它们简单,无集合,以避免多线程在以后崩溃:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    public static string SomeValue { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        SomeValue = e.Args[0];
    }
}
唯一需要实现的是触发消息的时刻,但由于它是IPC,只要有目标窗口的句柄,基本上可以从任何地方发送消息

将此信息与Franks关于WM_COPYDATA的评论结合起来,就可以开始了。有关WM_COPYDATA的信息:


希望有帮助。

我想您需要覆盖,尽管我不确定它是否存在于WPF视图中:

试试这个:

protected override void WndProc( etc...
[更新] 不能以这种方式重写WPF窗口类中的WndProc

将说明您需要一个挂钩:

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
        source.AddHook(WndProc);
    }
综合起来:

在App.xml.cs中,您将初始化应用程序启动参数。创建一些静态属性是最容易的。保持它们简单,无集合,以避免多线程在以后崩溃:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    public static string SomeValue { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        SomeValue = e.Args[0];
    }
}
唯一需要实现的是触发消息的时刻,但由于它是IPC,只要有目标窗口的句柄,基本上可以从任何地方发送消息

将此信息与Franks关于WM_COPYDATA的评论结合起来,就可以开始了。有关WM_COPYDATA的信息:


希望有帮助。

您发送的信息是HWND_IPC(窗口句柄?),而不是WM_IPC。 HWND_IPC的值0xFFFE不在用户消息WM_user+x的范围内

您不能以这种方式传输数据。有一个WM_COPYDATA,用于复制 给定的缓冲区从一个处理私有地址空间到另一个处理私有地址空间

我认为应该使用命名管道来传输数据。
SendMessage是如此的Win31;-)

您正在发送消息HWND_IPC(窗口句柄?),而不是WM_IPC。 HWND_IPC的值0xFFFE不在用户消息WM_user+x的范围内

您不能以这种方式传输数据。有一个WM_COPYDATA,用于复制 给定的缓冲区从一个处理私有地址空间到另一个处理私有地址空间

我认为应该使用命名管道来传输数据。
SendMessage是如此的Win31;-)

谢谢你的回复。该覆盖是否具有类似“
ref Message
”的参数?我的目标是Framework4,所以我认为我不能使用type
Message
。谢谢,只是查看了更新。我以前尝试过类似的方法,但问题是WndProc在我的主窗口类中。每当我试图通过App.xaml.cs访问时,就会出现“objectunused”异常,我无法编译它。不过,我仍然在使用App.xaml启动事件处理程序。我看不到SourceInitialization的任何内容,但这是否会削弱我以这种方式启动应用程序时处理命令行参数的能力?我以为只有在App.xaml的顶层直接处理启动时,我才能得到必要的e.Args数组。谢谢你的回复。该覆盖是否具有类似“
ref Message
”的参数?我的目标是Framework4,所以我认为我不能使用type
Message
。谢谢,只是查看了更新。我以前尝试过类似的方法,但问题是WndProc在我的主窗口类中。每当我试图通过App.xaml.cs访问时,就会出现“objectunused”异常,我无法编译它。不过,我仍然在使用App.xaml启动事件处理程序。我看不到SourceInitialization的任何内容,但这是否会削弱我以这种方式启动应用程序时处理命令行参数的能力?当我在App.xaml的顶层直接处理OnStartUp时,我认为我只能得到必要的e.Args数组。可能的重复可能的重复我希望我可以绕过编写pipeserver的整个问题。我认为我应该能够用两种或两种非常简短的方法通过本机窗口消息传递来实现这一点。我认为命名管道解决方案是最方便的:您设置一个“服务器”流,然后等待某个“客户端”连接。然后像通过任何其他流一样传输数据。这是NamedPipeServerStream:这是NamedPipeClientStream:这里的代码示例几乎涵盖了它。请在我们讲话时查看它。谢谢你的链接!我希望我能绕过编写pipeserver的整个问题。我认为我应该能够用两种或两种非常简短的方法通过本机窗口消息传递来实现这一点。我认为命名管道解决方案是最方便的:您设置一个“服务器”流,然后等待某个“客户端”连接。然后你只需要传输数据