使用DispEventAdvise时应用程序退出时发生异常

时间:2019-03-09 15:08:40

标签: c# c++ com

我有以下使用Visual Studio 2015编写并使用Windows SDK 7.1的测试设置:

    具有COM属性的
  • C#项目(TestC)。它公开了一个“运行”方法,并调用了“ NotifyEvent”事件
  • C ++ DirectShow过滤器(TestFilter)。它基于TransInPlace示例构建,并承载TestC。
  • C ++控制台应用程序(TestApp)。只需加载TestFilter

在Debug中进行编译并运行测试应用程序时,该功能似乎正常工作,并且事件已按预期方式处理。 问题是,应用程序在退出时崩溃,到目前为止,我仍无法弄清原因。非常感谢任何人的帮助。

现在了解详细信息: 应用程序如下所示:

#include <windows.h>
#include <initguid.h>
#include <atlbase.h>
#include <streams.h>

// {E705C8D3-EE60-4012-9E83-3CFE4A11D1B5}
DEFINE_GUID(CLSID_TestFilter,
    0xe705c8d3, 0xee60, 0x4012, 0x9e, 0x83, 0x3c, 0xfe, 0x4a, 0x11, 0xd1, 0xb5);

void Test()
{
    CComPtr<IBaseFilter> pFilter;
    HRESULT hr = CoCreateInstance(CLSID_TestFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pFilter);
    if (FAILED(hr))
        return;
}

void main()
{
    CoInitialize(NULL);
    Test();
    CoUninitialize();
}

当退出main函数的作用域时会发生崩溃,而我从调用堆栈中什么也没得到。

CS测试定义了以下接口

using System;
using System.Runtime.InteropServices;

namespace TestCs
{
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IFireTestCsEvents
    {
        [DispId(1)]
        void NotifyEvent(string message);
    }

    public delegate void NotifyEventEventHandler(string message);

    public interface ITestCs : IDisposable
    {
        event NotifyEventEventHandler NotifyEvent;

        bool Run(string fileName);

        void Close();
    }
}

这是接口的实现

using System.Runtime.InteropServices;

namespace TestCs
{
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IFireTestCsEvents))]
    public class TestCsImp : ITestCs
    {
        public event NotifyEventEventHandler NotifyEvent;

        public TestCsImp()
        {
        }

        public bool Run(string fileName)
        {
            NotifyEvent?.Invoke(fileName);
            return true;
        }

        public void Close()
        {
        }

        public void Dispose()
        {
            Close();
        }
    }
}

对于TestFilter,它基于TransInPlace类,并将TestCsWrapper对象添加到宿主TestC 这是头文件

#pragma once

#import "TestCs.tlb"
using namespace TestCs;

class TestCsWrapper :
    public IDispEventSimpleImpl<1, TestCsWrapper, &__uuidof(IFireTestCsEvents)>
{
public:
    BEGIN_SINK_MAP(TestCsWrapper)
        SINK_ENTRY_INFO(1, __uuidof(IFireTestCsEvents), 0x1, HandleEvent, &NotifyEvent)
    END_SINK_MAP()

    void __stdcall HandleEvent(BSTR message);
public:
    TestCsWrapper();
    virtual ~TestCsWrapper();

    bool Open();
    void Close();

    bool IsValid();

    bool Load(const wchar_t *fileName);
private:
    ITestCsPtr m_pTestCs;

    static _ATL_FUNC_INFO NotifyEvent;
};

这是实现

#include "Pch.h"
#include "TestCsWrapper.h"

_ATL_FUNC_INFO TestCsWrapper::NotifyEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };

#define CREATE_CRASH

void __stdcall TestCsWrapper::HandleEvent(BSTR message)
{
    ::SysFreeString(message);
}

TestCsWrapper::TestCsWrapper()
{
}

TestCsWrapper::~TestCsWrapper()
{
    Close();
}

bool TestCsWrapper::Open()
{
    m_pTestCs = ITestCsPtr(__uuidof(TestCsImp));
    if(!IsValid())
        return false;

#ifdef CREATE_CRASH
    DispEventAdvise(m_pTestCs);
#endif
    return true;
}

void TestCsWrapper::Close()
{
    if(IsValid())
    {
#ifdef CREATE_CRASH
        DispEventUnadvise(m_pTestCs);
#endif
        m_pTestCs->Close();
        m_pTestCs->Release();
        m_pTestCs.Detach();
    }
}

bool TestCsWrapper::IsValid()
{
    return (m_pTestCs != NULL);
}


bool TestCsWrapper::Load(const wchar_t *fileName)
{
    if(!IsValid())
        return false;

    BSTR bstr = ::SysAllocString(fileName);
    VARIANT_BOOL success = m_pTestCs->Run(bstr);
    ::SysFreeString(bstr);
    return success == VARIANT_TRUE;
}

当我禁用DispEventAdvise代码时,应用程序将退出,没有任何异常。

在过滤器的CreateInstance调用中,我添加了以下代码

bool TestFilter::Open()
{
    if (!m_testCs.Open())
        return false;

    m_testCs.Load(L"some messsage");
    return true;
}

可以使用完整的Visual Studio解决方案代码进行演示,并且可以在需要时提供

希望找出我做错了什么。 谢谢

0 个答案:

没有答案