C # Использование VB6-Dll - AccessViolationException - PullRequest
1 голос
/ 09 апреля 2011

Я пытаюсь использовать VB6 DLL в программе на C #. Но я всегда получаю 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

А вот код C #, который пытается использовать VB6 Dll:

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

С уважением виктор

1 Ответ

1 голос
/ 11 апреля 2011

Ваш byte[] b не имеет завершающего нуля, поэтому не является действительным неуправляемым LPCSTR. Я не понимаю, почему вы возитесь с попыткой закодировать имя метода вручную, вместо того, чтобы объявлять GetProcAddress, как это, и заставить код взаимодействия Framework позаботиться о сортировке для вас:

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

Вы должны проверить возвращаемое значение (pAddressOfFunctionToCall). Если это IntPtr.Zero, как я полагаю, вы получаете, поскольку ваш аргумент lpProcName для GetProcAddress неверен, то попытка вызова через оболочку Delegate всегда даст AccessViolationException.

Кроме того, не забудьте вызвать FreeLibrary на дескрипторе модуля, когда вы закончите.

...