3

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?

EDIT 1

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

Edit 2

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.".

Community
  • 1
  • 1
Jon Rea
  • 9,337
  • 4
  • 32
  • 35
  • What do you want to do with this assembly? – Vyacheslav Volkov Aug 07 '13 at 10:34
  • Reflect over it to discover the containing types for display purposes only. I don't need to create a run-time instance of any of the types. – Jon Rea Aug 07 '13 at 11:30
  • Still getting: "Could not load file or assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified." – Jon Rea Aug 12 '13 at 13:58
  • If you are interested, this is for the open source project 'Docu' (https://github.com/jagregory/docu), allowing it to read Windows Store assemblies. I could ping you the code I'm modifying, and then I could update this question if we make any progress. Thanks, Jon – Jon Rea Aug 12 '13 at 14:01
  • Did you ever solve this? I had a similar issue and found that having the .NET 4.5 application pre-load System.Runtime (added a reference include for System.Runtime in the build process for the .NET 4.5 build) allowed 'GetExtractedTypes' to proceed successfully. – Dave Doknjas Sep 21 '13 at 01:18
  • The Demo code supplied by Vyacheslav Volkov did work on a vanilla project but not on my own project. I think its because we have a complex assortment of PCLs and WinRT native libraries which confuse the issue somewhat. For the moment, this is on the back-burner for us. – Jon Rea Sep 24 '13 at 15:36

1 Answers1

4

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);
}
Vyacheslav Volkov
  • 4,592
  • 1
  • 20
  • 20
  • Thank you for your help so far. This gets me a step further, but still no luck. Please see my modified question... – Jon Rea Aug 07 '13 at 14:35
  • If you are interested, this is for the open source project 'Docu' (https://github.com/jagregory/docu), allowing it to read Windows Store assemblies. I could ping you the code I'm modifying, and then I could update this question if we make any progress. Thanks, Jon – Jon Rea Aug 12 '13 at 14:00
  • Still getting: "Could not load file or assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified." – Jon Rea Aug 12 '13 at 14:01
  • Strange but it works for me. I wrote the code that I ran from the console application. – Vyacheslav Volkov Aug 12 '13 at 14:26
  • I think this may be because the exe I'm trying to reflect references a second PCL library (targeting Profile78), which is present in the same folder as the main exe. Sorry for not posting that information, I guess that's pretty relevent! In my code, I have to also ReflectionOnlyLoad the DLLs in the same folder as the exe, which is fine until GetExportedTypes is called, and that's where I get the error about System 2.0.5.0... Cheers, Jon – Jon Rea Aug 13 '13 at 09:36
  • Unfortunately I cannot reproduce the error, can you give the code where you try to load the assemblies? – Vyacheslav Volkov Aug 13 '13 at 14:10
  • @VyacheslavVolkov If you're still there, could you please help me? I seem to be having a similar problem, even when I use your solution. I've asked a question [here.](http://stackoverflow.com/q/35261749/4077294) – James Ko Feb 08 '16 at 14:50