P/在托管代码中调用SetWindowLong和CallWindowProc(紧凑框架)

时间:2022-07-17 03:46:05

I am trying to override the window procedure for the winmobile taskbar (in order to catch and block pressed buttons) by using SetWindowLong. I have created a class with one method for overriding and one for restoring the window procedure. The MessageReceived method is the one I use to replace the taskbar window procedure with. My class looks the following way:

我正在尝试使用SetWindowLong来覆盖winmobile任务栏的窗口过程(以捕获和阻塞按下的按钮)。我创建了一个类,其中有一个方法用于重写,另一个方法用于恢复窗口过程。MessageReceived方法是我用来替换任务栏窗口过程的方法。我的班级看起来是这样的:

class ButtonBlocker
{
  public delegate IntPtr WindowProc(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam);

  public static WindowProc newWindowDeleg;
  private static IntPtr oldWindowProc;

  [DllImport("coredll.dll")]
  static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  [DllImport("coredll.dll")]
  static extern int GetWindowLong(IntPtr hWnd, int nIndex);

  [DllImport("coredll.dll")]
  static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

  [DllImport("coredll.dll", EntryPoint = "FindWindow")]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

  private static IntPtr MessageReceived(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam)
  {
      Debug.WriteLine("Message received");
      return CallWindowProc(oldWindowProc, hwnd, uMsg, wParam, lParam);
  }

  public static void OverrideWindowProc()
  {
      newWindowDeleg = MessageReceived;

      IntPtr taskBarHandle = FindWindow("HHTaskBar", null);

      int newWndProc = Marshal.GetFunctionPointerForDelegate(newWindowDeleg).ToInt32();
      int result = SetWindowLong(taskBarHandle, -4, newWndProc);
      oldWindowProc = (IntPtr)result;
      if (result == 0)
      {
          MessageBox.Show("Failed to SetWindowLong");
      }
  }

  public static void RestoreWindowProc()
  {
      IntPtr taskBarHandle = FindWindow("HHTaskBar", null);
      int result = SetWindowLong(taskBarHandle, -4, oldWindowProc.ToInt32());
  }
}

The behavior in the mobile emulator is the following - after I press a button, "Message received" is displayed in the Debug output, but the program crashes and offers to send a crash report to Microsoft. The visual studio debugger hangs and doesn't react to the stop command. It unfreezes only after an emulator reset. The problem seems to be with the CallWindowProc at the end of the MessageReceived method. Most probably, there is some issue with the old windowproc address. If I try to execute the RestoreWindowProc code immediately after the OverrideWindowProc code (with no messages being intercepted by my function), the application exits okay and the debugger does not freeze. Any ideas on how to get this to work would be appreciated.

移动仿真器中的行为是这样的——在我按下一个按钮后,“接收到的消息”将显示在调试输出中,但是程序崩溃并提供向Microsoft发送崩溃报告。visual studio调试器挂起,对停止命令没有反应。它只有在仿真器重置后才解冻。问题似乎在于MessageReceived方法末尾的CallWindowProc。最可能的是,旧的windowproc地址有一些问题。如果我试图在OverrideWindowProc代码之后立即执行RestoreWindowProc代码(我的函数没有拦截任何消息),则应用程序退出,调试器不会冻结。任何关于如何使它工作的想法都将被感激。

I am using Visual Studio 2008 SP1. The project targets .NET framework v3.5, Windows Mobile 6 Professional.

我正在使用Visual Studio 2008 SP1。这个项目的目标是。net framework v3.5, Windows Mobile 6 Professional。

1 个解决方案

#1


3  

You cannot replace the window procedure of a window that is owned by another process. The address of the replacement function is only valid in your process. It causes an immediate bomb in the other process. You would have to inject a DLL into the target process to work around this problem. You can't inject DLLs written in a managed language, the CLR isn't initialized.

不能替换另一个进程拥有的窗口的窗口过程。替换函数的地址只在您的过程中有效。它会在另一个过程中立即产生一颗炸弹。您需要向目标进程注入一个DLL来解决这个问题。不能注入用托管语言编写的dll, CLR没有初始化。

#1


3  

You cannot replace the window procedure of a window that is owned by another process. The address of the replacement function is only valid in your process. It causes an immediate bomb in the other process. You would have to inject a DLL into the target process to work around this problem. You can't inject DLLs written in a managed language, the CLR isn't initialized.

不能替换另一个进程拥有的窗口的窗口过程。替换函数的地址只在您的过程中有效。它会在另一个过程中立即产生一颗炸弹。您需要向目标进程注入一个DLL来解决这个问题。不能注入用托管语言编写的dll, CLR没有初始化。