C# 升级.NET时调用抛出System.ExecutionEngineeException(3.5->;4.5)

C# 升级.NET时调用抛出System.ExecutionEngineeException(3.5->;4.5),c#,.net,pinvoke,C#,.net,Pinvoke,我正在使用nsis7z.dll提取7z文件。该代码在.NET 3.5上运行良好,但当我使用.NET 4.5编译时,它确实提取了7z文件,但随后出现System.ExecutionEngineeException异常,导致崩溃。从我搜索的结果来看,使用P/Invoke发送的参数似乎有问题,主要是作为ref传递的参数 守则: public static bool ExtractNsis7z(string i_FileName, string i_ToDirectory) {

我正在使用nsis7z.dll提取7z文件。该代码在.NET 3.5上运行良好,但当我使用.NET 4.5编译时,它确实提取了7z文件,但随后出现System.ExecutionEngineeException异常,导致崩溃。从我搜索的结果来看,使用P/Invoke发送的参数似乎有问题,主要是作为ref传递的参数

守则:

        public static bool ExtractNsis7z(string i_FileName, string i_ToDirectory)
    {
        IntPtr ptr = GlobalAlloc((uint)GlobalMemoryFlags.GPTR, (UIntPtr)Marshal.SizeOf(typeof(stack)));

        stack st = (stack)Marshal.PtrToStructure(ptr, typeof(stack));

        st.next = IntPtr.Zero;

        for (int i = 0; i < i_FileName.Length && (i < st.text.Length - 1); i++)
        {
            st.text[i] = i_FileName[i];
        }

        return Extract7z(IntPtr.Zero, 0, i_ToDirectory, ref st, IntPtr.Zero);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public class stack
    {
        public IntPtr next;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
        public char[] text;

    };
    [DllImport("nsis7z.dll", EntryPoint = "Extract", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
    static extern bool Extract7z(IntPtr hWnd, Int32 stringSize, String outputDirectory, ref stack theStack, IntPtr extra);


    enum GlobalMemoryFlags : uint
    {
        GMEM_FIXED = 0x0000,
        GMEM_MOVEABLE = 0x0002,
        GMEM_ZEROINIT = 0x0040,
        GMEM_MODIFY = 0x0080,
        GMEM_VALID_FLAGS = 0x7F72,
        GMEM_INVALID_HANDLE = 0x8000,
        GHND = (GMEM_MOVEABLE | GMEM_ZEROINIT),
        GPTR = (GMEM_FIXED | GMEM_ZEROINIT),
        /*The following values are obsolete, but are provided for compatibility with 16-bit Windows. They are ignored.*/
        GMEM_DDESHARE = 0x2000,
        GMEM_DISCARDABLE = 0x0100,
        GMEM_LOWER = GMEM_NOT_BANKED,
        GMEM_NOCOMPACT = 0x0010,
        GMEM_NODISCARD = 0x0020,
        GMEM_NOT_BANKED = 0x1000,
        GMEM_NOTIFY = 0x4000,
        GMEM_SHARE = 0x2000
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
公共静态bool extracts7z(字符串i\u文件名,字符串i\u目录)
{
IntPtr ptr=GlobalAlloc((uint)GlobalMemoryFlags.GPTR,(uintpttr)marshall.SizeOf(typeof(stack));
stack st=(stack)Marshal.PtrToStructure(ptr,typeof(stack));
st.next=IntPtr.Zero;
对于(int i=0;i
ref Stack
看起来是错误的,因为
Stack
是一个类。不知道为什么需要调用
GlobalAlloc
来获取非托管内存。因为我们不能看到界面的C++侧,所以很难说多了。我建议如果你真的想要帮助你显示等价的C++代码。它实际上是正确的,一个疯狂的NSIS插件API约定。GlobalAlloc也是正确的,至少他不会用一根未端接的绳子射出他的腿。GC堆是如何损坏的很难理解,插件要做的第一件事就是将堆栈分配给一个全局变量。非常难看的代码,应该删除。7-zip的.NET包装是一个明显的替代方案。我找不到DLL的原始源代码。我所知道的是,这段代码在.NET3.5上运行得非常好,在.NET4.5上崩溃。它可能在3.5上也坏了,你会很幸运。使用@Hans引用的库。