Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# PinVokeStackResponsibility-从HookCallback调用非托管代码 我的目标_C#_.net_Pinvoke_Mouse Hook - Fatal编程技术网

C# PinVokeStackResponsibility-从HookCallback调用非托管代码 我的目标

C# PinVokeStackResponsibility-从HookCallback调用非托管代码 我的目标,c#,.net,pinvoke,mouse-hook,C#,.net,Pinvoke,Mouse Hook,我想将左键单击转换为右键单击 我的方法 我通过SetWindowsHookEx(user32.dll)注册一个低级钩子 过滤鼠标左键单击 检查我是否要翻译特定的点击 如果我真的想 不要传递信息 通过鼠标事件(user32.dll)创建新的鼠标单击 问题 当我这样做时: private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if(nCode >= 0 &&

我想将左键单击转换为右键单击

我的方法
  • 我通过SetWindowsHookEx(user32.dll)注册一个低级钩子
  • 过滤鼠标左键单击
  • 检查我是否要翻译特定的点击
  • 如果我真的想
    • 不要传递信息
    • 通过鼠标事件(user32.dll)创建新的鼠标单击
问题 当我这样做时:

  private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
     if(nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam && doRight) {
        doRight = false;
        MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
        mouse_event(/*right down + right up*/8 | 16, hookStruct.pt.x, hookStruct.pt.y, 0, 0);
        return new IntPtr(1);
     }
     return CallNextHookEx(_hookID, nCode, wParam, lParam);
  }
调用mouse_事件失败,出现一个PinVokeStack异常,我想我应该关心这个异常

DllImports 由于通常情况下,PinvokesTack不平衡是由不正确的导入签名引起的,因此我的签名如下:

  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  [return: MarshalAs(UnmanagedType.Bool)]
  private static extern bool UnhookWindowsHookEx(IntPtr hhk);

  [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

  [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  private static extern IntPtr GetModuleHandle(string lpModuleName);

  [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
出现
在这种情况下,我通常隔离问题的方法失败了——因为鼠标事件调用本身可以工作,而左键点击也可以工作。我讨厌当结构超过部分的总和时…

鼠标事件签名应该是这样的

public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, IntPtr dwExtraInfo);

鼠标事件签名应该是这样的

public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, IntPtr dwExtraInfo);

鼠标事件定义为:

VOID WINAPI mouse_event(
  __in  DWORD dwFlags,
  __in  DWORD dx,
  __in  DWORD dy,
  __in  DWORD dwData,
  __in  ULONG_PTR dwExtraInfo
);
WINAPI表示StdCall,DWORD表示uint,ULONG_PTR表示uintpttr。因此,正确地说,应该是:

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
问题是,long在C#中定义为64位,而(u)int是32位。(U) IntPtr是32位还是64位,取决于操作系统的位数


编辑:换句话说,您向函数传递的数据太多。由于被调用方清理堆栈,PInvoke注意到并非所有内容都已从堆栈中删除。它会为您执行此操作(但您传递了错误的数据,因此该函数可能执行了与您所希望的不同的操作)并向您发出警告。

鼠标事件定义为:

VOID WINAPI mouse_event(
  __in  DWORD dwFlags,
  __in  DWORD dx,
  __in  DWORD dy,
  __in  DWORD dwData,
  __in  ULONG_PTR dwExtraInfo
);
WINAPI表示StdCall,DWORD表示uint,ULONG_PTR表示uintpttr。因此,正确地说,应该是:

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
问题是,long在C#中定义为64位,而(u)int是32位。(U) IntPtr是32位还是64位,取决于操作系统的位数

编辑:换句话说,您向函数传递的数据太多。由于被调用方清理堆栈,PInvoke注意到并非所有内容都已从堆栈中删除。它会为您执行此操作(但您传递了错误的数据,因此该函数可能执行了与您所希望的不同的操作)并警告您。

Internet上有许多错误的p/invoke声明。他们通常从VB6开始生活。在该语言中,整数是16位,长是32位。返回到在16位操作系统上运行的VB1。它们在VB.NET或C#中无法正常工作

堆栈不平衡MDA是专门为捕捉这种错误声明而设计的,但它是一个选项(调试+异常)。如果只有一个参数或传递了大量零,则实际调用往往会起作用。不幸的是,调用后代码保持正常运行的几率也不坏。当方法返回时,堆栈指针值会自动更正。不过,你可能会遇到一些非常棘手的问题。

互联网上有很多糟糕的p/invoke声明。他们通常从VB6开始生活。在该语言中,整数是16位,长是32位。返回到在16位操作系统上运行的VB1。它们在VB.NET或C#中无法正常工作


堆栈不平衡MDA是专门为捕捉这种错误声明而设计的,但它是一个选项(调试+异常)。如果只有一个参数或传递了大量零,则实际调用往往会起作用。不幸的是,调用后代码保持正常运行的几率也不坏。当方法返回时,堆栈指针值会自动更正。不过,你可能会遇到一些非常棘手的问题。

该死的,我真傻——我甚至说通常签名是错误的。。。但现在我想知道-我从另一个项目(生产代码)复制了sig,它正在那里工作。。。发生了什么?P/Invoke在某种程度上可以原谅不正确的签名,尽管在您的情况下,不正确的数据可能会传递给函数。为了警告您签名不正确,PinVokeStacks调试助手在激活时会触发。该死的,我很愚蠢-我甚至说通常签名是错误的。。。但现在我想知道-我从另一个项目(生产代码)复制了sig,它正在那里工作。。。发生了什么?P/Invoke在某种程度上可以原谅不正确的签名,尽管在您的情况下,不正确的数据可能会传递给函数。为警告您的签名不正确,PinVokeStack托管调试助手将在其处于活动状态时触发。我知道CLR数据类型定义,但我只是傻到期望我们的productioncode是正确的:)我知道CLR数据类型定义,我只是傻到期望我们的productioncode是正确的:)