尝试使用 GetClassName 读取或写入受保护的内存
Attempted to read or write to protected memory with GetClassName
我目前正在编写一个 explorer.exe 包装器(文件夹视图,而不是另一个),并且我有一个来自 User32.dll#EnumChildWindows 的 IntPtr 列表。当我循环遍历 IntPtr 时,无论选择哪个 IntPtr,我都会得到 System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
使用 GetClassName 后:
string name0;
foreach (IntPtr ptr in list) {
name0="";
if (GetClassName(ptr,out name0,(IntPtr)14)!=IntPtr.Zero) //exception here on GetClassName
if (name0=="SysTreeView32") { this.QuickAccessTreeView=ptr; break; }
}
我认为这是出于保护目的,但也可能不是。如果是,我的问题是:解决这个问题的方法是什么?这不像我要检索很多信息,只是控件的 class 名称。如果这不是故意的,那么我的问题是为什么这不起作用?
您传递的缓冲区大小为 14,但 name0
变量为空。
您必须 pre-allocate 内存,传递正确的缓冲区大小并检查函数的 return 值:
确保您的 PInvoke 签名正确 GetClassName。
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
如文档中所述,函数 return 在失败的情况下为零。
var className = new StringBuilder(256);
if(GetClassName(ptr, className, className.Capacity)>0)
{
// do more processing
}
我目前正在编写一个 explorer.exe 包装器(文件夹视图,而不是另一个),并且我有一个来自 User32.dll#EnumChildWindows 的 IntPtr 列表。当我循环遍历 IntPtr 时,无论选择哪个 IntPtr,我都会得到 System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
使用 GetClassName 后:
string name0;
foreach (IntPtr ptr in list) {
name0="";
if (GetClassName(ptr,out name0,(IntPtr)14)!=IntPtr.Zero) //exception here on GetClassName
if (name0=="SysTreeView32") { this.QuickAccessTreeView=ptr; break; }
}
我认为这是出于保护目的,但也可能不是。如果是,我的问题是:解决这个问题的方法是什么?这不像我要检索很多信息,只是控件的 class 名称。如果这不是故意的,那么我的问题是为什么这不起作用?
您传递的缓冲区大小为 14,但 name0
变量为空。
您必须 pre-allocate 内存,传递正确的缓冲区大小并检查函数的 return 值:
确保您的 PInvoke 签名正确 GetClassName。
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetClassNameW", CharSet = CharSet.Unicode)] static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
如文档中所述,函数 return 在失败的情况下为零。
var className = new StringBuilder(256); if(GetClassName(ptr, className, className.Capacity)>0) { // do more processing }