簡體   English   中英

使用參數從C#調用void函數(在win32中)

[英]Calling a void function (in win32) from C# with parameters

我在win32中有以下代碼,它在目標應用程序中設置了一個鈎子。

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函數中使用的threadID。 (它只是小數而不是十六進制)

但我收到此錯誤消息:

檢測到PInvokeStackImbalance消息:調用PInvoke函數'TheOperator!TheOperator.Form1 :: InstallHook'使堆棧失去平衡。 這很可能是因為托管PInvoke簽名與非托管目標簽名不匹配。 檢查PInvoke簽名的調用約定和參數是否與目標非托管簽名匹配。

我試圖將我的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返回。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM