C # с использованием VB6-Dll - AccessViolationException

Я пытаюсь использовать DLL VB6 в программе на 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

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


person viktor    schedule 08.04.2011    source источник
comment
Забыл упомянуть: я использую .Net 3.5 ;-)   -  person viktor    schedule 09.04.2011
comment
Ты делаешь это неправильно. Насколько неверно, совершенно невозможно понять из вашего вопроса, вы не разместили ни одного фрагмента, на который можно было бы посмотреть.   -  person Hans Passant    schedule 09.04.2011
comment
Вероятно, вам нужно использовать двоичную совместимость в вашем проекте DLL VB6   -  person MarkJ    schedule 09.04.2011
comment
Почему бы не вызвать VB6 DLL через COM? Намного, намного проще.   -  person MarkJ    schedule 13.04.2011


Ответы (1)


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

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

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

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

person Chris Dickson    schedule 11.04.2011
comment
Я ввел в вопрос недостающий код из удаленного ответа. На самом деле ответ удалил модератор, а не ОП. Не знаю почему. - person MarkJ; 13.04.2011