COM Interop在调用托管DLL时抛出EEMessageException

时间:2011-07-05 22:07:36

标签: com interop

真正的COM互操作证明了我。我有一个包含WPF窗口的简单托管DLL。我有一个简单的ViewController类,它最终会启动这个窗口但是现在有一个空的方法什么都不做。

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

MfcVSApp1.exe中0x7c812aeb(kernel32.dll)的第一次机会异常:Microsoft C ++异常:内存位置0x0012cb30处的EEMessageException ..

显然昨天一切顺利。现在有些代码:

我的包装器实体:

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

加成

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

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 个答案:

答案 0 :(得分:1)

不知道这里发生了什么,但我决定放弃这个包装DLL并从头开始创建一个新的。我没有更改我正在包装的C#项目,只是为了看看这两个项目中的哪一个导致了问题。这个行为在某种程度上允许我调试被包装的C#项目中公开的每个API。使用Hans P建议的项目调试技术,我能够进一步调试我的包装器DLL。我松了一口气,只是能够看到一个托管异常。绝对是前进的一步。

事实证明,每次调用EphemerisViewController中的包装API都会抛出一个无法找到依赖项的管理异常(找到程序集清单与加载的程序集不匹配...... blah..blah。)。我们都知道是什么导致了这一点。

清理程序集引用后,消除了上述错误,然后我可以再次调用我的托管DLL。一天浪费了一天。另一方面,我学到了很多东西。为什么原始封装器停止工作是我无法理解的,但我很高兴让它去。它已经是命名空间损坏和DLL加载问题的组合,但谁知道。

我正准备放弃COM互操作并潜入MFC,但男孩,我很高兴我坚持使用枪支。与C#相比,就我而言,C ++开发很糟糕。例如,只是能够捕获C#中的一般异常,因为我们对C ++的catch(...)等价物是一个重要的好处。所有疯狂的c ++语法和用于执行简单转换的头部例程让我头晕目眩。更不用说Intellisense,哦intellisense。有了过期的虚拟助手许可证,每天都会让我想起它处于休眠状态,并且公司预算紧张,我会坚持使用C#一段时间,也许考虑调查像Boost这样的C ++库,以防万一。但是男孩,我很高兴回到.NET。

这里为我学到的经验是:与COM互操作,你必须密切关注细节!