调用托管代码的非托管代码在dev机器上运行,而不是在已部署的机器上运行

时间:2011-08-09 05:26:58

标签: c# c++ interop com-interop directshow

我正在构建一个基于VideoRendererElement项目(http://videorendererelement.codeplex.com/)的网络摄像头应用程序,它使用DirectShowLib和Interop以及非托管的activex组件。我使用的是Visual Studio 2010,但我的目标是.NET 3.5(2.0 clr运行时)。

我已经能够在我的开发机器上构建和运行应用程序,没有任何问题(甚至在Visual Studio之外)。但是,当我在目标计算机上部署应用程序(Windows 7,.NET最新版本,C ++可再发行版本为最新版本)时,应用程序崩溃了。我设置了一个额外的方法来将正在运行的应用程序记录到目标机器上的文本文件中,跟踪一个关键差异,非托管代码调用托管代码中的方法,只丢失先前定义的静态字段。这只发生在目标机器上(我将代码部署到的机器上)。这里有一些代码片段和我记录的内容。令人困惑的是,此错误仅发生在目标计算机上。任何帮助我指向正确方向的人都将不胜感激。

namespace MediaBridge
{
    .....

    public class MediaBridgeManager
    {
        public delegate void NewMediaGraphInfo(MediaBridgeGraphInfo GraphInfo);

        private static readonly Dictionary<string, NewMediaGraphInfo> _delegateHash = new Dictionary<string, NewMediaGraphInfo>();

        ......

        public static void AddMediaGraphInfo(MediaBridgeGraphInfo GraphInfo)
        {
            if (_delegateHash.ContainsKey(GraphInfo.MediaUrl))
            {
                NewMediaGraphInfo callback = _delegateHash[GraphInfo.MediaUrl];
                _delegateHash.Remove(GraphInfo.MediaUrl);

                /* Suppress all errors on the callback */
                try
                {
                    callback(GraphInfo);
                }
                catch {}
            }
        }

        ......

        public static bool RegisterCallback(string MediaUrl, NewMediaGraphInfo Callback)
        {
            bool returnval = true;
            MediaUrl = FormatUrl(MediaUrl);

            if (!_delegateHash.ContainsKey(MediaUrl))
            {
                _delegateHash.Add(MediaUrl, Callback);
            }
            else
            {
                returnval = false;
            }

            return returnval;
        }
    }
}

在应用程序的.NET部分首先调用RegisterCallback()并使用URL和回调函数填充_delegateHash之前。这已在目标计算机上的日志文件中得到验证。

现在是非托管部分:

STDMETHODIMP CMediaBridgeSourceFilter::Load(LPCOLESTR lpwszFileName, const AM_MEDIA_TYPE *pmt)
{
    /* Thread-saftey */
    CAutoLock cAutoLockShared(&m_cSharedState);

    HRESULT phr = S_OK;

    /* Create the output pin for our filter */
    m_pPin = new CMediaBridgeSourceFilterPin(&phr, this);

    /* Create a new class to store information about us/graph in it */
    MediaBridge::MediaBridgeGraphInfo ^ graphInfo = gcnew MediaBridge::MediaBridgeGraphInfo();

    /* Set the media url sent */
    graphInfo->MediaUrl = gcnew System::String(lpwszFileName);

    /* Set the pointer to the filter graph */
    graphInfo->FilterGraph = System::IntPtr(this->GetFilterGraph());

    /* Store the pointer for our instance of the filter */
    graphInfo->SourceFilter = System::IntPtr(this);

    /* Do the callback into our managed code */
    MediaBridge::MediaBridgeManager::AddMediaGraphInfo(graphInfo);

    return phr;
}

根据我的日志文件,在.NET端调用MediaBridge :: MediaBridgeManager :: AddMediaGraphInfo()但是从未到达回调,因为_delegateHash变量现在为空。

以下是我的日志文件在我尝试部署应用程序的目标计算机上的内容:

RegisterCallback(): MediaUrl = dshowmediabridge://d0ffd222-d023-483b-8fc7-4b4035ce3922/ Contains Key: True Delegate Hash count: 1

InitializeDirectShow(): RegisterCallback == true, Url == DShowMediaBridge://d0ffd222-d023-483b-8fc7-4b4035ce3922

AddMediaGraphInfo(): MediaUrl = dshowmediabridge://d0ffd222-d023-483b-8fc7-4b4035ce3922/ FilterGraph: 71122304 Contains Key: False Delegate Hash count: 0

注意当非托管代码调用AddMediaGraphInfo()时,委托哈希计数(_delegateHash.Count)现在为0。

我是否应该做些什么来识别VS在我的开发机器上为我做的目标机器上的COM / C ++的dll?

1 个答案:

答案 0 :(得分:0)

您如何在目标计算机上部署和运行应用程序。您只是复制可执行文件还是创建安装程序?如果要创建安装程序,是否使用RegSvr32注册AX文件?

COM组件的问题是它们必须在相关方框的注册表中注册。在你的盒子上,你已经注册了,所以你不会有问题。但是,在目标框上,可能会或可能不会在用户的心血来潮中注册。如果您已设置安装程序,则必须“安装”AX文件,以便在注册表中注册。如果不是,则无论您如何部署AX文件,都无法找到AX文件。这是COM的缺点之一。