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