简体   繁体   English

.NET Framework 4.5或更高版本中的AccessViolationException

[英]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: 我无法解决的很奇怪的是:

  • If I compile the project to .NET Framework 4.0, it works. 如果我将项目编译为.NET Framework 4.0,则可以正常工作。
  • Under .NET framework 4.5 or higher, it throws a AccessViolationException (the infamous "Attempted to read or write protected memory. This is often an indication that other memory is corrupt.") 在.NET Framework 4.5或更高版本中,它将引发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旨在避免出现裸露的指针,因此只有少数几种可能的来源:

  • Calling Unamanaged Code via P/Invoke or COM interop. 通过P / Invoke或COM互操作调用非托管代码。
  • Binarity missmatch. 二元错配。 If the unmanaged code you call is x32 and you call it from x64 (or vice versa), it will not work. 如果您调用的非托管代码是x32,并且是从x64调用的(反之亦然),则它将无法正常工作。 The way around that is to either hardcode the binarity or use a helper process of proper binarity. 解决方法是对二进制文件进行硬编码或使用适当二进制文件的帮助程序。 The linked code is said to exlcusively run for x64. 据说链接的代码专门为x64运行。 If you do not define binarity, the Framework can pick "whatever" binarity it feels like today. 如果您没有定义二元性,那么框架可以选择当今的“任何”二元性。 Have you picked the Target of the Project accordingly? 您是否已相应选择了项目目标?
  • 3rd parter interferece. 第三分手干涉。 It was a few years back, but we had a case where a certain Virus scanner would kill every other Windows Forms application. 几年前,但是我们遇到了一个案例,即某个病毒扫描程序会杀死所有其他Windows Forms应用程序。 Try excludin the programm/turning background protection off for a spell. 尝试排除程序/关闭背景保护以防出现咒语。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 .NET目标框架兼容性和编译器 - 在.NET 4.5或更高版本上 - .NET target framework compatibility and the compiler - on .NET 4.5 or higher Asp.NET MVC应用程序是使用.net Framework 4.5版构建的,我想在更高的.net框架4.7.2上运行该应用程序 - An Asp.NET MVC application is built with .net framework version 4.5, I want to run the application on a higher .net framework that is 4.7.2 C# AccessViolationException 与 .NET 4.5 或更高版本中的互操作回调 - C# AccessViolationException with interop callbacks in .NET 4.5 or above 更改.NET Framework会导致System.AccessViolationException - Changing .NET framework causes System.AccessViolationException 将SignalR与.net Framework 4.5集成 - Integrating SignalR with .net framework 4.5 静默安装.NET Framework 4.5 - Silent installation of .NET framework 4.5 在 .NET 框架 4.5 中使用雪花 - Using Snowflake in .NET Framework 4.5 .Net Framework 4.5中的数组的MaxSize - MaxSize of array in .Net Framework 4.5 .net框架4中的高内存问题,但在框架4.5中没有 - High Memory issues in .net framework 4 but not in framework 4.5 安装Framework 4.5时,以.NET Framework 4为目标 - Targeting .NET Framework 4 when Framework 4.5 is installed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM