Department of InformatiX
Microsoft .NET Micro Framework Tools & Resources

The .NET Micro Framework comes with sophisticated and - what is more important - extensible emulator architecture. Unfortunately the projects for creating emulators in Visual Studio force us to use somewhat obsolete technology - Windows Forms. Although Steve just introduced his series about creating emulators for Windows Presentation Foundation, I have decided to publish my already written article in case anybody of you simply can't wait any longer. :-)

Emulator projects

Emulators are plain .NET applications like any other, which means, that it shouldn't be any problem to create an emulator eg. in a form of Windows service, or say inside Windows Workflow Foundation. :-)

There is a new project type coming with .NET Micro Framework SDK, called Device Emulator, which is intended specially for this task. It brings three main features, which we will have to implement ourselves in when creating our independent emulators. The first one is registration of the emulator into the Visual Studio. This assures that the emulator is showed in the emulators list in the properties of .NET Micro Framework application, as soon as you make a first successfull build. The next one is generation of empty Emulator.config file, and its automatic loading during runtime. Last, but not least, it generates the emulator template itself, a class derived from Microsoft.SPOT.Emulator.Emulator.

Troubles

So where is the problem? Why can't we just use this project and create for example a Window Presentation Foundation window instead of Windows Forms form? Well the problem is, that the WPF application - like many others - is a special type of project. Until your emulator becomes of that special type, you will be able to add only standard items into the project (and I suspect the User Control (WPF) is offered by mistake):

Add new item dialog

Whatever Emulator

The first solution is to create the project you need, and somehow squeeze the emulator in. That way we will lose the advantages mentioned above, Let's try to implement them.

Registration into Visual Studio

This one is quite easy - it's just a short registry writing:

string keyBase = @"HKEY_CURRENT_USER\Software\Microsoft\.NETMicroFramework\v3.0\Emulators\MyEmulator"; Microsoft.Win32.Registry.SetValue(keyBase, "Name", "My Emulator"); Microsoft.Win32.Registry.SetValue(keyBase, "Path", @"C:\Path\To\MyEmulator.exe"));

However, this solution is not very flexible one. You have to check the current framework's version, and if the team decides to change the registry structure, or adds some additional steps required to successfully register the emulator, you will hardly get informed. On the other side it is probably the only one distributable possibility. The Visual Studio actually uses the RegisterEmulator class in Microsoft.SPOT.Tasks.dll assembly, which you can find in the Tools SDK folder. If you want to depend on the .NET Micro Framework SDK installation (which is not that unreasonable assumption), you can use it too. In that case, this line will do:

new Microsoft.SPOT.Tasks.RegisterEmulator { SubkeyName = "MyEmulator", Name = "My Emulator", Path = @"C:\Path\To\MyEmulator.exe" }.Execute();

Emulator.config

The standard emulator project contains an empty Emulator.config file, which you can use to change the emulator's configuration without rebuilding it. This file is during building copied to the output folder, with the same name as your executable and .emulatorconfig extension. This luxury can be compensated using these steps:

  1. Add a new XML file to the project. Name it as your assembly and add the extension. For example the project is named MFEmulator1 by default. Hence your configuration file should be named MFEmuator1.exe.emulatorconfig
  2. Change its Copy to Output Directory property from Do not copy to Copy if newer, eventually Copy always.
  3. The sample XML configuration the Microsoft Emulator uses can be found in the SDK directory, at Tools\Microsoft.SPOT.Emulator.Sample.SampleEmulator.exe.emulatorconfig. This one is a pretty good empty template:
    <Emulator> <Types> <GpioPort>Microsoft.SPOT.Emulator.Gpio.GpioPort</GpioPort> <LcdDisplay>Microsoft.SPOT.Emulator.Lcd.LcdDisplay</LcdDisplay> <WinFS>Microsoft.SPOT.Emulator.FS.WindowsFileSystem</WinFS> <AsyncWinFS>Microsoft.SPOT.Emulator.FS.AsyncWindowsFileSystem</AsyncWinFS> <BSRegion>Microsoft.SPOT.Emulator.BlockStorage.Region</BSRegion> <BSBlock>Microsoft.SPOT.Emulator.BlockStorage.Block</BSBlock> <BSDevice>Microsoft.SPOT.Emulator.BlockStorage.EmulatorBlockStorageDevice</BSDevice> <RemovableBSD>Microsoft.SPOT.Emulator.BlockStorage.EmulatorRemovableBlockStorageDevice</RemovableBSD> <NativeFS>Microsoft.SPOT.Emulator.FS.NativeFileSystem</NativeFS> <RamManager>Microsoft.SPOT.Emulator.Memory.RamManager</RamManager> </Types> <EmulatorComponents> </EmulatorComponents> </Emulator>

Final project adjustments

What remains now is to add a referenct to the Mirosoft.SPOT.Emulator assembly and start the emulator class by calling MyEmulator.Start() during runtime, which is allowed to happen in another thread, too. In the installed emulator project template, the Main method is used to create and run the emulator, and everything else needed to run your application takes place in the emulator's Initializeomponent() method:

namespace MyEmulators { public class MyEmulator : Microsoft.SPOT.Emulator.Emulator { public override void InitializeComponent() { base.InitializeComponent(); // Start your WPF application, service, (ev. WinForms application if you are that kind of guy) or whatever here. // If it is blocking call (like Application.Run()), start it here in another thread. } public override void UninitializeComponent() { base.UninitializeComponent(); // Exit your application, stop your service or close whatever you need here. } // Your assembly's entry point: static void Main() { new MyEmulator().Start(); } } }

Of course it is no problem to make it the other way, starting the emulator instance from your application code base.

An Example: Console Emulator

  1. Create a new console application.
  2. Add a reference to the Microsoft.SPOT.Emulator.dll assembly from the Tools directory of SDK.
  3. Make the generated Program class derive from Microsoft.SPOT.Emulator.Emulator one.
  4. Now the application is full-featured emulator. Place new Program().Start(); inside the Main method and if you try to run the project, a known messagebox will appear: No assembly file is found. Please specify at least one exe, dll, manifest or pe file to load.
  5. To be able to test the emulator, create now a .NET Micro Framework application, console one is good enough. For sake of simplicity, let's try the famous blinking - add a reference to Microsoft.SPOT.Hardware.dll and let's have for example:
  6. using System.Threading; using Microsoft.SPOT.Hardware; namespace MFConsoleApplication1 { public class Program { public static void Main() { OutputPort port = new OutputPort(Cpu.Pin.GPIO_Pin3, false); while (true) { Thread.Sleep(1000); port.Write(!port.Read()); } } } }
  7. Try to run the blinking stuff - most likely it will use the Microsoft Emulator. Switch to the Micro Framework Device Deployment in the Output window:
    Output window
  8. Only single line will appear inside the window, beginning with Launching emulator with command line. Now copy everything starting with first "/load up to - yet excluding - the last single quote. Switch to the Visual Studio with emulator - console in fact, and past this in the Command line arguments textbox in the Debug tab of the project properties. You also can stop the Microsoft Emulator now.
  9. The last item remaining is the configuration file. Add a new XML file to the project. We need only GPIO_Pin3 in our sample, so the configuration can look like this:
    <?xml version="1.0" encoding="utf-8" ?> <Emulator> <Types> <GpioPort>Microsoft.SPOT.Emulator.Gpio.GpioPort</GpioPort> </Types> <EmulatorComponents> <GpioPort id="Pin_Select"> <Pin>3</Pin> <ModesExpected>InputOutputPort</ModesExpected> <ModesAllowed>InputOutputPort</ModesAllowed> </GpioPort> </EmulatorComponents> </Emulator>
  10. As already mentioned above, rename the XML file to your assembly name + .emulatorconfig, this means ConsoleApplication1.exe.emulatorconfig in our case, and set Copy to Output Directory property to the Copy if newer value in the Properties window (F4).
  11. And finally, our console emulator need some functionality. A bit of state information and pin monitoring:
    using System; using Microsoft.SPOT.Emulator; using Microsoft.SPOT.Emulator.Gpio; namespace ConsoleApplication1 { class Program : Emulator { private static void Main() { new Program().Start(); } public override void Start(string[] args) { Console.WriteLine("Emulator loaded."); base.Start(args); } public override void Run() { (FindComponentById("Pin_Select") as GpioPort).OnGpioActivity += delegate(GpioPort sender, bool edge) { Console.WriteLine(edge); }; Console.WriteLine("Emulator running..."); base.Run(); Console.WriteLine("Emulator exited. Press any key to continue."); Console.ReadKey(); } } }
  12. And that's it. We have created an emulator from standard console application. Similarly you can inject full emulator features into project of any type and technology. Again, the best place to initialize your favorite technology is likely to be the InitializeComponent() method, which is what the standard emulator template uses anyway for the Windows Forms. Don't forget to shut it down properly inside the UninitializeComponents() method, if required.
    Console emulator running

Emulator Whatever

The second option is to use the standard emulator template as is, and smuggle the desired technology inside. The Visual Studio distinguishes between different project types (eg. Windows Forms Application × WPF Application × ASP.NET Web Application × Word 2007 Add-in etc.) and uses this information to adjust the project behavior, including the list of available project items (Windows Form × WPF Window × Web Form × Word Document etc.). Each project type has assigned its own GUID, which is stored in the .csproj file. As an example, if you are creating a WPF Application and open the project file say in notepad, you will see
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <AssemblyName>WpfApplication1</AssemblyName> <OutputType>WinExe</OutputType> <RootNamespace>WpfApplication1</RootNamespace> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProductVersion>9.0.30729</ProductVersion> <ProjectGuid>{34895117-845f-4fef-9ea4-26211b9c3d15} </ProjectGuid> ... </PropertyGroup> ...

The ProjectTypeGuids element determines of what type the project is. {60dc8134-eba5-43b8-bcc9-bb4bc16c2548} means WPF application, {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} stands for C# language. As you have probably already guessed, you need to take these GUIDs and insert them into the project file of your emulator. If it already contains the ProjectTypeGuids element, just use semicolon to separate the GUIDs, if not, feel free to create it - in the first /Project/PropertyGroup element, as shown above. Save, and open the project in Visual Studio again (or just reload). Now when you want to add a new project item, various sweets are waiting for you:

Add new project item dialog of the tampered emulator project

Whatever Emulator, revisited

If you have the .NET Micro Framework SDK, have read through the whole article down to here, and you want any of your project types to behave like emulator without the need to implement the functionality yourself as in the first part, I have a nice surprise for you - you can do that. You only have to notice some of the inconspicious part in the emulator's project file:

<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{439094ED-505C-476E-B005-90F5719E1044}</ProjectGuid> <OutputType>WinExe</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>MFEmulator1</RootNamespace> <AssemblyName>MFEmulator1</AssemblyName> <EmulatorId>{a11fd6cd-1bf7-46f7-987d-c7129ddcd11a}</EmulatorId> <TargetFrameworkVersion>v3.0</TargetFrameworkVersion> <NetMfTargetsBaseDir Condition="'$(NetMfTargetsBaseDir)'==''">$(MSBuildExtensionsPath)\Microsoft\.NET Micro Framework\</NetMfTargetsBaseDir> </PropertyGroup> ... <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(NetMfTargetsBaseDir)\v3.0\Emulator.Targets" /> <ItemGroup> <Reference Include="Microsoft.SPOT.Emulator, Version=3.0.7186.0, Culture=neutral, PublicKeyToken=2670f5f21e7f4192, processorArchitecture=x86" /> ... </ItemGroup> ... </Project>

Insert the marked lines into your project file, and they will gain the functionality of emulator projects immediately. Remember this is only a help during the emulator development for you, which you don't have to use (eg. if you don't like the automatic registration) - this trick even does not work if you don't have the .NET Micro Framework SDK installed. Advanced developers can go further, and see or adjust the mentioned .target files to their liking (eg. switch off the registration stuff only). Though, woe betide you who will end up with wrecked studio asking for help in the community! :-)

Comments
Comment 3/11/2012 1:28:38 AM
I think that "User Control (WPF)" is not mistake since as you know you can host WPF conrol in WinForms. I have created WPF user control which accepts a reference to the Emulator: public Form1(Emulator emulator) { InitializeComponent(); ((UserControl1) this.elementHost1.Child).Emulator = emulator; } and the whole implementation is kept by UserControl1 class.
Sign in using Live ID to be able to post comments.