调用托管代码的非托管代码在开发机器上工作,而不是在部署机器上工作

Unmanaged code calling managed code works on dev machine, not on deployed machine

本文关键字:工作 机器 部署 托管代码 开发 调用 非托管代码      更新时间:2023-10-16

我正在构建一个基于VideoRendererElement项目(http://videorendererelement.codeplex.com/)的网络摄像头应用程序,它使用DirectShowLib和与非托管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;
}

根据我的日志文件MediaBridge::MediaBridgeManager::AddMediaGraphInfo()正在. net端被调用,但回调从未达到,因为_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()时,Delegate哈希计数(_delegateHash.Count)现在是0。

我应该做些什么来识别目标机器上的dll到com/c++, VS在我的开发机器上为我做的?

如何在目标机器上部署和运行应用程序。您是简单地复制可执行文件还是创建一个安装程序?如果您正在创建安装程序,您是否在RegSvr32中注册了AX文件?

COM组件的问题是它们必须在相关盒子上的注册表中注册。在你的盒子上,你已经注册了这个,所以你不会有问题。然而,在目标框上,它可能被注册,也可能不被注册,这取决于用户的突发奇想。如果您已经设置了安装程序,则必须"安装"AX文件,以便在注册表中注册它。否则,无论您如何部署AX文件,都无法找到AX文件。这是COM的缺点之一。