2011-08-09 63 views
0

我正在构建基于VideoRendererElement项目(http://videorendererelement.codeplex.com/)的webcam应用程序,该项目使用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; 
} 

根据我的日志文件媒体桥:: 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 

注意委派哈希计数(_delegateHash.Count)现在怎么是在0时非托管代码调用AddMediaGraphInfo()。

有没有什么我应该做的,以确定目标机器上的VS的COM/C++的DLL,我在开发机器上为我做的?

+1

你是否在调试模式下编译?你可能会遇到VS调试模式redist dll的DLL问题,它只能在装有VS的PC上安装。尝试释放... –

+0

谢谢J.N.我已经在发布模式下构建了解决方案。 – Reg

+0

尽管我仍然不能100%确定它为什么在开发框中工作,但由于这是一个从Visual Studio 2005/2008构建的开放源代码解决方案,我将其导入到VS 2010中,我试图将原始ActiveX控件文件复制到应用程序的目录覆盖用解决方案构建的VS2010,重新注册它,现在它可以工作。我认为这与VS 2010构建它的Windows SDK(7.1)或更高版本的MSBuild针对.NET 4有关,我知道.NET 4如何处理与COM的互操作。 – Reg

回答

0

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

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

+0

谢谢格雷戈里。我创建了一个安装程序,然后将其复制并在我部署它的盒子上手动运行regsvr32。 – Reg

相关问题