【问题标题】:Broadcast Windows HWND_BROADCAST message广播 Windows HWND_BROADCAST 消息
【发布时间】:2011-09-07 16:38:50
【问题描述】:

我正在此应用程序中的一个应用程序中工作,我将等待应用程序 1 中的某个事件,当此事件发生时,我将向应用程序 2 发送消息,该应用程序将执行某些操作。

第一个 API 声明

private const int HWND_BROADCAST = 0xffff;

 [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int RegisterWindowMessage(string lpString);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool SendNotifyMessage(int hWnd, int Msg, int wParam, int lParam);

应用程序 1 代码

private string msgstr = "MYMESSAGE";              
public int  msg = RegisterWindowMessage(msgstr);
                if (msg == 0)
                {
                    MessageBox.Show(Marshal.GetLastWin32Error().ToString());
                }

                //SendNotifyMessage(HWND_BROADCAST, msg, 4848484, 8484865);

                SendNotifyMessage(HWND_BROADCAST, msg, 0, 0);

                MessageBox.Show(Marshal.GetLastWin32Error().ToString());

应用程序 2 代码

 static readonly int msg = RegisterWindowMessage("MYMESSAGE");
     protected override void WndProc(ref Message m)
        {
            if (m.Msg == msg)
            {
                MessageBox.Show(m.Msg.ToString() + " = from wndproc");
            }
            base.WndProc(ref m);
         }

有人会指出这段代码有什么问题吗? 我怀疑 SendNotifyMessage 有问题

lparam 和 wparam 参数

有人会建议我实现这种行为的其他替代方法吗?

【问题讨论】:

    标签: c# winapi ipc


    【解决方案1】:

    HWND_BROADCAST 非常危险。我知道这不太可能,但如果另一个应用程序也处理了您的消息怎么办??

    不管怎样,除此之外,你读过http://msdn.microsoft.com/en-us/library/ms644953.aspx

    调试代码问题的最基本方法(因为它基于 WINAPI)是使用GetLastError。您应该始终检查方法的返回值以查看它们是否成功,因此请确保它返回零(这意味着它有效)。如果不是,并且您收到访问被拒绝等错误,请尝试在禁用 UAC 或以管理员身份 (Vista+) 的情况下运行。

    当消息被 UIPI 阻止时, 最后一个错误,检索到 GetLastError,设置为 5(访问 拒绝)。

    【讨论】:

    • UIPI 和 UAC 是什么意思?
    • 用户界面权限隔离 (UIPI)、用户帐户控制 (UAC)。 UAC 是您应该担心的,因为默认情况下应用程序在 Vista+ 上以“非特权”方式运行,我相信您知道,您是否尝试以管理员身份运行您的应用程序?
    • 是的,我以管理员身份运行我的应用程序,我得到最后一个错误 0。没有管理员权限,它返回 5。你是对的。但我仍然没有收到应用程序 2。
    • 您是否尝试过将通过 WndProc 的所有消息记录到文件中?这将是很多(通常),但您将能够通过它搜索应用程序 1 返回的消息 ID。您是否确保它们都返回相同的 ID?如果您独立运行应用程序,它们可能是相同的,但在一起可能会中断..
    • 感谢您的帮助,问题出在访问权限上。谢谢!您能否建议我使用其他方法来实现此行为(学习目的)
    【解决方案2】:
    1. 不存在有问题的代码。只存在不符合您预期的代码。如果你想让我们告诉你上面的代码有什么问题,你应该告诉我们你期望它做什么,(好吧,我们可以猜到,)但最重要的是,它做了什么。你收到错误了吗?它只是默默地失败了吗?这是一个问题的重要组成部分,你知道的!

    2. 您正在使用 RegisterWindowMessage() 和 SendNotifyMessage() 等方法,您没有向我们展示这些方法的定义。当我们不知道 SendNotifyMessage() 是如何声明的时,我们应该如何判断问题是否出在 SendNotifyMessage() 上?

    3. 您的应用程序 2 有一个 WndProc,您希望在其中接收窗口消息。是否已正确注册?你确定它有效吗?它是否接收其他窗口消息?如果您从应用程序 2 中发送它,它会收到“MYMESSAGE”吗?

    4. HWND_BROADCAST 仅向顶级窗口发送消息。您确定您的窗口是顶级窗口吗?

    5. 您没有检查应用程序 2 中对 RegisterWindowMessage() 的调用是否成功。首先检查一下怎么样?

    6. “MYMESSAGE”不是一个很好的消息名称。如何使用更独特的东西,例如您的名字加姓氏,或者创建一个 guid 并将其字符串表示形式用作您的消息名称?

    【讨论】:

      【解决方案3】:

      下面的代码效果很好,

      服务器端。

      public partial class Server : Form
          {
              private UInt32 msg;
              public Server()
              {
                  InitializeComponent();
      
              }
      
              protected override void OnLoad(EventArgs e)
              {
                  base.OnLoad(e);
                  msg = RegisterWindowMessage("THIS_IS_MY_UNIQUE_MESSAGE");
              }
      
              [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
              static extern uint RegisterWindowMessage(string lpString);
      
              [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
              static extern bool SendNotifyMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
      
              private void SendMessage(object sender, EventArgs e)
              {
                  var retval = SendNotifyMessage(new IntPtr(-1), msg, 0, 0);
              }
      
      
          }
      

      客户端

      public partial class Client : Form
          {
              public Client()
              {
                  InitializeComponent();
              }
      
              [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
              static extern uint RegisterWindowMessage(string lpString);
      
      
              private static UInt32 GetMessage()
              {
                  return RegisterWindowMessage("THIS_IS_MY_UNIQUE_MESSAGE");
              }
      
              protected override void WndProc(ref Message m)
              {
                  if (m.Msg == (int)GetMessage())
                  {
                      MessageBox.Show(@"Hello, from server");
                  }
                  base.WndProc(ref m);
              }
          }
      

      【讨论】:

      • 不错。传递一个字符串作为参数怎么样?
      猜你喜欢
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 1970-01-01
      • 2013-09-09
      相关资源
      最近更新 更多