Reputation: 9455
In a console application; If I execute:
Assembly.LoadFrom(@"c:\...\MyWinRTApp.exe")
I get:
System.BadImageFormatException occurred
HResult=-2147024885
Message=Could not load file or assembly 'file:///C:\_...\MyWinRTApp.exe' or one of its dependencies. An attempt was made to load a program with an incorrect format.
Source=mscorlib
Is there any way around this?
In relation to "Vyacheslav Volkov"'s answer below, I now get a step further, thank you. However I now get a different issue.
"assembly.GetExportedTypes()"
now throws
"Cannot resolve dependency to Windows Runtime type 'Windows.UI.Xaml.Application'. When using the ReflectionOnly APIs, dependent Windows Runtime assemblies must be resolved on demand through the ReflectionOnlyNamespaceResolve event."
If I try to ReflectionOnlyLoad the referenced assemblies, then I get the error:
"Could not load file or assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)".
This is related to loading winmd references, and explained in the post here: Could not load file or assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime'.
The full code I'm trying is this:
using System.Runtime.InteropServices.WindowsRuntime;
var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
/*WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve += (x, y) =>
{
y.NamespaceName ???
y.ResolvedAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(???));
return;
};*/
foreach (var references in assembly.GetReferencedAssemblies())
{
try
{
Assembly.ReflectionOnlyLoad(references.FullName);
}
catch (FileNotFoundException)
{
var fi = new FileInfo(assemblyPath);
var fi2Name = String.Format("{0}\\{1}.dll", fi.DirectoryName, references.Name);
var fi2 = new FileInfo(fi2Name);
if (fi2.Exists)
{
Assembly.ReflectionOnlyLoadFrom(fi2.FullName);
}
}
catch (FileLoadException)
{
// When a winmd assembly is attempted.
}
}
return assembly;
Any more ideas?
Thanks, Jon
The latest idea successfully resolves "{Windows.UI.Xaml, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime}".
However, when ".GetExportedTypes()" is called on the "Client.exe" assembly, the 'ReflectionOnlyNamespaceResolve' event is only fired once for namespace "Windows.UI.Xaml", which resolves to "C:\windows\system32\WinMetadata\Windows.UI.Xaml.winmd".
An exception is then thrown within ".GetExportedTypes()", which is "Cannot resolve dependency to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.".
Upvotes: 3
Views: 1901
Reputation: 4742
If you want only to discover the containing types you should use the Assembly.ReflectionOnlyLoad method.
Assembly.ReflectionOnlyLoadFrom(@"c:\...\MyWinRTApp.exe")
UPDATE
Here's the code that works for me:
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (sender, eventArgs) => Assembly.ReflectionOnlyLoad(eventArgs.Name);
WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve += (sender, eventArgs) =>
{
string path =
WindowsRuntimeMetadata.ResolveNamespace(eventArgs.NamespaceName, Enumerable.Empty<string>())
.FirstOrDefault();
if (path == null) return;
eventArgs.ResolvedAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(path));
};
Assembly loadFrom = Assembly.ReflectionOnlyLoadFrom(@"C:\....\WinRTApp.exe");
Type[] types = loadFrom.GetExportedTypes();
foreach (Type type in types)
{
Console.WriteLine(type);
}
Upvotes: 4