【问题标题】:C# Interface to DLL and ExecutionEngineExceptionDLL 和 ExecutionEngineException 的 C# 接口
【发布时间】:2017-08-25 20:12:22
【问题描述】:

C# 新手。我已经编写了一个可以工作的 WDF 驱动程序和 DLL。我正在用 C# 创建一个应用程序来通过 DLL 访问硬件。有一个特定的函数在第一次调用后不久就会导致 ExecutionEngineException。以下是 DLL 中的函数定义:

DECLDIR int ReadDatagram(int channel, unsigned long *msgID, unsigned int *msgType, int *msgLen, unsigned int *data);

在我的 C# 应用程序代码中,我使用以下行导入此函数:

[DllImport("pcmcanDLL.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern int ReadDatagram(int channel, ref uint msgID, ref uint msgType, ref int msgLen, uint[] data);

当我启动应用程序并打开一个频道时,这个函数会被一个计时器定期调用。在很短的不确定时间后,我收到以下异常消息。如果我注释掉他对这个函数的调用,应用程序永远不会有问题。

消息:mscorlib.dll 中出现“System.ExecutionEngineException”类型的未处理异常

我的应用程序代码在这里。我相信我正在正确处理指针参数,因为偶尔这会工作几次,并且这些数据在这些停止中是好的。欣赏任何见解。

private void rcvTimer_Tick(object sender, EventArgs e)
{
    int channel = 1;
    String dsplyString = "Packet Received\n";
    uint msgID = 0, msgType = 0;
    int msgLen = 0;
    uint[] data = new uint[8];
    ErrorTypes dllReturn = ErrorTypes.RCV_BUFFER_EMPTY;

    do
    {
        dllReturn = (ErrorTypes)NativeMethods.ReadDatagram(channel, ref msgID, ref msgType, ref msgLen, data);

        if (dllReturn != ErrorTypes.SUCCESS && dllReturn != ErrorTypes.RCV_BUFFER_EMPTY)
        {
            MessageBox.Show("Error receiving packet.", "Receipt Error",
               MessageBoxButtons.OK, MessageBoxIcon.Error);
            break;
        }
        else if (dllReturn == ErrorTypes.SUCCESS)
        {
           dsplyString = String.Format("{0}  {1}  {2}  {3}\n", channel, msgID, msgType, msgLen);
        }
    } while (dllReturn != ErrorTypes.RCV_BUFFER_EMPTY);

}

【问题讨论】:

  • 还看到了以下错误消息:mscorlib.dll 中发生了“System.AccessViolationException”类型的未处理异常附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
  • 很难说你做错了什么,因为没有关于如何调用 DLL 的规范。仅仅知道参数的类型是不够的。

标签: c# .net exception dll


【解决方案1】:

尝试关注

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {

        }

    }
    public enum ErrorTypes : int
    {
        RCV_BUFFER_EMPTY = 0,
        SUCCESS = 1
    }
    public class Test
    {
        [DllImport("pcmcanDLL.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int ReadDatagram(int channel, ref uint msgID, IntPtr msgType, ref int msgLen, IntPtr dataPtr);

        private void rcvTimer_Tick(object sender, EventArgs e)
        {
            int channel = 1;
            String dsplyString = "Packet Received\n";
            uint msgID = 0;
            uint msgType = 0;
            int msgLen = 0;
            uint[] data = new uint[8];


            ErrorTypes dllReturn = ErrorTypes.RCV_BUFFER_EMPTY;

            IntPtr dataPtr = Marshal.AllocHGlobal(Marshal.SizeOf(data));
            IntPtr msgTypePtr = Marshal.AllocHGlobal(Marshal.SizeOf(msgType));
            do
            {
                Marshal.StructureToPtr(msgType, msgTypePtr, true);
                Marshal.StructureToPtr(data, dataPtr, true);
                dllReturn = (ErrorTypes)ReadDatagram(channel, ref msgID, msgTypePtr, ref msgLen, dataPtr);


                if (dllReturn != ErrorTypes.SUCCESS && dllReturn != ErrorTypes.RCV_BUFFER_EMPTY)
                {
                    MessageBox.Show("Error receiving packet.", "Receipt Error",
                       MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
                }
                else if (dllReturn == ErrorTypes.SUCCESS)
                {
                   dsplyString = String.Format("{0}  {1}  {2}  {3}\n", channel, msgID, msgType, msgLen);
                }
            } while (dllReturn != ErrorTypes.RCV_BUFFER_EMPTY);

            Marshal.FreeHGlobal(dataPtr);
            Marshal.FreeHGlobal(msgTypePtr);

        }
    }
}

【讨论】:

  • 这里有很多错误
  • 您甚至没有尝试过代码,那么您怎么知道它不起作用?您所做的只是制作否定的 cmets,并且永远不会发布真正的解决方案。
  • 查看我在 pinvoke 标签中的记录,发现不是真的。
  • 你为什么不在这里发布解决方案?
  • 因为没有足够的信息来明确回答。再次,您对 IntPtr 的使用很奇怪。所有这些类型都可以由 pinvoke 框架自然地编组。无需手动进行。如果您手动进行,则不需要这样做,但如果您这样做,则应该正确完成。你没有这样做。我不想解释你为什么弄错了,因为我在之前的问题中这样做了,而你没有听。
猜你喜欢
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多