1

按照以下知识库文章的示例,我们实现了 AssemblyResolve 事件,以便将 .Net 指向正确的文件夹以从中加载程序集:http: //support.microsoft.com/kb/837908

这是我们当前的实现:

public static class AssemblyLoader
{
    /// <summary>
    /// A custom AssemblyResolver that will search for missing assemblies in the root and subfolders of the executing assembly
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <returns></returns>
    public static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        string assemblyPath = string.Empty;
        string assemblyFileName = string.Empty;

        try
        {
            // This handler is called only when the common language runtime tries to bind to the assembly and fails.
            string rootProbingPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            

            // Loop through the referenced assembly names.
            assemblyFileName = args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll";

            // Search for the filename in the root and subfolders of the rootProbingPath
            string[] matchingAssemblies = Directory.GetFiles(rootProbingPath, assemblyFileName, SearchOption.AllDirectories);

            // If a match is found, awesomeness was achieved!
            if (matchingAssemblies.Length > 0)
                assemblyPath = matchingAssemblies[0];

            // Throw a clear exception when the assembly could not be found.
            if (string.IsNullOrEmpty(assemblyPath))
                throw new FileNotFoundException(string.Format("AssemblyLoader: Could not find assembly '{0}' in '{1}' or its subfolders.", assemblyFileName, rootProbingPath));

            Console.WriteLine(string.Format("[" + DateTime.Now.ToString() + "] AssemblyLoader: Assembly '{0}' found at '{1}'", assemblyFileName, assemblyPath));

            // Load the assembly from the specified path.
            return Assembly.LoadFrom(assemblyPath, AppDomain.CurrentDomain.Evidence);
        }
        catch (Exception ex)
        {
            throw new Exception(string.Format("[" + DateTime.Now.ToString() + "] The assemblyloader could not load the assembly '{0}' from path '{1}': " + ex.Message, assemblyFileName, assemblyPath), ex);
        }
    }
}

我们在所有批处理程序中都使用它,这些程序通常并行运行并且使用大部分相同的程序集。

批次会定期崩溃,留下以下痕迹:

[26/04/2013 12:35:01] AssemblyLoader:在“C:\COMPANY_Batch\MDS\Executables\MDS\FACADE\COMPANY.DistributieOrderFacade.dll”中找到程序集“COMPANY.DistributieOrderFacade.dll”

[26/04/2013 12:35:01] AssemblyLoader:程序集“COMPANY.DOCUMENTCENTERDOCS.dll”位于“C:\COMPANY_Batch\MDS\Executables\MDS\CLIENT\COMPANY.DOCUMENTCENTERDOCS.dll”

26/04/2013 12:35:01:在队列中创建 COMPANYDocument...:\rug.adroot\dfsroot\mds\Data\queue_new\ 26/04/2013 12:35:01

无法加载文件或程序集 'COMPANY.DistributeOrderBRDA,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' 或其依赖项之一。一般异常(HRESULT 异常:0x80131500)

错误中的程序集确实位于 AssemblyLoader 搜索的文件夹之一中。如果我再次运行该程序,它确实会成功。

我试图通过在两个控制台应用程序中使用此程序集加载器并同时访问相同的 dll 来查看 dll 是否被锁定,但这似乎不是问题。

我还应该提到,这只是其中一批的日志。还有其他的,很少有相同的程序集没有被加载。

我不知道接下来从哪里开始寻找解决方案。

4

1 回答 1

0

这是由于在每个批次运行之前更新了 dll 的更新脚本。当两个批次同时运行并且有一个需要更新的 dll 时,导致问题的 dll 上发生了锁定。

我们已经删除了这个脚本一周了,还没有发现任何问题。所以我们的结论是这就是问题所在。

于 2013-05-21T07:34:21.713 回答