Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Launching an application from an SD card fails. AppDomain.CreateInstanceAndUnwrap() and Assembly.Load() - not implemented?


  • Please log in to reply
39 replies to this topic

#1 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 22 December 2010 - 07:25 PM

Hi,

I am working on a project where I need to launch an application from an SD card. The netduino is running firmware v4.1.1.0 alpha 2 and file I/Os with the SD card work fine.


A little research lead me to an app launcher on on fezzer.com (http://www.fezzer.co...-external-apps/) which creates a new app domain and loads the target assemblies for the application dynamically. Porting it over to the netduino was straight forward and I've attached the project to this thread.

The problem is that AppDomain.CreateInstanceAndUnwrap() always fails with a 'not implemented' exception and Assembly.Load() always returns 'null'.

I would have expected these basic functions to be supported on the netduino.

Is there something that I'm missing or are these functions just not supported by the latest netduino SDK?

Cheers,
-Fabien.

Attached Files

  • Attached File  Boot.zip   65.46KB   33 downloads


#2 AlfredBr

AlfredBr

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationConnecticut, USA

Posted 22 December 2010 - 07:37 PM

I'm struggling with the same error, but I'll try the suggestion in the thread below tonight. http://forums.netdui..._6396#entry6396

#3 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 22 December 2010 - 08:22 PM

Hi Alfred, I looked at the source of the MF 4.1 porting kit, specifically: corlib_native_System_AppDomain.cpp and corlib_native_System_Reflection_Assembly.cpp where the app domain creation and assembly loading functions live. There's indeed an implementation for both BUT it is controlled by a compilation switch: #if defined(TINYCLR_APPDOMAINS). Is the netduino MF implementation actually compiled with a 'TINYCLR_APPDOMAINS' switch enabled? Cheers, -Fabien.

#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 22 December 2010 - 09:32 PM

Is the netduino MF implementation actually compiled with a 'TINYCLR_APPDOMAINS' switch enabled?


Hi Fabien,

If you press Ctrl+C in MFDeploy, it'll display the capabilities of the device.

On the Netduino...
AppDomains: True

If there's a piece disabled or missing, let me know and I'll see if we can enable it in the core firmware...

Chris

#5 AlfredBr

AlfredBr

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationConnecticut, USA

Posted 22 December 2010 - 10:02 PM

Chris,

See if you can use this to reproduce the problem.

using System;
using System.Diagnostics;
using System.Reflection;
using Microsoft.SPOT;

[Serializable]
public class SerializableClass
{
    public string WhatIsMyAppDomain()
    {
        return AppDomain.CurrentDomain.FriendlyName;
    }
}

public class MarshallByRefClass : MarshalByRefObject
{
    public string WhatIsMyAppDomain()
    {
        return AppDomain.CurrentDomain.FriendlyName;
    }
}

public class Test
{
    public static void Main(string[] args)
    {
        AppDomain ad = AppDomain.CreateDomain("OtherAppDomain");
        var assemblyName = Assembly.GetExecutingAssembly().FullName;
        var marshall = (MarshallByRefClass) ad.CreateInstanceAndUnwrap(assemblyName, "MarshallByRefClass");
        var serializable = (SerializableClass) ad.CreateInstanceAndUnwrap(assemblyName, "SerializableClass");
        Debug.Print(marshall.WhatIsMyAppDomain());
        Debug.Print(serializable.WhatIsMyAppDomain());
    }
}


#6 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 22 December 2010 - 11:10 PM

Hi Fabien,

If you press Ctrl+C in MFDeploy, it'll display the capabilities of the device.

On the Netduino...
AppDomains: True

If there's a piece disabled or missing, let me know and I'll see if we can enable it in the core firmware...

Chris


Hmmm..


HalSystemInfo.halVersion: 4.1.2821.0
HalSystemInfo.halVendorInfo: Netduino (4.1.1.0 a2) by Secret Labs LLC
HalSystemInfo.oemCode: 34
HalSystemInfo.modelCode: 177
HalSystemInfo.skuCode: 4096
HalSystemInfo.moduleSerialNumber: 00000000000000000000000000000000
HalSystemInfo.systemSerialNumber: 0000000000000000
ClrInfo.clrVersion: 4.1.2821.0
ClrInfo.clrVendorInfo: Netduino (4.1.1.0 a2) by Secret Labs LLC
ClrInfo.targetFrameworkVersion: 4.1.2821.0
SolutionReleaseInfo.solutionVersion: 4.1.1.0
SolutionReleaseInfo.solutionVendorInfo: Netduino (4.1.1.0 a2) by Secret Labs LLC
SoftwareVersion.BuildDate: Sep 29 2010
SoftwareVersion.CompilerVersion: 400771
FloatingPoint: True
SourceLevelDebugging: True
ThreadCreateEx: True
LCD.Width: 0
LCD.Height: 0
LCD.BitsPerPixel: 0
AppDomains: True
ExceptionFilters: True
IncrementalDeployment: True
SoftReboot: False
Profiling: False
ProfilingAllocations: False
ProfilingCalls: False
IsUnknown: False

So, AppDomains are enabled.

I ran Alfred's code and here's what I get:


AppDomain ad = AppDomain.CreateDomain("OtherAppDomain"); -> OK
var assemblyName = Assembly.GetExecutingAssembly().FullName; -> OK
var marshall = (MarshallByRefClass)ad.CreateInstanceAndUnwrap(assemblyName, "MarshallByRefClass"); -> Exception is thrown


The thread '<No Name>' (0x3) has exited with code 0 (0x0).
#### Exception System.NotImplementedException - 0xca000000 (1) ####
#### Message:
#### System.AppDomain::CreateInstanceAndUnwrap [IP: 0000] ####
#### AppDomainTest.Test::Main [IP: 0017] ####
A first chance exception of type 'System.NotImplementedException' occurred in mscorlib.dll
#### Exception System.NotImplementedException - 0xca000000 (1) ####
#### Message:
#### AppDomainTest.Test::Main [IP: 0017] ####
A first chance exception of type 'System.NotImplementedException' occurred in AppDomainTest.exe
An unhandled exception of type 'System.NotImplementedException' occurred in AppDomainTest.exe


How can one instantiate and run a class from a dynamically loaded assembly on the netduino?

Cheers,
-Fabien.

#7 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 25 December 2010 - 06:17 AM

The problem is that AppDomain.CreateInstanceAndUnwrap() always fails with a 'not implemented' exception and Assembly.Load() always returns 'null'.


Fabien,

Do you have a sample assembly that you're trying to load? Perhaps with source? I'm making sure we have a good repro case for this to investigate further...

Chris

#8 bill.french

bill.french

    Advanced Member

  • Members
  • PipPipPip
  • 260 posts
  • LocationPrinceton, NJ

Posted 25 December 2010 - 02:41 PM

I would have expected these basic functions to be supported on the netduino.


Am I naive for thinking these functions are almost the polar opposite of basic?

#9 AlfredBr

AlfredBr

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationConnecticut, USA

Posted 25 December 2010 - 04:51 PM

My sample code does not work on the emulator either, so this is not appear to be a Netduino specific thing....

#10 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 28 December 2010 - 09:24 PM

Am I naive for thinking these functions are almost the polar opposite of basic?


LoL! Well, 'basic' as far as loading / executing assemblies goes ;-)

#11 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 28 December 2010 - 09:32 PM

Fabien, Have you tried loading assemblies into the current AppDomain (using Assembly.Load)? Chris

#12 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 28 December 2010 - 09:36 PM

Fabien,

Do you have a sample assembly that you're trying to load? Perhaps with source? I'm making sure we have a good repro case for this to investigate further...

Chris


Hi Chris,

Sorry for the delay in responding to your question: I got sidetracked with the holidays :)

Here's something super-simple that I tried loading and executing, either in a .dll or in an executable:


using System;
using System.Reflection;
using Microsoft.SPOT;

namespace ASSM
{
    public class TestClass
    {
        public void Print()
        {
            Debug.Print("Hello from dynamically-loaded assembly!");
        }
    }
}

I attempted loading the assembly using these functions to no avail:


public static System.Reflection.Assembly Load(byte[] rawAssembly)
Member of System.Reflection.Assembly


public static System.Reflection.Assembly Load(string assemblyString)
Member of System.Reflection.Assembly


public System.Reflection.Assembly Load(string assemblyString)
Member of System.AppDomain

and attempted instantiating the class using:


public object CreateInstanceAndUnwrap(string assemblyName, string typeName)
Member of System.AppDomain

None of which work...

#13 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 28 December 2010 - 10:26 PM

Here's how I attempted loading the assembly:


using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.IO;
using SecretLabs.NETMF.Hardware.Netduino;

namespace AppDomainTest
{
    public class Test
    {
        public static void Main(string[] args)
        {
            StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Cpu.Pin.GPIO_Pin10 );

            using (FileStream assmfile = new FileStream(@"SD\assm.dll", FileMode.Open, FileAccess.Read, FileShare.None))
            {
                byte[] assmbytes = new byte[assmfile.Length];

                assmfile.Read(assmbytes, 0, (int) assmfile.Length);

                // assm is always null after Assembly.Load() returns!
                var assm = Assembly.Load(assmbytes);

                // and we get a NullReferenceException here of course...
                var type = assm.GetType("ASSM.TestClass");

                // Do something with the type here...
            }

            StorageDevice.Unmount("SD");
        }
    }
}


#14 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 28 December 2010 - 10:48 PM

Here's how I attempted loading the assembly:

This will probably not help much, but IMHO Assembly.Load(byte[] rawAssembly) requires PE file, not DLL (.NET Micro Framework has its own format).

#15 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 28 December 2010 - 11:07 PM

This will probably not help much, but IMHO Assembly.Load(byte[] rawAssembly) requires PE file, not DLL (.NET Micro Framework has its own format).


That's true. Use the .pe file in the "le" (little endian) folder if loading assemblies directly...

Chris

#16 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 29 December 2010 - 10:04 AM

CW2, Chris, Thanks. Good to know. I'll try with a PE file and will let you know what happens. Cheers, -Fabien.

#17 Fabien Royer

Fabien Royer

    Advanced Member

  • Members
  • PipPipPip
  • 406 posts
  • LocationRedmond, WA

Posted 29 December 2010 - 09:28 PM

At last, I finally figured it out! :)

Here's the code of the target assembly being loaded from the SD card as a little-endian .pe file.
  • This assembly only references Microsoft.SPOT.Native and mscorlib, both of which are already loaded in the calling assembly below. This is important because assemblies are explicitly loaded. Any dependency also needs to be dynamically loaded.
  • Note the bold string in Print(): it will be in the output at the very end of this post.


using System;
using System.Reflection;
using Microsoft.SPOT;

namespace ASSM
{
    public class TestClass
    {
        public void Print()
        {
             Debug.Print("Hello from " + this.ToString());
        }
    }
}


Now for the the loader assembly:


using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.IO;
using SecretLabs.NETMF.Hardware.Netduino;

namespace AppDomainTest
{
    public class Test
    {
        public static void Main(string[] args)
        {
            StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Cpu.Pin.GPIO_Pin10 );

            using (FileStream assmfile = new FileStream(@"SD\assm.pe", FileMode.Open, FileAccess.Read, FileShare.None))
            {
                byte[] assmbytes = new byte[assmfile.Length];
                assmfile.Read(assmbytes, 0, (int) assmfile.Length);

                var assm = Assembly.Load(assmbytes);
                var obj = AppDomain.CurrentDomain.CreateInstanceAndUnwrap("ASSM, Version=1.0.0.0", "ASSM.TestClass");
                var type = assm.GetType("ASSM.TestClass");
                MethodInfo mi = type.GetMethod("Print");

                 mi.Invoke(obj, null);
            }

            StorageDevice.Unmount("SD");
        }
    }
}


And the output:


The debugging target runtime is loading the application assemblies and starting execution.
Assembly: ASSM (1.0.0.0) (188 RAM - 328 ROM - 151 METADATA)

AssemblyRef = 8 bytes ( 2 elements)
TypeRef = 12 bytes ( 3 elements)
FieldRef = 0 bytes ( 0 elements)
MethodRef = 16 bytes ( 4 elements)
TypeDef = 8 bytes ( 1 elements)
FieldDef = 0 bytes ( 0 elements)
MethodDef = 4 bytes ( 2 elements)

Attributes = 0 bytes ( 0 elements)
TypeSpec = 0 bytes ( 0 elements)
Resources = 0 bytes ( 0 elements)
Resources Files = 0 bytes ( 0 elements)
Resources Data = 0 bytes
Strings = 28 bytes
Signatures = 15 bytes
ByteCode = 21 bytes



Total: (9848 RAM - 79908 ROM - 44518 METADATA)

AssemblyRef = 92 bytes ( 23 elements)
TypeRef = 748 bytes ( 187 elements)
FieldRef = 60 bytes ( 15 elements)
MethodRef = 940 bytes ( 235 elements)
TypeDef = 2424 bytes ( 303 elements)
FieldDef = 932 bytes ( 460 elements)
MethodDef = 3020 bytes ( 1506 elements)

DebuggingInfo = 1528 bytes

Attributes = 48 bytes ( 6 elements)
TypeSpec = 24 bytes ( 6 elements)
Resources Files = 72 bytes ( 3 elements)
Resources = 304 bytes ( 38 elements)
Resources Data = 1184 bytes
Strings = 6778 bytes
Signatures = 5626 bytes
ByteCode = 25520 bytes


'Microsoft.SPOT.Debugger.CorDebug.dll' (Managed): Loaded 'ASSM'
Hello from ASSM.TestClass
The thread '<No Name>' (0x1) has exited with code 0 (0x0).
Done.
Waiting for debug commands...
The program '[8] Micro Framework application: Managed' has exited with code 0 (0x0).

Cheers,
-Fabien.

#18 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 30 December 2010 - 05:39 AM

Awesome! Thanks, Fabien.

#19 Dezorian

Dezorian

    Member

  • Members
  • PipPip
  • 24 posts

Posted 20 March 2011 - 09:05 AM

Awesome project! Tnx for sharing.

#20 Stavros Tekes

Stavros Tekes

    Member

  • Members
  • PipPip
  • 17 posts
  • LocationThessaloniki, Greece

Posted 12 August 2011 - 12:16 PM

At last, I finally figured it out! :)

Here's the code of the target assembly being loaded from the SD card as a little-endian .pe file.

  • This assembly only references Microsoft.SPOT.Native and mscorlib, both of which are already loaded in the calling assembly below. This is important because assemblies are explicitly loaded. Any dependency also needs to be dynamically loaded.
  • Note the bold string in Print(): it will be in the output at the very end of this post.


Hi Fabien, and all others in the thread

Thanks for the contribution, it could eventually help to a remote update of our software.

Has anyone tested this with the netduino plus?

I am using MF 4.2 RC1 and I am trying your exact code (as all my tries have failed) and I receive the same exception in CreateInstanceAndUnwrap you had.


Cheers

Stavros
Stavros




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.