运行COM DLL引发的异常 [英] Exceptions raised running COM DLL

查看:131
本文介绍了运行COM DLL引发的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我会再试一次....:)

I will try again .... :)

如果我有此代码:

void CTestDlg::OnBnClickedButtonTest()
{
    MSAToolsLibrary::IMSAToolsLibraryInterfacePtr p;
    HRESULT hr;
    hr = p.CreateInstance(__uuidof(MSAToolsLibrary::MSAToolsLibraryClass));
    if (FAILED(hr))
    {
        __int64 i;
        p->SetPathXML(m_strPublisherDatabaseXML.AllocSysString(), &i);
        p->ReadPublisherData(&i);
    }
}

然后运行它,得到一个无声的异常:

And I run it, I get this silent exception:

Exception thrown at 0x00007FFCD00B7788 (KernelBase.dll) in Test.exe: 0x04242420 (parameters: 0x0000000031415927, 0x00007FFCBF6C0000, 0x00000099D88FBDC0).

但是,如果我使用包装器(标题:

But, if I use a wrapper (header:

#pragma once

#import "D:\\My Programs\\2017\\MSAToolsLibrary\\MSAToolsLibrary\\bin\\Release\\MSAToolsLibrary.tlb" raw_interfaces_only named_guids

class CMSATools
{
public:
    CMSATools();
    ~CMSATools();
    void SetPathXML(CString strPath);
    void OpenPublisherDatabase();

private:
    MSAToolsLibrary::IMSAToolsLibraryInterfacePtr m_pInterface;
}

类别:

#include "stdafx.h"
#include "MSATools.h"


CMSATools::CMSATools()
{
    m_pInterface = NULL;

    HRESULT hr;
    hr = m_pInterface.CreateInstance(__uuidof(MSAToolsLibrary::MSAToolsLibraryClass));
    if (FAILED(hr))
    {
        // TODO: Throw exception ?
    }
}


CMSATools::~CMSATools()
{
}

void CMSATools::SetPathXML(CString strPath)
{
    if (m_pInterface != NULL)
    {
        CComBSTR    bstrText = strPath.AllocSysString();
        __int64     iResult;

        m_pInterface->SetPathXML(bstrText, &iResult);
    }
}

void CMSATools::OpenPublisherDatabase()
{
    __int64 iResult;

    if (m_pInterface != NULL)
        m_pInterface->ReadPublisherData(&iResult);
}

并在MFC中使用它:

void CTestDlg::OnBnClickedButtonGetNames()
{
    CMSATools toolsMSA;

    UpdateData(TRUE);

    toolsMSA.SetPathXML(m_strPublisherDatabaseXML);
    toolsMSA.OpenPublisherDatabase();
}

它在做同样的事情,但我得到了这些无声的例外:

It is doing the same thing, yet I get these silent exceptions:

Exception thrown at 0x00007FFCD00B7788 (KernelBase.dll) in Test.exe: 0x04242420 (parameters: 0x0000000031415927, 0x00007FFCBF6C0000, 0x00000090F277C040).
Exception thrown at 0x00007FFCD00B7788 in Test.exe: Microsoft C++ exception: EEFileLoadException at memory location 0x00000090F277BB80.
Exception thrown at 0x00007FFCD00B7788 in Test.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFCD00B7788 in Test.exe: Microsoft C++ exception: EEFileLoadException at memory location 0x00000090F277BB80.
Exception thrown at 0x00007FFCD00B7788 in Test.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFCD00B7788 in Test.exe: Microsoft C++ exception: EEFileLoadException at memory location 0x00000090F277BB80.
Exception thrown at 0x00007FFCD00B7788 (KernelBase.dll) in Test.exe: 0xE0434352 (parameters: 0xFFFFFFFF80070002, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00007FFCBF6C0000).

为什么一种方法可以工作而另一种会导致异常(我似乎无法检测到) ?

Why should one way work and the other cause exceptions (that I can't seem to even detect)?

请稍等-我现在看到了我的愚蠢错误!片刻....

Please hold off - I see my stupid error now! One moment ....

void CTestDlg::OnBnClickedButtonTest()
{
    MSAToolsLibrary::IMSAToolsLibraryInterfacePtr p;
    HRESULT hr;
    hr = p.CreateInstance(__uuidof(MSAToolsLibrary::MSAToolsLibraryClass));
    if (SUCCEEDED(hr))
    {
        __int64 i;
        p->SetPathXML(m_strPublisherDatabaseXML.AllocSysString(), &i);
        p->ReadPublisherData(&i);
    }
}

我现在更正了测试用例,它们都具有提出了同样的例外。这是似乎在DLL中引起问题的方法:

I corrected the test case now and they both have the same exceptions raised. This is the method that seems to cause the problem in the DLL:

public void ReadPublisherData(out Int64 iResult)
{
    iResult = MakeResult(true);

    try
    {
        _PublisherData.Publishers.Clear(); // Reset

        XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
        using (StreamReader reader = new StreamReader(_strPathXML))
        {
            _PublisherData = (PublisherData)x.Deserialize(reader);
            _PublisherData.BuildPublisherDictionaryFromList();
            iResult = _PublisherData.PublisherDictionary.Count;
        }
    }
    catch
    {
        iResult = MakeResult(false);
    }
 }

据我所知,这不会导致任何例外。似乎...

As far as I am aware it doesn't cause any exceptions. It seems ...

推荐答案

您唯一明显的问题是您没有问题。您使用的COM服务器是用托管语言编写的。非常简单,仅使用属性即可完成。考虑到您已经问过的问题,可能是C#。关键是这些异常是 silent ,它们被抛出并捕获在托管代码中。

The only obvious problem you have is that you don't have a problem. The COM server you are using was written in a managed language. Pretty common, dead-simple to do with just an attribute. Probably C#, given that you've asked questions about it. The point is that these exceptions are silent, they are thrown and caught inside the managed code.

跨COM边界传递异常是非法的, CLR为您提供坚决的保证,以确保这种情况永远不会发生。如果未捕获到托管异常,则它将变为指示失败的HRESULT错误代码。由于您使用的是#import生成的包装程序,因此您将永远不会真正看到这些错误代码,因此包装程序会抛出 _com_error 将它们转换为C ++异常。您不会尝试捕获它们,因此,如果发生这种情况,您的程序将崩溃并在Terminate()上死亡,不可能不注意到这一点。

Passing exceptions across a COM boundary is illegal, the CLR gives you a rock-hard guarantee that this will never happen. If a managed exception is not caught then it gets turned into an HRESULT error code that indicates a failure. Since you are using the wrappers generated by #import, you'll never actually see these error codes, the wrapper turns them back into a C++ exception by throwing a _com_error. You make no attempt at catching them so if it happens then your program will keel over and die on terminate(), impossible to not notice that.

Fwiw,0x04242420是一个非致命异常代码,是调试器的实现细节。 在此处记录

Fwiw, 0x04242420 is a non-fatal exception code and is an implementation detail of the debugger. Documented here.

EEFileLoadException是内部使用的非托管异常CLR,并在要求Fusion加载程序集且找不到它时触发。变成托管的FileLoadException。鉴于托管的COM服务器通常在查找依赖程序集时遇到问题,因此您可能会稍微担心它。但这通常在托管代码使用XML序列化时发生,我们知道您正在使用它。使用异常进行流控制不是很好,但是性能也是一项功能。关于它的更多信息在这篇文章中

The EEFileLoadException is an unmanaged exception used inside the CLR and triggered when Fusion is asked to load assembly and it can't find it. Turns into a managed FileLoadException. You might be slightly more concerned about it given that managed COM servers often have a problem finding dependent assemblies. But this commonly happens when the managed code uses XML serialization, we know you are using it. Using exceptions for flow-control isn't very nice but performance is a feature as well. More about it in this post.

所以最好不为此担心。如果您不相信自己的COM服务器能够正确实施,则只需调试两者即可。项目>属性>调试,并将调试器类型设置从自动更改为混合。并使用调试> Windows>异常设置,然后选中 CLR异常复选框,以在引发托管异常时强制调试器中断。

So rather best to not fret about it. If you don't trust your COM server to be implemented correctly then simply debug both. Project > Properties > Debugging and change the Debugger Type setting from Auto to Mixed. And use Debug > Windows > Exception Settings and tick the checkbox for CLR Exceptions to force the debugger to break when a managed exception is thrown.

这篇关于运行COM DLL引发的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆