1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
2 
3 using System.Collections.Generic;
4 using System.Diagnostics.CodeAnalysis;
5 using System.IO;
6 using System.Linq;
7 using System.Reflection;
8 
9 namespace System.Web.WebPages.Deployment
10 {
11     internal static class AppDomainHelper
12     {
GetBinAssemblyReferences(string appPath, string configPath)13         public static IDictionary<string, IEnumerable<string>> GetBinAssemblyReferences(string appPath, string configPath)
14         {
15             string binDirectory = Path.Combine(appPath, "bin");
16             if (!Directory.Exists(binDirectory))
17             {
18                 return null;
19             }
20 
21             AppDomain appDomain = null;
22             try
23             {
24                 var appDomainSetup = new AppDomainSetup
25                 {
26                     ApplicationBase = appPath,
27                     ConfigurationFile = configPath,
28                     PrivateBinPath = binDirectory,
29                 };
30                 appDomain = AppDomain.CreateDomain(typeof(AppDomainHelper).Namespace, AppDomain.CurrentDomain.Evidence, appDomainSetup);
31 
32                 var type = typeof(RemoteAssemblyLoader);
33                 var instance = (RemoteAssemblyLoader)appDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
34 
35                 return Directory.EnumerateFiles(binDirectory, "*.dll")
36                     .ToDictionary(assemblyPath => assemblyPath,
37                                   assemblyPath => instance.GetReferences(assemblyPath));
38             }
39             finally
40             {
41                 if (appDomain != null)
42                 {
43                     AppDomain.Unload(appDomain);
44                 }
45             }
46         }
47 
48         private sealed class RemoteAssemblyLoader : MarshalByRefObject
49         {
50             [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Method needs to be instance level for cross domain invocation"),
51              SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom",
52                  Justification = "We want to load this specific assembly.")]
GetReferences(string assemblyPath)53             public IEnumerable<string> GetReferences(string assemblyPath)
54             {
55                 var assembly = Assembly.LoadFrom(assemblyPath);
56                 return assembly.GetReferencedAssemblies()
57                     .Select(asmName => Assembly.Load(asmName.FullName).FullName)
58                     .Concat(new[] { assembly.FullName })
59                     .ToArray();
60             }
61         }
62     }
63 }
64