2011-08-09 78 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

相關問題