我正在編寫可作爲控制檯應用程序或服務運行的C#代碼。當作爲控制檯應用程序運行時,它工作正常。當作爲服務運行時,我收到了一個奇怪的錯誤。服務報告'找不到指定的文件'存在的文件
啓動時,我的服務產生一個線程,此線程搜索目錄中的插件.dll,它們實現了某些服務的功能。我枚舉插件目錄中的文件,然後爲每個找到的文件嘗試加載程序集並確定它是否實現了所需的接口。
這種架構描述如下:http://code.msdn.microsoft.com/windowsdesktop/Creating-a-simple-plugin-b6174b62
我發現我可以列舉所有的插件,但是當我打電話Assembly.GetTypes(),我得到與消息LoaderException:「無法加載文件或程序集「MyProject,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null」或它的某個依賴項,系統找不到指定的文件。
嗯,這是雙層因爲在代碼只是這一次前行,該文件是從到Directory.GetFiles調用枚舉(路徑,「* .dll文件」)。請記住,此代碼在以控制檯應用程序運行時也可以找到。
我的服務以本地系統運行,SYSTEM帳戶對文件具有完全權限,管理員也是如此。根據this page,本地系統的令牌包括NT AUTHORITY \ SYSTEM和BUILTIN \ Administrators SID,所以我不認爲這是文件系統權限問題。
我正在失望。任何人都可以提出一個原因和解決方案?
下面的代碼(它看起來長,但它的很多是記錄):
private void LoadPlugins()
{
lstPlugins = new List<MyDesiredInterface>();
string path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
path += "\\PlugIns";
if (Directory.Exists(path))
{
Log("PlugIns folder exists.", TAG);
string[] dllFileNames = Directory.GetFiles(path, "*.dll");
ICollection<Assembly> assemblies = new List<Assembly>(dllFileNames.Length);
foreach (string dllFile in dllFileNames)
{
AssemblyName an = AssemblyName.GetAssemblyName(dllFile);
Assembly assembly = Assembly.Load(an);
assemblies.Add(assembly);
}
Log("Found " + assemblies.Count + " assemblies.", TAG);
Type pluginType = typeof(MyDesiredInterface);
ICollection<Type> pluginTypes = new List<Type>();
foreach (Assembly assembly in assemblies)
{
if (assembly != null)
{
Log("Evaluating assembly: " + assembly.Location, TAG);
try
{
Type[] types = assembly.GetTypes(); <-- error happens here
foreach (Type type in types)
{
if (type.IsInterface || type.IsAbstract)
{
Log("Assembly does not implement our interface.", TAG);
continue;
}
else
{
if (type.GetInterface(pluginType.FullName) != null)
{
Log("Assembly implements our interface!", TAG);
pluginTypes.Add(type);
}
}
}
}
catch (ReflectionTypeLoadException ex)
{
StringBuilder errMsg = new StringBuilder("An exception occurred tying to load types in an assembly.\r\n");
errMsg.Append("The assembly is: " + assembly.Location + "\r\n");
errMsg.Append("Exceptions are:\r\n");
foreach (Exception e in ex.LoaderExceptions)
{
errMsg.Append(e.Message + "\r\n");
}
Log(errMsg.ToString(), TAG);
}
}
}
foreach (Type type in pluginTypes)
{
MyDesiredInterface plugin = (MyDesiredInterface)Activator.CreateInstance(type);
this.Log("Loading plugin: " + plugin.CommandName(), TAG);
plugin.Register(this);
lstPlugins.Add(plugin);
}
this.Log("Total plugins loaded: " + lstPlugins.Count, TAG);
}
else
{
Log("PlugIns folder not found.", TAG);
}
}
這裏的日誌文件:
3/12/2014 9:53:46 AM chatInterface LoadPlugIns()
3/12/2014 9:53:46 AM chatInterface PlugIns folder exists.
3/12/2014 9:53:46 AM chatInterface Found 13 assemblies.
3/12/2014 9:53:46 AM chatInterface Evaluating assembly: C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\PlugIn1.dll
3/12/2014 9:53:46 AM chatInterface An exception occurred tying to load types in an assembly.
The assembly is: C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\PlugIn1.dll
Exceptions are:
Could not load file or assembly 'MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
3/12/2014 9:53:46 AM chatInterface Evaluating assembly: C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\PlugIn2.dll
3/12/2014 9:53:46 AM chatInterface An exception occurred tying to load types in an assembly.
The assembly is: C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\PlugIn2.dll
Exceptions are:
Could not load file or assembly 'MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
有人建議我用集綁定日誌查看器(fuslogvw.exe)記錄失敗。下面是該日誌顯示:
*** Assembly Binder Log Entry (3/13/2014 @ 9:50:30 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
Running under executable C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\MyProjectService.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: Where-ref bind. Location = C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\MyPlugIn.dll
LOG: Appbase = file:///C:/Users/MyUsername/Documents/Visual Studio 2010/Projects/MyProject/MyProjectService/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Attempting download of new URL file:///C:/Users/MyUsername/Documents/Visual Studio 2010/Projects/MyProject/MyProjectService/bin/Debug/PlugIns/MyPlugIn.dll.
LOG: Assembly download was successful. Attempting setup of file: C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\MyPlugIn.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: MyPlugIn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Re-apply policy for where-ref bind.
LOG: Binding succeeds. Returns assembly from C:\Users\MyUsername\Documents\Visual Studio 2010\Projects\MyProject\MyProjectService\bin\Debug\PlugIns\MyPlugIn.dll.
LOG: Assembly is loaded in LoadFrom load context.
在這個測試中來看,我使用Assembly.LoadFrom()而不是Assembly.Load(),但在這兩種情況下,裝配負荷。這個日誌顯示它在LoadFrom加載上下文中,我有其他的運行,顯示它在Load load上下文與另一個調用。在任何情況下,加載成功,但嘗試枚舉GetTypes將失敗,並顯示「系統找不到指定的文件」。
任何幫助,將不勝感激!
感謝,CodeMad。日誌查看器沒有顯示任何故障。 –