Fixes: U4-3290 PackageBinaryInspector returns error during install

This commit is contained in:
Shannon
2013-11-01 17:10:01 +11:00
parent b2c5d7270e
commit 083ca23d93

View File

@@ -62,28 +62,39 @@ namespace Umbraco.Core.Packaging
var files = Directory.GetFiles(dllPath, "*.dll");
var dllsWithReference = new List<string>();
var errors = new List<string>();
var assembliesWithErrors = new List<string>();
var assembliesWithErrors = new List<Assembly>();
//we need this handler to resolve assembly dependencies below
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) =>
{
var a = Assembly.ReflectionOnlyLoadFrom(GetAssemblyPath(Assembly.ReflectionOnlyLoad(e.Name)));
var a = Assembly.ReflectionOnlyLoad(e.Name);
if (a == null) throw new TypeLoadException("Could not load assembly " + e.Name);
return a;
};
//First load each dll file into the context
foreach (var f in files) Assembly.ReflectionOnlyLoadFrom(f);
//Then load each referenced assembly into the context
foreach (var f in files)
//First load each dll file into the context
var loaded = files.Select(Assembly.ReflectionOnlyLoadFrom).ToList();
//load each of the LoadFrom assemblies into the Load context too
foreach (var a in loaded)
{
var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f);
foreach (var assemblyName in reflectedAssembly.GetReferencedAssemblies())
Assembly.ReflectionOnlyLoad(a.FullName);
}
//get the list of assembly names to compare below
var loadedNames = loaded.Select(x => x.GetName().Name).ToArray();
//Then load each referenced assembly into the context
foreach (var a in loaded)
{
//don't load any referenced assemblies that are already found in the loaded array - this is based on name
// regardless of version. We'll assume that if the assembly found in the folder matches the assembly name
// being looked for, that is the version the user has shipped their package with and therefore it 'must' be correct
foreach (var assemblyName in a.GetReferencedAssemblies().Where(ass => loadedNames.Contains(ass.Name) == false))
{
try
{
Assembly.ReflectionOnlyLoadFrom(GetAssemblyPath(Assembly.ReflectionOnlyLoad(assemblyName.FullName)));
Assembly.ReflectionOnlyLoad(assemblyName.FullName);
}
catch (FileNotFoundException)
{
@@ -92,7 +103,7 @@ namespace Umbraco.Core.Packaging
string.Concat("This package references the assembly '",
assemblyName.Name,
"' which was not found"));
assembliesWithErrors.Add(f);
assembliesWithErrors.Add(a);
}
catch (Exception ex)
{
@@ -101,7 +112,7 @@ namespace Umbraco.Core.Packaging
string.Concat("This package could not be verified for compatibility. An error occurred while loading a referenced assembly '",
assemblyName.Name,
"' see error log for full details."));
assembliesWithErrors.Add(f);
assembliesWithErrors.Add(a);
LogHelper.Error<PackageBinaryInspector>("An error occurred scanning package assemblies", ex);
}
}
@@ -110,34 +121,62 @@ namespace Umbraco.Core.Packaging
var contractType = GetLoadFromContractType<T>();
//now that we have all referenced types into the context we can look up stuff
foreach (var f in files.Except(assembliesWithErrors))
foreach (var a in loaded.Except(assembliesWithErrors))
{
//now we need to see if they contain any type 'T'
var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f);
var found = reflectedAssembly.GetExportedTypes()
.Where(contractType.IsAssignableFrom);
if (found.Any())
var reflectedAssembly = a;
try
{
dllsWithReference.Add(reflectedAssembly.FullName);
var found = reflectedAssembly.GetExportedTypes()
.Where(contractType.IsAssignableFrom);
if (found.Any())
{
dllsWithReference.Add(reflectedAssembly.FullName);
}
}
catch (Exception ex)
{
//This is a hack that nobody can seem to get around, I've read everything and it seems that
// this is quite a common thing when loading types into reflection only load context, so
// we're just going to ignore this specific one for now
var typeLoadEx = ex as TypeLoadException;
if (typeLoadEx != null)
{
if (typeLoadEx.Message.InvariantContains("does not have an implementation"))
{
//ignore
continue;
}
}
else
{
errors.Add(
string.Concat("This package could not be verified for compatibility. An error occurred while scanning a packaged assembly '",
a.GetName().Name,
"' see error log for full details."));
assembliesWithErrors.Add(a);
LogHelper.Error<PackageBinaryInspector>("An error occurred scanning package assemblies", ex);
}
}
}
errorReport = errors.ToArray();
return dllsWithReference;
}
/// <summary>
/// In order to compare types, the types must be in the same context, this method will return the type that
/// we are checking against but from the LoadFrom context.
/// we are checking against but from the Load context.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static Type GetLoadFromContractType<T>()
{
var contractAssemblyLoadFrom = Assembly.ReflectionOnlyLoadFrom(
GetAssemblyPath(Assembly.ReflectionOnlyLoad(typeof (T).Assembly.FullName)));
var contractAssemblyLoadFrom =Assembly.ReflectionOnlyLoad(typeof (T).Assembly.FullName);
var contractType = contractAssemblyLoadFrom.GetExportedTypes()
.FirstOrDefault(x => x.FullName == typeof(T).FullName && x.Assembly.FullName == typeof(T).Assembly.FullName);