2011-09-16 50 views
3

我一直在爲這一整晚奮戰。我只是沒有什麼錯。我正在嘗試獲取桌面圖標+標題大小。我有一些函數可以找到桌面句柄並將其放入名爲SysListView32_hwnd的變量中。我已經驗證它是正確的與Windows間諜程序。這是我遇到麻煩的部分。使用LVM_GETITEMRECT消息獲取桌面圖標大小

Rectangle rct = new Rectangle(); 
IntPtr pRct = Marshal.AllocHGlobal(Marshal.SizeOf(rct)); 
Marshal.StructureToPtr(rct, pRct, true); 

SendMessage(SysListView32_hwnd, LVM_GETITEMRECT, (IntPtr)0, pRct); 

Rectangle Rect = (Rectangle)Marshal.PtrToStructure(pRct, typeof(Rectangle)); 
Marshal.FreeHGlobal(pRct); 
Debug.WriteLine(Rect.Height + " " + Rect.Width); 

它每次都會崩潰瀏覽器。 C#的Visual Studio 2010 的Windows 7 x64和我編譯爲64位程序

Here是我的全部應用程序,如果需要

+0

你知道哪一行崩潰了explorer /導致異常嗎? – jadarnel27

+0

@ jardarnel27這很容易,它是SendMessage –

+0

@David對你來說很容易,也許。在這個問題中,這是一個很好的做法,在程序被炸燬的地方。這樣人們就不必假設/猜測。 – jadarnel27

回答

1

這解決了大量的編輯之前的原始問題。

它失敗了,因爲寫入它的方式只能在您從擁有目標窗口句柄的進程調用時才起作用。這是因爲你傳遞了一個指針,但這隻在你的過程中有效。一旦它落在另一個進程中,它就指向一個毫無意義的地址。即使它確實意味着什麼,一個進程無法在系統幫助下讀取另一個進程內存。自然探險家炸彈。

解決方案是使用VirtualAllocEx()在資源管理器進程中分配內存。然後發送消息。然後使用ReadProcessMemory()將rect的內容編組回到您的過程中。最常被引用的代碼示例是Code Project article。該示例使用LVM_GETITEMTEXT,但原理是相同的。

2

這解決了問題的廣泛編輯中提出的其他問題。

在我看來,像我們與LVITEMsVirtualAllocEx指定sizeof(uint)工作。

VirtualAllocEx()dwSize參數的文檔,MSDN上,規定:

的存儲器中的區域的大小來分配,以字節爲單位。

如果lpAddress爲NULL,則函數將dwSize舍入到下一個頁面邊界。

如果lpAddress不爲NULL,則該函數將分配從lpAddress到lpAddress + dwSize範圍內包含一個或多個字節的所有頁面。這意味着,例如跨頁邊界的2字節範圍會導致函數分配兩個頁面。

換句話說,它分配整個頁面。由於一個頁面是4KB,你會得到好運。您應該確保dwSize足夠大,以滿足您所需的緩衝區。

爲什麼pszText =(IntPtr的)((INT)lpBaseAddress + Marshal.SizeOf(typeof運算(LVITEM)))?這不就是指結構的結束嗎?

是的,它指向結構的末尾。重點在於LVITEMpszText字段必須指向調用者分配的緩衝區。編寫這段代碼的人選擇在結構的末尾使用備用緩衝區空間。由於該結構聲明pszText包含256個字節,因此它很容易放入4KB頁面的剩餘部分。所以它有用,但它有點不透明。

+1

好的謝謝,這是我不明白。 –

+0

這兩個都是非常好的答案。 – jadarnel27