C# 内核32 VirtualAllocEx间歇性返回IntPtr.Zero
我们正在尝试从系统托盘图标中读取工具提示,代码正在工作,但是对于下面调用Kernel32.VirtualAllocEx的方法,它会间歇性地返回零C# 内核32 VirtualAllocEx间歇性返回IntPtr.Zero,c#,interop,tooltip,intptr,C#,Interop,Tooltip,Intptr,我们正在尝试从系统托盘图标中读取工具提示,代码正在工作,但是对于下面调用Kernel32.VirtualAllocEx的方法,它会间歇性地返回零 IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx( hProcess, IntPtr.Zero, new UIntPtr(BUFFER_SIZE), MemAllocationType.COMMIT, MemoryProtection.PAGE_READWRI
IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
hProcess,
IntPtr.Zero,
new UIntPtr(BUFFER_SIZE),
MemAllocationType.COMMIT,
MemoryProtection.PAGE_READWRITE);
if (ipRemoteBuffer == IntPtr.Zero)
return String.Empty;
它似乎工作得非常好,然后突然停止工作并始终返回IntPtr.Zero。检查Marshal.GetLastWin32Error()时,返回8(内存不足)。以下是完整代码:
public static string GetTooltip(string search)
{
IntPtr _ToolbarWindowHandle = GetSystemTrayHandle();
UInt32 count = User32.SendMessage(_ToolbarWindowHandle, TB.BUTTONCOUNT, 0, 0);
List<string> tooltips = new List<string>();
for (int i = 0; i < count; i++)
{
TBBUTTON tbButton = new TBBUTTON();
string text = String.Empty;
IntPtr ipWindowHandle = IntPtr.Zero;
text = GetTBButtonText(_ToolbarWindowHandle, i, ref tbButton, ref text, ref ipWindowHandle);
if (!String.IsNullOrWhiteSpace(text) && text.ToLowerInvariant().Contains(search.ToLowerInvariant()))
return text;
}
return String.Empty;
}
static unsafe string GetTBButtonText(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle)
{
const int BUFFER_SIZE = 0x1000;
byte[] localBuffer = new byte[BUFFER_SIZE];
UInt32 processId = 0;
UInt32 threadId = User32.GetWindowThreadProcessId(hToolbar, out processId);
IntPtr hProcess = Kernel32.OpenProcess(ProcessRights.ALL_ACCESS, false, processId);
if (hProcess == IntPtr.Zero)
return String.Empty;
IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
hProcess,
IntPtr.Zero,
new UIntPtr(BUFFER_SIZE),
MemAllocationType.COMMIT,
MemoryProtection.PAGE_READWRITE);
if (ipRemoteBuffer == IntPtr.Zero)
{
var error = Marshal.GetLastWin32Error();
return String.Empty;
}
// TBButton
fixed (TBBUTTON* pTBButton = &tbButton)
{
IntPtr ipTBButton = new IntPtr(pTBButton);
int b = (int)User32.SendMessage(hToolbar, TB.GETBUTTON, (IntPtr)i, ipRemoteBuffer);
if (b == 0)
return String.Empty;
// this is fixed
Int32 dwBytesRead = 0;
IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
bool b2 = Kernel32.ReadProcessMemory(
hProcess,
ipRemoteBuffer,
ipTBButton,
new UIntPtr((uint)sizeof(TBBUTTON)),
ipBytesRead);
if (!b2)
return String.Empty;
}
// button text
fixed (byte* pLocalBuffer = localBuffer)
{
IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);
int chars = (int)User32.SendMessage(hToolbar, TB.GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer);
if (chars == -1) { Debug.Assert(false); return ""; }
// this is fixed
Int32 dwBytesRead = 0;
IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
bool b4 = Kernel32.ReadProcessMemory(
hProcess,
ipRemoteBuffer,
ipLocalBuffer,
new UIntPtr(BUFFER_SIZE),
ipBytesRead);
if (!b4)
return String.Empty;
text = Marshal.PtrToStringUni(ipLocalBuffer, chars);
return text;
}
}
publicstaticstringgettooltip(字符串搜索)
{
IntPtr_ToolbarWindowHandle=GetSystemTrayHandle();
UInt32 count=User32.SendMessage(_ToolbarWindowHandle,TB.BUTTONCOUNT,0,0);
列表工具提示=新建列表();
for(int i=0;i
如果我打电话释放内存,那么问题就解决了
const uint MEM_RELEASE = 0x8000;
UIntPtr uintPtr = UIntPtr.Zero;
var successfullyReleased = Kernel32.VirtualFreeEx(hProcess, ipRemoteBuffer, uintPtr, MEM_RELEASE);
if (!successfullyReleased)
{
}
调用
Marshal.GetLastError
以在任何P/Invoke失败时获取错误代码。它返回8,这似乎是错误\u内存不足\u内存8(0x8)没有足够的存储空间来处理此命令。无论如何,我没有记错,所以我必须对此做一些研究。谢谢你的回复。没有评论的否决投票?是的,这是标准做法。否决票不需要评论。他们也没有投票权。同样,你也不应该在否决票后留下评论。我想这对我来说没有意义,要么有人知道我在问什么,在这种情况下,他们指出我哪里出了问题,或者我怎么完全没有抓住要点/是个白痴,要么他们什么都不知道,在这种情况下,他们不发表评论,继续前进。哦,好吧。。。。希望有更多互操作经验的人仍能提供帮助。对粗鲁和辱骂的人投反对票是的,但不是因为不知道什么:S