对于存在的文件,服务报告'找不到指定的文件'

时间:2014-03-12 15:21:02

标签: c# windows-services

我正在编写可以作为控制台应用程序或服务运行的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失败,并显示“系统无法找到指定的文件。”

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:0)

请检查您是否引用了一个程序集,而该程序集又引用旧版本。删除,重建和重新引用可能会有所帮助。

&#34; FuseLogVw&#34;有助于找到谁正在加载程序集,定义日志路径并运行解决方案,然后检查FuseLogVw中的第一行

答案 1 :(得分:0)

来自http://msdn.microsoft.com/en-us/library/ky3942xh(v=vs.110).aspx

“如果assemblyString指定完整的程序集名称,则抛出FileLoadException,并且与简单名称匹配的第一个程序集具有不同的版本,区域性或公钥标记。加载程序不会继续探测与简单名称匹配的其他程序集。“

那么组装的多个版本是否存在?