我正在编写可以作为控制台应用程序或服务运行的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(path,“* .dll”)的调用中枚举的。请记住,此代码在作为控制台应用程序运行时也可以找到。
我的服务作为本地系统运行,SYSTEM帐户对文件具有完全权限,管理员也是如此。根据{{3}},本地系统的令牌包括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失败,并显示“系统无法找到指定的文件。”
任何帮助将不胜感激!
答案 0 :(得分:0)
请检查您是否引用了一个程序集,而该程序集又引用旧版本。删除,重建和重新引用可能会有所帮助。
&#34; FuseLogVw&#34;有助于找到谁正在加载程序集,定义日志路径并运行解决方案,然后检查FuseLogVw中的第一行
答案 1 :(得分:0)
来自http://msdn.microsoft.com/en-us/library/ky3942xh(v=vs.110).aspx:
“如果assemblyString指定完整的程序集名称,则抛出FileLoadException,并且与简单名称匹配的第一个程序集具有不同的版本,区域性或公钥标记。加载程序不会继续探测与简单名称匹配的其他程序集。“
那么组装的多个版本是否存在?