【问题标题】:C# Using VB6-Dll - AccessViolationExceptionC# 使用 VB6-Dll - AccessViolationException
【发布时间】:2011-04-14 05:37:32
【问题描述】:

我尝试在 C# 程序中使用 VB6 DLL。但我总是得到一个 AccessViolationException。也许你可以告诉我我做错了什么。 我在本教程中创建了一个 Test-VB6-DLL: http://oreilly.com/pub/a/windows/2005/04/26/create_dll.html

然后我尝试像在这篇文章中那样动态地使用这个 DLL: http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx?PageIndex=3#comments

但如果我尝试使用 [DLLImport]。我总是遇到 AccessViolationException。 也许有人可以给我一个提示。

问候 维克多

P.S.:我能够做的是创建对现有 DLL 的引用。但是这种方法有一个缺点,如果更新 DLL,我必须更新所有引用。这将发生(或多或少)开放,因为 dll 是正在开发的软件项目的一部分。也许有可能更新引用而不需要重新编译 C# 程序?


@MarkJ:不——二进制兼容性没有成功。

以下是来源: VB6-Dll:

Option Explicit

Public Function Increment(var As Integer) As Integer
   If Not IsNumeric(var) Then Err.Raise 5

   Increment = var + 1
End Function

这里是尝试使用 VB6 Dll 的 C# 代码:

class Program
{

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr LoadLibrary(String DllName);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, byte[] procedureName);
    static void Main(string[] args)
    {
        IntPtr pDll = LoadLibrary(@"P:\dev\Path\to\TestProjekt.dll");

        string x = "Increment";         
        Encoding e = Encoding.GetEncoding("ISO-8859-1");
        byte[] b = e.GetBytes(x);

        IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, b);
        Increment inc = Increment)Marshal.
                GetDelegateForFunctionPointer(pAddressOfFunctionToCall,
                                              typeof(Increment));

        int a = inc(5);    // <---- Here the AccessViolationException is thrown

        return;
    }
}

与此同时,我已经阅读了我能找到的任何文档,但我仍然不知道为什么这不起作用 grgrgrgrgr

问候 维克多

【问题讨论】:

  • 我忘了说:我使用的是 .Net 3.5 ;-)
  • 你做错了。从你的问题中完全无法猜测到有多错,你没有发布任何 sn-p 来查看。
  • 您可能需要在您的 VB6 dll 项目中使用二进制兼容性
  • 为什么不通过COM调用VB6 DLL呢?非常非常容易。

标签: c# vb6 dllimport access-violation


【解决方案1】:

您的byte[] b 没有终止空值,因此不是有效的非托管LPCSTR。我不明白您为什么要尝试手动对方法名称进行编码,而不是像这样声明 GetProcAddress 并让框架互操作代码为您处理编组:

public static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procedureName);

您必须检查返回值 (pAddressOfFunctionToCall)。当我相信你得到的是IntPtr.Zero 时,因为你对GetProcAddress 的 lpProcName 参数是错误的,那么尝试通过它的 Delegate 包装器调用总是会给出一个AccessViolationException

另外,完成后不要忽略在模块句柄上调用FreeLibrary

【讨论】:

  • 我已将已删除答案中的缺失代码放入问题中。实际上是版主删除了答案,而不是OP。不知道为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-05
相关资源
最近更新 更多