我正在使用Se7enSoft的MozNet插件.这是FireFox 3.6的WebBrowser控件.它使用XulRunner.
我要做的第一件事是执行Initialize(...)方法.
var binDirectory = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
var xulRuntimeDirectory = Path.Combine(binDirectory, "xul");
Se7enSoft.MozNet.Xpcom.Initialize(xulRuntimeDirectory, null);
Run Code Online (Sandbox Code Playgroud)
我必须将它传递给我们安装XulRunner的目录.此插件的Initialize方法在内部使用以下DLLImport.
[DllImport("xpcom", CharSet = CharSet.Ansi,
EntryPoint = "NS_CStringContainerFinish",
CallingConvention = CallingConvention.Cdecl)]
internal static extern int Moz_CStringContainerFinish(ACString container);
Run Code Online (Sandbox Code Playgroud)
XulRunner的xpcom.dll中的NS_CStringContainerFinish方法是必需的.
就在第一次调用此方法之前,MozNet插件会临时更改PATH环境变量.
Environment.SetEnvironmentVariable("path",
Environment.GetEnvironmentVariable("path") + ";" +
binDirectory, EnvironmentVariableTarget.Process);
Run Code Online (Sandbox Code Playgroud)
XulRunner的位置暂时添加到PATH环境变量中,以确保它可以解析xpcom.dll(和其他).
但它仍然无法找到它.我收到以下异常.
Unable to load DLL 'xpcom': Cannot find method.
(Exception from HRESULT: 0x8007007F)
at Se7enSoft.MozNet.Native.MozNativeMethods.Moz_CStringContainerInit(
ACString container)
at Se7enSoft.MozNet.Xpcom.XpCom_Init()
at Se7enSoft.MozNet.Xpcom.Initialize(String mozPath, String profPath)
Run Code Online (Sandbox Code Playgroud)
此问题仅发生在3台PC上(Windows 2000和XP).适用于数百个其他人.
如果我调试并跳过Environment.SetEnvironmentVariable(...)方法,我可以重现该问题.
SetEnvironmentVariable是否存在任何可能阻止其更改PATH环境变量的问题?
找到了原因.
DLLImport语句使用动态链接库搜索顺序自动定位xpcom.dll文件.
[DllImport("xpcom", CharSet = CharSet.Ansi,
EntryPoint = "NS_CStringContainerFinish",
CallingConvention = CallingConvention.Cdecl)]
internal static extern int Moz_CStringContainerFinish(ACString container);
Run Code Online (Sandbox Code Playgroud)
简而言之,它搜索:
结果发现了3台有问题的电脑,有不同的xpcom.dll.这是首先发现的,而BOOM ......例外情况很丰富.
PATH环境变量中列出的目录(UNC路径)指向一对DLL,它们是xpcom.dll的依赖项,即:
我们通过仅为我们的流程更改PATH变量来修复它.通过在PATH环境变量的开头添加路径,确保我们的路径在任何其他路径之前被搜索.
var pluginDirectory = @"C:\....\xulrunner\");
var path = Environment.GetEnvironmentVariable("path");
Environment.SetEnvironmentVariable(
"path",
pluginDirectory + ";" + path,
EnvironmentVariableTarget.Process);
Run Code Online (Sandbox Code Playgroud)