c# - 使用参数从 C# 调用 void 函数(在 win32 中)

标签 c# .net winapi dll dllimport

我在 win32 中有以下代码,它在目标应用程序中设置了一个 Hook 。

void InstallHook(DWORD ThreadId)
{
    g_hHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, g_hInstDll, ThreadId); 
}

我希望从 C# (.net) 调用此函数。

到目前为止我有这个:

[DllImport("TheHookDll.dll")]
public extern static void InstallHook(UInt32 ThreadId);

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

我这样调用它:

IntPtr hWnd = FindWindow(null, "MyTargetAppWindowTitle");

UInt32 threadID = GetWindowThreadProcessId(hWnd, IntPtr.Zero);

InstallHook(threadID);

这为我提供了目标的句柄 (hWnd),以及在 win32 中的 InstallHook 函数中使用的线程 ID。 (它只是小数而不是十六进制)

但我收到此错误消息:

PInvokeStackImbalance was detected Message: A call to PInvoke function 'TheOperator!TheOperator.Form1::InstallHook' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

我试图将我的 dll 文件中的调用约定(配置属性 -> C/C++ -> 所有选项 -> 调用约定)从 __cdel 更改为 __stdcall,但没有成功。 (同样的错误)

我做错了什么?

我已将 DWORD 更改为 UInt32,因为 c# 不支持 DWORD 等。但这是正确的方法吗?

有什么提示吗?

最佳答案

像这样定义您的 PInvoke:

    [DllImport("TheHookDll.dll", CallingConvention = CallingConvention.Cdecl)]
    public extern static void InstallHook(UInt32 ThreadId);

原因是当您调用这个特定函数时,调用者需要清理堆栈。如果不在您的 PInvoke 签名中明确指定它,运行时将不会清理堆栈,因此它会弄乱堆栈,从而导致您看到的错误消息。

如果您没有明确指定 CallingConvention,运行时会假定您尝试调用的函数是一个 StdCall,其中被调用者会清理堆栈。事实并非如此,堆栈将变得一团糟和肮脏。

除此之外,您的签名看起来是正确的; DWORD 在 C# 中确实是 uintUInt32。如果那个给你带来麻烦,你可以尝试用 MarshalAs 属性装饰它并让 Marshal 将它作为非托管类型 U8 返回。

关于c# - 使用参数从 C# 调用 void 函数(在 win32 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17602450/

相关文章:

c# 从控制台应用程序显示窗口窗体

c++ - 删除 ListView 中特定项目的复选框

c# - 如何在 C# 中通过表达式树构建集合过滤器

c# - IQueryable、List、IEnumerator 之间的区别?

ruby-on-rails - Rails - 大型数据库查询

c# - 从列表对象的列表字段中删除元素的最佳方法

c++ - Win32 ListView 中的可变高度项目

c - WWindow 创建文件 读取文件 写入文件

c# - 如何为 HttpClient (WinForms) 设置默认的 json 序列化设置

C# 应用程序调用 Powershell 脚本问题