调用托管DLL时COM互操作引发EEMessageException

调用托管DLL时COM互操作引发EEMessageException,com,interop,Com,Interop,COM互操作对我来说是一场噩梦。我有一个简单的托管DLL,其中包含一个WPF窗口。我有一个简单的ViewController类,它最终将启动这个窗口,但现在有一个空方法,它什么也不做 我已经为这个托管DLL创建了一个托管包装器,它公开了一个为COM互操作注册的接口。我可以调用我的托管包装器OK。我可以在托管包装DLL的入口点显示MessageBox。但是,如果我尝试调用正在包装的DLL中此ViewController类上的任何方法,我会得到以下结果: MFCVSAPP1.EXE中0x7C812

COM互操作对我来说是一场噩梦。我有一个简单的托管DLL,其中包含一个WPF窗口。我有一个简单的ViewController类,它最终将启动这个窗口,但现在有一个空方法,它什么也不做

我已经为这个托管DLL创建了一个托管包装器,它公开了一个为COM互操作注册的接口。我可以调用我的托管包装器OK。我可以在托管包装DLL的入口点显示MessageBox。但是,如果我尝试调用正在包装的DLL中此ViewController类上的任何方法,我会得到以下结果:

MFCVSAPP1.EXE中0x7C812AEB(Kelnel.dll)中的第一个机会例外:微软C++异常:内存位置0x00 12Cb30… 显然,昨天一切都很顺利。下面是一些代码:

我的包装器实体:

[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也被注册为COM互操作,但后来我取消了该选项,因为它没有帮助。船上的大师们,我需要帮助。这已经消耗了两个工作日,我从开始的地方后退了三步。昨天一切顺利

添加

本机客户端正在使用我的包装器,如下所示:

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

    }
}

另外,我已经清理和重建了很多次解决方案,但运气不好。

不知道这里发生了什么,但我决定放弃这个包装器DLL,从头开始创建一个新的。我没有改变正在包装的C#项目,只是为了看看这两个项目中的哪一个导致了问题。这一行为本身就让我能够调试正在包装的C#项目中公开的每个API。使用Hans P建议的项目调试技术,我能够进一步调试我的包装器DLL。看到一个管理异常,我松了一口气。这无疑是向前迈出的一步

事实证明,对EphersViewController中包装的API的每次调用都会引发一个管理异常,该异常导致找不到依赖项(定位的程序集清单与加载的程序集不匹配…,等等)。我们都知道这是什么原因

清理程序集引用从而消除上述错误后,我可以再次调用托管DLL。一方面浪费了一天。另一方面,我学到了很多。为什么原来的包装停止工作是超出我的理解,但我很高兴让它去。这是名称空间损坏和DLL加载问题的组合,但谁知道呢

我正准备放弃COM互操作,潜入MFC,但天哪,我很高兴我坚持自己的立场。和C语言相比,C++的开发就我而言而言是个难题。例如,只需捕获C中的一个一般异常,就等于C++中的catch(…)等价物是一个严重的好处。所有疯狂的C++语法和头部抓取程序来执行简单的转换,让我头晕目眩。更不用说智能感知,哦智能感知。有了过期的虚拟助理许可证,每天提醒我它是休眠的,而且公司的预算很紧,我会坚持C++一段时间,也许会考虑在所有的情况下,如Boost那样研究C++库,以防万一。但是,男孩,我很高兴回到.NET

这里给我的教训是:使用COM互操作,您必须密切关注细节

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

    }
}