COM Interop выбрасывает EEMessageException при вызове управляемой DLL - PullRequest
3 голосов
/ 06 июля 2011

Какой кошмар COM-взаимодействия доказывает мне.У меня есть простая управляемая DLL, содержащая окно WPF.У меня есть простой класс ViewController, который в конечном итоге будет запускать это окно, но сейчас у него есть пустой метод, который ничего не делает.

Я создал управляемую оболочку для этой управляемой DLL, которая предоставляет интерфейс, зарегистрированный для взаимодействия COM.Я могу позвонить в мою управляемую упаковку ОК.Я могу отобразить MessageBox в точке входа моей управляемой DLL-библиотеки-оболочки.Однако, если я пытаюсь вызвать ЛЮБОЙ метод для этого класса ViewController в DLL, которую я упаковываю, я получаю следующее:

Исключение первого шанса в 0x7c812aeb (kernel32.dll) в MfcVSApp1.exe: исключение Microsoft C ++:EEMessageException в ячейке памяти 0x0012cb30 ..

Очевидно, все это работало вчера.Теперь немного кода:

Мои объекты-оболочки:

[Guid("83C799E0-9808-40c2-A1AB-80BCB77A3B18")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface IMaryln
    {
        void GetEphemeris(DateTime date, double latitude, double longitude);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="date"></param>
        /// <param name="latitude"></param>
        /// <param name="longitude"></param>
        void GetEphemeris1(Int64 millSecsSince1970, double latitude, double longitude);
    }

 [Guid("144DB386-D8EF-41a8-B9B1-57EE8A64600C")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("ManagedProxy.Maryln")]
    [ComVisible(true)]
    public class Maryln : IMaryln
    {
        #region IMaryln Members

        public Maryln()
        {
            System.Diagnostics.Debugger.Launch();
        }

        public void GetEphemeris(DateTime date, double latitude, double longitude)
        {
            //new EphemerisViewController().GetEphemeris(date, latitude, longitude);
        }

        public void GetEphemeris1(Int64 nanoSecsSince1970, double latitude, double longitude)
        {
            // This method does not throw.  However, it will not be executed
            // if any method in EphemerisViewController is called.
            MessageBox.Show("Called from c++" + nanoSecsSince1970.ToString());


            try
            {
                //new Maryln().Test();    // this will not throw
                new EphemerisViewController().GetString();   // this will 
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }                              
        }

        public void Test()
        {
            MessageBox.Show("maryln test");
        }

        #endregion
    }

Управляемая DLL, на которую ссылается управляемая DLL-оболочка, содержит UserControl и этот ViewController:

public class EphemerisViewController
    {      
        public EphemerisViewController()
        {          
        }                 

        public void GetString()
        {
            MessageBox.Show("me");
        }

    }

Эта DLL также была зарегистрирована для COM-взаимодействия, но затем я снял эту опцию, поскольку это не помогло.Гуру на борту, мне нужна помощь здесь.Это заняло два рабочих дня, и я сделал 3 шага назад, с которых начал.Все сработало вчера.

Добавление

Собственный клиент использует мою оболочку следующим образом:

void CMfcVSApp1Doc::LaunchEphemrisDialog()
{   
    HRESULT hr;
    CoInitialize(NULL);
    try 
    {               
        ManagedProxy::IMarylnPtr maryln(__uuidof(ManagedProxy::Maryln));    
        LONG64 time = 1309897499216000000;
        hr = maryln->GetEphemeris1(time, 0, 0);
    }
    catch(...)
    {

    }
}

Кроме того, я много раз чистил и перестраивал решение, но неудачи.

1 Ответ

1 голос
/ 06 июля 2011

Не знаю, что здесь могло произойти, но я решил отказаться от этой DLL-оболочки и создать новую с нуля.Я не изменил проект C #, который я упаковывал, просто чтобы посмотреть, какой из этих двух проектов вызвал проблему.Один только этот акт позволил мне отладить каждый из API-интерфейсов, представленных в проекте C #.Используя методику отладки проекта, предложенную Хансом П, я смог дополнительно отладить свою DLL-оболочку.Я вздохнул с облегчением, просто увидев управляемое исключение.Определенно, это шаг вперед.

Оказалось, что каждый вызов обернутого API в EphemerisViewController вызывал исключение управления, которое не может быть найдено (обнаруженный манифест сборки не совпадает с загруженной сборкой .... бла..blah.).Мы все знаем, что является причиной этого.

После очистки ссылок на сборки, тем самым устраняя вышеупомянутую ошибку, я мог бы затем снова вызвать свою управляемую DLL.День потрачен впустую с одной стороны.С другой стороны, многому научился.Почему оригинальная обертка перестала работать, я не понимаю, но я рад это отпустить.это была комбинация повреждения пространства имен и проблем с загрузкой DLL, но кто знает.

Я готовился отказаться от COM-взаимодействия и погрузиться в MFC, но, блин, я рад, что придерживался своего оружия.По сравнению с C #, разработка C ++ отстой, насколько я понимаю.Например, просто возможность поймать общее исключение в C # применительно к эквиваленту catch (...), который мы имеем для C ++, является серьезным преимуществом.Весь сумасшедший синтаксис c ++ и подпрограммы царапания головы для выполнения простых преобразований заставляют меня вращатьсяНе говоря уже об Intellisense, о IntelliSense.С истекшей лицензией Virtual Assist, которая напоминает мне каждый день, что она бездействует, и ограниченным корпоративным бюджетом, я некоторое время буду придерживаться C #, возможно, с мыслями о том, чтобы исследовать библиотеки C ++, такие как Boost, когда все это будет сделано, на всякий случай.Но, мальчик, я рад вернуться в .NET.

Урок, который я усвоил для меня, заключается в следующем: при взаимодействии с COM вы должны уделять пристальное внимание деталям!

...