我正在构建基于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,我在开发机器上为我做的?
你是否在调试模式下编译?你可能会遇到VS调试模式redist dll的DLL问题,它只能在装有VS的PC上安装。尝试释放... –
谢谢J.N.我已经在发布模式下构建了解决方案。 – Reg
尽管我仍然不能100%确定它为什么在开发框中工作,但由于这是一个从Visual Studio 2005/2008构建的开放源代码解决方案,我将其导入到VS 2010中,我试图将原始ActiveX控件文件复制到应用程序的目录覆盖用解决方案构建的VS2010,重新注册它,现在它可以工作。我认为这与VS 2010构建它的Windows SDK(7.1)或更高版本的MSBuild针对.NET 4有关,我知道.NET 4如何处理与COM的互操作。 – Reg