[英]AccessViolationException in .NET framework 4.5 or higher
I'm trying to run a .NET C# console app found on internet ( article , code ). 我正在尝试运行在Internet上找到的.NET C#控制台应用程序( 文章 , 代码 )。
It uses a few pInvoke calls, and at some point triggers Marshal.PtrToStringUni(IntPtr ptr, int len)
. 它使用了几个pInvoke调用,并在某个时刻触发了
Marshal.PtrToStringUni(IntPtr ptr, int len)
。
What is very strange, and that I can't fix, is this: 我无法解决的很奇怪的是:
AccessViolationException
(the infamous "Attempted to read or write protected memory. This is often an indication that other memory is corrupt.") AccessViolationException
(臭名昭著的“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。”) The stack trace tells me: 堆栈跟踪告诉我:
at System.Buffer.Memmove(Byte* dest, Byte* src, UInt64 len) at System.String.CtorCharPtrStartLength(Char* ptr, Int32 startIndex, Int32 length) at System.Runtime.InteropServices.Marshal.PtrToStringUni(IntPtr ptr, Int32 len)
在System.String.CtorCharPtrStartLength(Char * ptr,Int32 startIndex,Int32 length)在System.Buffer.Memmove(Byte * dest,Byte * src,UInt64 len)在System.Runtime.InteropServices.Marshal.PtrToStringUni(IntPtr ptr,Int32 LEN)
I've searched the net for hours, and saw similar problems, but nothing that could help me. 我已经在网上搜索了几个小时,发现了类似的问题,但是没有任何帮助。 I absolutely need to implement this functionality in my project, and feel that to compile this part in .Net Framework 4.0 while the rest is in higher version could open to some troubles in the future.
我绝对需要在我的项目中实现此功能,并认为在其余部分为更高版本的同时在.Net Framework 4.0中进行编译的这一部分将来可能会遇到一些麻烦。 Anyway, there has to be a way to make it work.
无论如何,必须有一种使其起作用的方法。
Is there a way to make this code work? 有没有办法使此代码有效?
EDIT : I just updated the link 'code'. 编辑:我刚刚更新了链接“代码”。 The author just commited a new version.
作者刚提交了一个新版本。
EDIT 2: I understand that not having code directly here doesn't makes one want to help. 编辑2:我知道没有直接在这里没有代码不会使一个想要帮助。 I thought that it would be more efficient to link to the article that list the important parts.
我认为链接到列出重要部分的文章会更有效。
So here is some context and some code: 所以这是一些上下文和一些代码:
The code aims to list all the files locked by a process. 该代码旨在列出进程锁定的所有文件。 It first gets a list of SYSTEM_HANDLE_INFORMATION.
它首先获取SYSTEM_HANDLE_INFORMATION的列表。 Here is the struct:
这是结构:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public int ProcessID;
public byte ObjectTypeNumber;
public byte Flags; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
public ushort Handle;
public int Object_Pointer;
public UInt32 GrantedAccess;
}
It iterates through the collection, and sends each item in the GetFileDetails Method. 它遍历该集合,并在GetFileDetails方法中发送每个项目。
Here is the method, I only copy it until the try/catch statement that fails in .NET 4.5, and succeeds in .NET 4.0: 这是方法,我只复制它,直到在.NET 4.5中失败并在.NET 4.0中成功的try / catch语句为止:
private static FileDetails GetFileDetails(Win32API.SYSTEM_HANDLE_INFORMATION sYSTEM_HANDLE_INFORMATION)
{
FileDetails fd = new FileDetails();
fd.Name = "";
IntPtr ipHandle = IntPtr.Zero;
Win32API.OBJECT_BASIC_INFORMATION objBasic = new Win32API.OBJECT_BASIC_INFORMATION();
IntPtr ipBasic = IntPtr.Zero;
Win32API.OBJECT_TYPE_INFORMATION objObjectType = new Win32API.OBJECT_TYPE_INFORMATION();
IntPtr ipObjectType = IntPtr.Zero;
Win32API.OBJECT_NAME_INFORMATION objObjectName = new Win32API.OBJECT_NAME_INFORMATION();
IntPtr ipObjectName = IntPtr.Zero;
string strObjectTypeName = "";
string strObjectName = "";
int nLength = 0;
int nReturn = 0;
IntPtr ipTemp = IntPtr.Zero;
if (!Win32API.DuplicateHandle(m_ipProcessHwnd, sYSTEM_HANDLE_INFORMATION.Handle,Win32API.GetCurrentProcess(), out ipHandle, 0, false, Win32API.DUPLICATE_SAME_ACCESS)) return fd;
ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
Win32API.NtQueryObject(ipHandle, (int) Win32API.ObjectInformationClass.ObjectBasicInformation, ipBasic, Marshal.SizeOf(objBasic), ref nLength);
objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
Marshal.FreeHGlobal(ipBasic);
ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
nLength = objBasic.TypeInformationLength;
while ((uint)(nReturn = Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectTypeInformation, ipObjectType, nLength, ref nLength)) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
{
Marshal.FreeHGlobal(ipObjectType);
ipObjectType = Marshal.AllocHGlobal(nLength);
}
objObjectType = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
if (Is64Bits())
{
ipTemp = new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32);
}
else
{
ipTemp = objObjectType.Name.Buffer;
}
try
{
strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
}
catch (AccessViolationException)
{
return null;
}
For those interested, the full code is available in the link above Thank you for your help 对于那些感兴趣的人,完整的代码可以在上面的链接中找到。谢谢您的帮助
Access Violation excpetion come from the OS because of some faulty pointers. 由于某些错误的指针,访问冲突专有权来自操作系统。 As .NET is designed to avoid naked pointers, there is only a few possible sources:
由于.NET旨在避免出现裸露的指针,因此只有少数几种可能的来源:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.