Home   Community Projects   OpenNETCF.com   About us    
OpenNETCF Blogs  
 
Below are the latest posts from the OpenNETCF Team: ChrisNeilAlex  

Latest Posts

Hosting RESTful Web Services in Windows CE - Part II

In the last article we looked at setting up Padarn for using custom HttpHandlers.  In this article we'll look at exactly how we use a custom handler to get data.

The GET Service

Probably the most common HTTP method is the GET method.  It's what your browser used to pull the content of this page, and it's what our REST service will use to get back a list of all Books in our database.

First, I create an entity that defines a Book.  This code file will actually get shared between the device and desktop projects to make things simple.

public class Book
{
  public int ID { get; set; }
  public string Title { get; set; }
  public string Author { get; set; }
  public int? Pages { get; set; }

  public static Book FromXml(string xml)
  {
    // omitted for brevity
  }

  public string AsXml()
  {
    // omitted for brevity
  }
}

I've left out the XML serialization/deserialization routines because they take up a lot of space and aren't really that interesting.  They're in the example source (I'll post it when I get these articles up - be patient) if you want to see them.

So next I need a way to get a list of these from my Database.  To encapsulate all of this logic, I created a DatabaseConnector singleton class that resides in the same assembly as the HttpHandlers.  Remember, these handlers are stateless and get created and called every time a URL is requested, so it would be pointless to put a connector instance in the handler itself.

The DatabaseConnector exposes a GetAllBooks method:

public Book[] GetAllBooks()
{
  string sql = "SELECT BookID, Title, Author, Pages FROM Books";
  List<Book> books = new List<Book>();

  using(SqlCeCommand cmd = new SqlCeCommand(sql, Connection))
  using(var resultset = cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
  {
    if (resultset.HasRows)
    {
      while (resultset.Read())
      {
        books.Add(new Book
        {
          ID = resultset.GetInt32(0),
          Title = resultset.GetString(1),
          Author = resultset.GetString(2),
          Pages = resultset.IsDBNull(3) ? null : (int?)resultset.GetInt32(3)
        });
      }
    }
  }

  return books.ToArray();
}

Now all that I need to do is call this from my GetHandler like so:

public class GetHandler : BaseHandler
{
public override void ProcessRequest(HttpContext context)
{
  string entity = GetEntityName(context.Request.Path);

  // the only entity we support is "Books"
  if (string.Compare(entity, "books", true) != 0)
  {
    throw new HttpException(HttpErrorCode.NotFound, string.Format("Entity '{0}' not supported", entity));
  }

  Book[] books = DataConnector.GetInstance().GetAllBooks();

  StringBuilder sb = new StringBuilder(XML_HEADER);
  sb.Append("<books>");

  foreach (var b in books)
  {
    sb.Append(b.AsXml());
  }

  sb.Append("</books>");

  context.Response.Write(sb.ToString());
  context.Response.Flush();
}

That's all there is to it.  We now have implemented a REST service to get all Books from our Windows CE device.  When the Padarn server sees a GET request at http://<ip address>/books/ it will return an XML stream of all of the books in the database.  Here's an example of the output:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book>
    <id>1</id>
    <title>The Count of Monte Cristo</title>
    <author>Alexandre Dumas</author>
    <pages>1573</pages>
  </book>
  <book>
    <id>2</id>
    <title>Programming WCF Services</title>
    <author>Juval Loewy</author>
    <pages>610</pages>
  </book>
</books>

The GET Client

Now let's look at how a non-browser client (i.e. a desktop application) might make use of this service.

First, since I like abstraction and encapsulation, I created a class named RestConnector that handles all communications for REST services and a class named BookClient who's job is to handle nothing but interactions with the Books service.  RestConnector handles any GET requirements through the following methods:

public string Get(string directory)
{
  string page = string.Format("http://{0}/{1}", DeviceAddress, directory);

  StringBuilder sb = new StringBuilder();

  byte[] buf = new byte[8192];

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(page);

  HttpWebResponse response = (HttpWebResponse)request.GetResponse();

  return GetResponseData(response);
}

private string GetResponseData(HttpWebResponse response)
{
  StringBuilder sb = new StringBuilder();

  byte[] buf = new byte[8192];

  Stream stream = response.GetResponseStream();

  string result = null;
  int count = 0;

  do
  {
    count = stream.Read(buf, 0, buf.Length);

    if (count != 0)
    {
      // look for a UTF8 header
      if ((buf[0] == 0xEF) && (buf[1] == 0xBB) && (buf[2] == 0xBF))
      {
        result = Encoding.UTF8.GetString(buf, 3, count - 3);
      }
      else
      {
        result = Encoding.UTF8.GetString(buf, 0, count);
      }
      sb.Append(result);
    }
  } while (count > 0);

  return sb.ToString();
}

The BookClient uses the Get method to retrieve the XML for a list of books from the service and then deserializes that XML like this:

public Book[] GetAllBooks()
{
  List<Book> books = new List<Book>();

  string xml = Connector.Get(ENTITY_NAME);

    XmlDocument doc = new XmlDocument();
  doc.LoadXml(xml);

  foreach (XmlNode node in doc.SelectNodes("books/book"))
  {
    books.Add(Book.FromXml(node.OuterXml));
  }

  return books.ToArray();
}

It's really that simple.  At this point we have a simple array of Book instances passed from our service to our desktop client so we can do whatever we'd like with them (I'm just displaying them).

Up next: Using POST to add a new entity



Managed Code in the Embedded World

posted @ Fri, 05 Feb 2010 16:51:01 GMT by Chris
tags: OpenNETCF,Padarn

Hosting RESTful Web Services in Windows CE - Part I

I've spent a bit of time lately adding HttpHandler support to our Padarn Web Server for Windows CE, and today I just wrapped up the code for a pretty in-depth example for using it to host RESTful Web Services.  I'm going to give some highlights on how it works here in my blog as well, because while it's remarkably easy to get working, there's still a lot going on.

Background

The general idea is to have a database on a Windows CE device and a client application on the desktop that could access that database via a Web Service hosted on the device.  I want to be able to do all of the CRUD operations through the service, and nicely these to the HTTP methods:

POST - Create a new entity in the database
PUT - Update an existing entity in the database
GET - Read an entity (or list of entities) from the database
DELETE - Delete an entity from the database

To make things simple, I created a very simple database that contains only one table.  The simple data model isn't real-world, but if you can make it work for one table, making it work for your entire database is really just an extension of the code base.

Setting Up Padarn

I'm going to use custom HttpHandlers to act as the service entry points.  HttpHandlers in Padarn look and work just like they do under IIS, the only difference is how they get "installed:. For Padarn, the handlers are configured, like everything else, in Padarn's configuration file.  To make my life simpler, and the code easier to read, I'll create a separate handler for each separate HTTP method, so one for GET, one for POST and so on.  This is how they get registered with the server:

<httpHandlers>
  <assembly>SampleSite.dll</assembly>
  <add verb="GET" path="/*" type="SampleSite.Handlers.GetHandler, SampleSite"/>
  <add verb="PUT" path="/*" type="SampleSite.Handlers.PutHandler, SampleSite"/>
  <add verb="POST" path="/*" type="SampleSite.Handlers.PostHandler, SampleSite"/>
  <add verb="DELETE" path="/*" type="SampleSite.Handlers.DeleteHandler, SampleSite"/>
</httpHandlers>

Pretty simple. the "add" nodes simply say what method/verb in any given server path maps to a given class.  Padarn uses regex to parse the path, so the first add line basically says "for GET methods to any path on the server, call into an instance of a GetHandler class".  Since the GetHandler is in a separate assembly from my hosting executable, Padarn needs to know about that assembly so it can load it at run time.  The assembly node simply tells Padarn to load up that assembly before it tries creating any custom handler class instances.

Once this is configured, the only thing left to do is to implement the handlers.  An HttpHandler is really simple - it contains a single overriden method that gets called when a page is requested.  Here's what the GetHandler stub looks like:

namespace SampleSite.Handlers
{
  public class GetHandler : BaseHandler
  {
    public override void ProcessRequest(HttpContext context)
    {
      // do stuff here
    }
  }
}

I get in an HttpContext, which has both the HttpRequest and HttpResponse objects. Note how we're trying very hard to mirror the object model Microsoft uses to make the learning curve much easier and to make your code more portable.  The HttpRequest contains, among other things, the incoming path and data.  The HttpResponse is where we write back out our data. 

SImple enough so far, right?  Next up: getting data from our RESTful service.
 



Managed Code in the Embedded World

posted @ Fri, 05 Feb 2010 16:18:58 GMT by Chris
tags: OpenNETCF,Padarn

Getting Access Point information from Visual Basic

Well I blew the VB cobwebs out of my brain this morning and wrote a very basic example of getting AP info like signal strength using the SDF.  It took me nearly 2 hours and a whole lot of search engine work to remind me of syntax to crank out a simple 70-line application (I actually had to find a machine with VB installed first, as it's no longer in my "default" install of Studio).  Hard to believe I was once fluent enough in the language to have written a book.

At any rate, here's the sample: BasicWiFiSample.rar (532.46 KB)



Managed Code in the Embedded World

posted @ Wed, 13 Jan 2010 12:26:21 GMT by Chris
tags: Compact Framework Code,OpenNETCF,SDF Samples

OpenNETCF IoC Framework updates

For those following the OpenNETCF IoC Framework, I've checked in another set of fixes.  So yes, it's still an active project.



Managed Code in the Embedded World

posted @ Wed, 06 Jan 2010 12:42:12 GMT by Chris
tags: .NET Compact Framework,Dependency Injection,OpenNETCF,OpenNETCF.IoC

Marshal.Copy/Write is no longer atomic?

Ages ago I did a science project where I was reading and writing registers from managed code.  It worked well and there is absolutely no reason that you shouldn't be able to do this kind of thing.  Windows CE is an embedded platform, and affecting hardware is what we do in the embedded world.

Well, as with any code posted on the web (and in fact this got rolled into the Smart Device Framework), it got used in some actual shipping products.  Great!  i'm not the only one who thinks we should be able to do this stuff.

Well, over the past 6 months or so I had a few different people contact me saying that the code either didn't work, or did work on their earlier hardware, but was now giving strange behavior.

Most telling was that if you hooked up a scope to the memory, you would see 4 write pulses when writing to a register.  Furthermore, all 4 bytes in the register ended up getting set to the last byte in the array you wanted to write.  For example, if you wrote 0x12345678 to a register, it would actually get set to 0x56565656.

Now I know that this code originally worked.  I wrote it using actual hardware (PXA255) so the behavior was new.  The fact that there were 4 strobes on the memory strongly suggested that the code was actually doing 4 individual writes for the 4 bytes, not a single, atomic 4-byte write.

I looked at the code and it couldn't be more simple.  A write boiled down to this:

public void WriteInt32(int data)
{
   Marshal.WriteInt32(m_addressPointer, data);
}

A bit more investigation found that the behavior was fine under CF 1.0, but started failing in CF 2.0.  What that means is that Microsoft changed the underlying implementation of the Marshal class, and in a bad way.  Why would they do such a stupid, stupid thing?  The new mechanism is going to not only cause a break for the writes we're looking at, but it's also a lot slower.

Since I don't know who did this, I can only guess as to what happened.  If you write a 4-byte value to an address that is not DWORD aligned (i.e. not evenly divisible by 4) then an ARM processor with throw a fault and puke on you (x86 throws, but handles it internally).  My bet is that some edge case got reported that the CF was throwing an unaligned exception, and some idiot developer decided that the heavy-handed solution of changing the write to happen byte-by-byte would be the solution.  Yes, it prevents the error, but it causes bugs and is bad, bad form.  Personally I'd like to slap the persone who made the change and the person who reviewed the change and thought it was ok.

So how do you get around this?  Well by doing what the CF itself should have done.  Instead of using Marshal, you use unsafe code and pointers, and check address alignnment before writing.  Something like this:

public unsafe void WriteInt32(int data, int offset)
{
  int baseAddr = (m_addressPointer.ToInt32() + offset);
  if (baseAddr % 4 == 0)
  {
    // dword aligned
    uint* pDest = (uint*)(baseAddr);
    *pDest = (uint)data;
  }
  else if (baseAddr % 2 == 0)
  {
    // word aligned
    ushort* pDest = (ushort*)(baseAddr);
    *pDest = (ushort)(data >> 0x10);
    pDest += 2;
    *pDest = (ushort)(data & 0xFFFF);
  }
  else
  {
    // byte aligned
    byte* pDest = (byte*)(baseAddr);
    foreach (byte b in BitConverter.GetBytes(data))
    {
      *pDest = b;
      pDest++;
    }
  }
}

This is a classic case of someone not understanding the problem they are solving.  This logic should have been done well below us - that's the whole point of using managed code, right?  To simplify things.  Unfortunately it also allows many developers to write code without understanding what it's really doing, and in my mind that's crazy risky. 

Testing also shows that the Read and Copy methods are similarly broken and all of these bugs still exist in CF 3.5, and I strongly suspect it will remain broken in future versions.  So beware, if you're using Marshal for moving data, you could probably get 4x performance improvement by using a pointer instead.



Managed Code in the Embedded World

posted @ Tue, 05 Jan 2010 11:53:28 GMT by Chris
tags: .NET Compact Framework,OpenNETCF

Revisiting the Form Stack

Long, long ago I wrote an article for MSDN on creating a multi-Form CF application that used a Form Stack.  Since we all tend to grow and learn as developers, we find different ways to do things (and generally we scoff at code we wrote years before as inferior crap). 

Well Peter Nowak is giving a presentation of the OpenNETCF.IoC framework next week and I decided that a sample of using the UI elements of the library (Workspaces, SmartParts, etc) might be handy and so I decided to rewrite the Form Stack following my latest thinking.  Basically the idea is to allow a user to navigate through Forms (actually Views - you are separating your Views from the Model, right?) like you would on a browser.  You can move forward and back as well as "adding" to the end or top of the stack.  We also don't want to be constantly creating new instances of the View classes because we like applications to perform well.

Here's a look at the new application (yes, I know it's "developer ugly" but this is about architecture, not aesthetics):

You can see the stack in the list, and our current position is noted by the asterisk.  "Fwd" will move down to View B, "Back" will move up to Form A, or you can push a new A or B onto the stack at the current location, which will truncate everything currently above (after) the current position.  Again, think of how your browser works.  It's important to know, also, that there are only 3 total View instances created at this point (one of each specific type).

The code for this application is in source control over at the OpenNETCF.IoC Framework Codeplex site.  You'll notice it's called FormStackCS, hinting that there may be a FormStackVB coming.  If you'd like to volunteer to do that port, by all means let me know (meaning don't hold your breath waiting for me to do it).



Managed Code in the Embedded World

posted @ Wed, 25 Nov 2009 11:21:11 GMT by Chris
tags: Compact Framework Code,Dependency Injection,Inversion of Control,OpenNETCF,OpenNETCF.IoC,Patterns and Practices

Debugging Smart Device MSTEST Unit Tests

If you've ever done mstest unit testing with a Smart Device project, then you're painfully aware of how badly Microsoft dropped the ball on this one.  Debugging a unit test requires making device registry modifications, adding a call to Debugger.Break in your code, then telling Studio to Attach to Remote Process once the breakpoint has been hit.  Seriously, that's their officially published answer to how you debug a Smart Device unit test!

If you know anything about testing, you know that keeping the cycle time for a test to a minimum.  The longer it takes a developer to go from "start testing" to a break point where they can step, then the less productive they're going to be.  Even worse, if the process is painful, slow and convoluted (check, check and check for Microsoft's recommendation), they're likely to just skip writing tests altogether.

Internally we get around this by using our own test runner which uses Reflection to load up and run tests.  I've decided to once again give back to the community and publish this gem as part of Project Resistance (it will get checked in to the IoC Framework as well).

It does not support everything that mstest does, but it's got enough to get you going, and I think it's at least reasonably easy to modify if it doesn't meet your needs.  The currently supported attributes are:

It also might now be obvious how to set it up for your own app.  You need to add a reference to your test assemblies (so VS will deploy them - for some stupid reason you can't tell it to do so via the Configuration Manager) and make sure all projects are set to deploy to the same place.

As usual, if you have feedback or updates, please let me know.  Submitting a patch right on one of the project portals is probably the easiest way (hint, hint).

It's probably worth noting here that the code for this is the CFTestRunner project, and you have to pull it from the source tab on the project site (it's not in the release download yet).



Managed Code in the Embedded World

posted @ Fri, 20 Nov 2009 12:36:06 GMT by Chris
tags: .NET Compact Framework,Compact Framework Code,OpenNETCF,OpenNETCF.IoC,Project Resistance,Windows CE Code

Project Resistance Note: This will be a slow week

For those following Project Resistance, this is probably going to be a week with little progress.  I've got a major milestone on another project that we're trying to prepare for followed by an on-site installation so my activity in the code base will be very, very limited.  I believe Alex is also on-site and swamped this week as well.  We will be back at it next week though, hopefully with some new graphics so we can hammer out the final details of the UI.



Managed Code in the Embedded World

posted @ Mon, 02 Nov 2009 19:57:31 GMT by Chris
tags: OpenNETCF,Project Resistance

Project Resistance: Event Aggregation with OpenNETCF.IoC

So my final piece of functionality for the week in Project Resistance was to add key handling to the code base.  The idea is that if you're running on a non-touch device (or for some reason want to use the D-Pad on a touch device) then you need some ability to "select" a resistance band to change.  I plumbed through events from the Form down to the ResistorController, and back up to the View so now you can move left or right to select a resistance band and then up or down will cycle the band just like a gesture will.  Of course there's nothing yet to *visually* show you what band is selected, but the code is in place for it.

What's most interesting about the way this works is that I'm not using the standard old EventHandler subscription mechanism in code.  Instead I'm using a pattern called "event aggregation."  It's a bit odd, but I couldn't find a reasonable definition online of exactly what event aggregation is, so instead of a link, I'll actually have to provide a bit more information. 

Event aggregation is the ability of a framework to automatically collect up (or aggregate) event information and wire publishers to subscribers.  The OpenNETCF.IoC framework, which Project Resistance is using for Dependency Injection and as well as the UI framework, also provides Event Aggregation through simple Attributes.  Let's look at this key-handling as an example.

In the normal old-school event handling way of thinking, if the ResistorController wanted to get events when a KeyDown happened on the Form, the controller would need a reference to the Form so it could do a form.KeyDown += new KeyEventHandler(Foo).  The problem with this is that to do this, the Controller now has to know about the Form, meaning that they get coupled together.  That's bad from a maintenance and extensibilty standpoint, and it really sucks from a test standpoint.

Sure, I could interface the Form and then pass an interface reference in, but still, why does the Controller need to know anything about the Form?  Really it just wants to know when some other component wants to change the currently selected band or change the value of the selected band.

Well this is a classic case of where Event Aggregation rocks.  In the OpenNETCF.IoC framework, we simply need to know the string name of the event (which is stored in a global constant so everyone can use it).

The Form "publishes" the event with a simple attribute like this:

[EventPublication(EventNames.DPadEvent)]
public event KeyEventHandler DPadKeyPressed;

The anything that wants to receive the event simply uses an attribute to subscribe.  This is what it looks like in the ResistorController:

[EventSubscription(EventNames.DPadEvent, ThreadOption.Caller)]
public void DPadHandler(object sender, KeyEventArgs e)
{
...
}

By the nature of the fact that these objects were inserted into one of the IoC framework's DI container collections, the two automagigically get paired up.  No references get passed around, no interfaces get unnecessarily polluted, and out objects stay nicely decoupled.  All that is required is that both attributes use the same string name for the event and that the handler method signature matches the expected publisher's delegate.



Managed Code in the Embedded World

posted @ Fri, 30 Oct 2009 14:51:57 GMT by Chris
tags: OpenNETCF,Project Resistance

Project Resistance: Form Painting and Comments on the Studio Designer

I didn't do much today with Project Resistance, but that didn't stop progress. Alex got all of the background paionting ironed out today while I was screwing around with paying work.  It looks pretty nice (well, except for the lower workspace, which is awaiting artwork):

I did do some thinking on the broader process of developing WinMo apps, though.  One thing that most Windows developers (as well as a great many devs for other OSes) have come to rely on is the good old WYSIWYG editor for Form/Screen/View layouts.  Generally speaking, they've been around for a good while now and not counting that major backslide called Visual InterDev, they've done a pretty good job of presenting a design time what you see at runtime.

Well for everything except Smart Device projects.  We at OpenNETCF have been building controls and libraries for devices since before we were a company.  We've seen all the iterations of Microsoft's tools (all the way back to the add-in for VB 6 in fact). Never has designing a Form in the tool been easy once you go past the basic Label, Textbox and Button UI.

Since Studio '03, to get any form of custom control to render properly you had to do a whole load of extra work.  And to make matters worse, how you had to do it seems to have changed with every new release of Studio, meaning you have to re-do a lot of the work for existing controls to get the new tools to support them.  I think this is one of the reasons there are so few 3rd-party vendors doing nice controls (especially with any sort of designer support).  To make thigs even worse, trying to support just the current tool runs into bugs almost immediately.

So what do those of use who build these apps day-in and day-out do?  Well we live with a rectangle, or a series of them, in the designer and do all of the actual layout by iterating with a device or the emulator.  So the run-time view you see above looks like this in the designer:

Fancy, eh?  And what, you ask, is the upper "DeckWorkspace"?  Well it's a container object from the OpenNETCF.IoC framework.  It basically holds a UserControl, which is what that resistor image is.  It, similarly, gives you very little as design time:

Yes, this is the state-of-the-art.  If you're coming to device development from the desktop, be prepared to be a bit frustrated.  Could we have added designer support for the resistor to this project?  Sure.  But I bet it would take more than twice the time we have already into the entire project just to get it to render, and even then it would come with caveats (like it would work with CF 3.5 but not 2.0 projects or similar silliness).

So the moral of the story is that you just get used to it.  Unless you plan to be a control vendor don't bother wasting your time even trying to get designer support working.  You'll only end up frustrated, behind schedule, and with a load of convoluted code that you'll have to rewrite the next time Microsoft releases a new version of Studio.  Maybe things will change in VS10, but based on the track record I seriously doubt it.

Don't take all of this as being completely down on Studio though.  As far as a development tool it's still the best thing out there (well it's not so great for C++, but that's another diatribe - just do yourself a favor and get SourceInsight for that).  I've used a lot of tools, and Studio, by far, is the most stable and feature-rich tool that I've ever used.  It's just that there's still a lot of room for improvement.



Managed Code in the Embedded World

posted @ Thu, 29 Oct 2009 21:41:22 GMT by Chris
tags: OpenNETCF,Project Resistance

Project Resistance, Day 4: graphic fixes and more gesturing

We've made more today progress on Project Resistance.  It turns out that the earlier bug was indeed due to the fact that in the Compact Framework Color.Transparent is not a transparent color.  How intuitive.  If you do Graphics.Clear(Color.Transparent) what actually occurs is that the underlying bitmap gets filled with white.  We (and by "we" I mean "Alex") had to create some utility functions to directly manipulate the HDC and do actual transparency. 

Again, it's more than a little awkward, and how Microsoft might expect the vast majority of developers out there to get this right I'm not sure.  Even if everyone could write this code, I still think they shouldn't have to.  We should be focused on solving our business problems, not solving platform problems.

At any rate, we got a fix into the code, and I added gesturing support for the resistance bands in the ResistorView as well.

 

You can see that the background is not right, but that's an offset math issue (again due to the inability to draw transparent controls on a Form) that should be simple to fix.  Yes, the View for the numeric data at the bottom is hideous, but right now it's simply there to ensure that events get properly wired from the view above, down to the controller and back out.  Making it look good will require work from the graphic designer.

As a side note, Alex seems to be having some difficulties using SVN as a CodePlex client and that's why the fix took so long to get published.  I'm not having any problems with the TFS client.



Managed Code in the Embedded World

posted @ Wed, 28 Oct 2009 13:59:50 GMT by Chris
tags: OpenNETCF,Project Resistance

Project Resistance: iPhone Edition

Today has been a slow day here for Project Resistance because I'm neck deep in writing other code.  I did manage to get the gesture events for the Tolernace band on the ResistorView plumbed in so now you can swipe up/down with your finger and it actually changes the band color (though I noticed I need to fix a couple images) and it updates a second View with a text representation of the tolerance. Right now that view looks like an engineer created it, so no screen shot today - I'd rather not embarass myself.

On another, more fun note, fellow MVP and iPhone development author Christopher Fairbairn has started an iPhone port of Project Resistance.  He's also started blogging about his project.  Looking at his posts and how easy a time he's having so far makes me almost jealous.  If it weren't for the facts that you have to subject your eyes to the abomination known as Objective-C and you have to work on a Mac I just might be.  It should be interesting to see how the two projects track toward getting a product to market.  So far we're both just barely out of the gate.



Managed Code in the Embedded World

posted @ Tue, 27 Oct 2009 18:35:35 GMT by Chris
tags: OpenNETCF,Project Resistance

HOWTO: Determine whether or not a library exports a function

Back in May 2008, I wrote a blog post about checking for Win32 methods. I was recently reminded of this when a customer emailed us about a scenario that exactly matched the intended use case.

The customer was using the Smart Device Framework with a Windows CE 5.0 device and was receiving a MissingMethodException "Can't find an Entry Point 'xxx' in a PInvoke DLL 'yyy'". The exception message is detailed enough to explain the situation -- since Windows CE is modular, whoever created the OS image had not added a required component, resulting in the native functions to be missing from coredll.dll. This is not an uncommon scenario in the Windows CE world.

Below is an example of how you can gracefully handle calling the PlaySound function from coredll.dll even on devices that don't support the function. The important part is the call to Device.Win32Library("coredll").HasMethod("PlaySound"). This is return false if coredll.dll does not exist or if coredll.dll does not export the PlaySound function. Of course, you could raise a PlatformNotSupportedException or try another mechanism for playing the sound file instead of just returning without calling the native PlaySound function. The important point is that you should code in a way that can handle scenarios where the native function is not available and adapt accordingly.

Imports System.Runtime.InteropServices
Imports OpenNETCF.Reflection

Partial Public Class MainForm
  Friend Class NativeMethods
    Private Const SND_ASYNC As Integer = &H1
    Private Const SND_FILENAME As Integer = &H20000

    Public Shared Sub SafelyPlaySound(ByVal soundFile As String)
      If Not Device.Win32Library("coredll").HasMethod("PlaySound") Then
        Exit Sub ' Function is not exported so we silently return
      End If

      ' Coredll exists and the PlaySound function has been exported
      ' so we can safely make the P/Invoke call
      PlaySound(soundFile, IntPtr.Zero, SND_ASYNC And SND_FILENAME)
    End Sub

     _
    Private Shared Function PlaySound(ByVal szSound As String, _
                                      ByVal hMod As IntPtr, _
                                      ByVal flags As Integer) As Integer
    End Function

  End Class
End Class

posted @ Mon, 20 Apr 2009 10:30:52 GMT by Neil
tags: .NET Compact Framework

Get Padarn for free!

Last week we quietly launched a fantastic new promotion for our Padarn Web Server product:

Padarn is a lightweight, single-purpose web server that supports a growing subset of ASP.NET. It is written entirely in C# and can be used as stand-alone web server, or embedded into an existing application. Padarn can be used to create elegant, data-driven web sites using SQL Server Compact Edition, or interface with a whole myriad of hardware peripherals, such as web cams, sensors, controllers, etc.

If you would like more information on Padarn, please send an email to padarn@opennetcf.com.

posted @ Mon, 20 Apr 2009 07:42:42 GMT by Neil
tags: .NET Compact Framework

HOWTO: Build the Smart Device Framework source code

Note: This blog post only applies to Smart Device Framework Standard or Professional Edition customers.
>

If you open the SDF Public Source solution that ships with Smart Device Framework 2.3 and then build the source, you'll come across the following error:

Friend access was granted to 'OpenNETCF,PublicKey=...', but the output assembly is 
named 'OpenNETCF, Version=2.3.0.21, Culture=neutral, PublicKeyToken=null'. Try 
adding a reference to 'OpenNETCF,PublicKey=...' or changing the output assembly name 
to match.

(Note that I've replaced the actual public key with ellipses in the above. You will see an extraordinarily long hexadecimal number in your errors list in Visual Studio.)

The easiest way to remedy this is through a quick search & replace. Hit Ctrl-H to bring up the Find & Replace window. In the Find what text box, enter the following:

,PublicKey=00240000048000009400000006020000002400005253413100040000010001002beeba3
bfe7c548e085cffb8c2b6fd61ddd02b06d70864bb7de8bb22473edf5ab4b2196ff98e232c3e87f11fd
7986b743d5d3fdd6ecaf624bacfed116e1cefa50cd652365371d0ebd2702eb1084fed46df79ac0f59f4
d66c547918613d56dcf106843f3458516d3cd26f057a346d9f645fc24a7410a095c754835916e13cdbe

Make sure the Replace with text box is empty and the Look in combobox is showing Entire Solution. Click the Replace All button. When the search & replace has completed, build the solution again and it will succeed.

If you wish to do this manually (you may only want to use 1 or 2 of the 16 projects), you will need to modify the AssemblyInfo.cs file for the following projects:

  • OpenNETCF
  • OpenNETCF.Configuration
  • OpenNETCF.Net
  • OpenNETCF.Windows.Forms
>

posted @ Fri, 06 Mar 2009 05:19:08 GMT by Neil
tags: HOWTO

ANN: Smart Device Framework 2.3

Today, we released Smart Device Framework 2.3. This is the long awaited release of the Smart Device Framework for Visual Studio 2008.

It's been a painful path to get to this point, what with contending with frustrating bugs in Visual Studio 2008 forms designer and all, but we finally got there. Thanks for you patience and understanding.

Along with the new version is a new naming convention. We've dropped the name Smart Device Framework Extensions for Visual Studio with its Standard and Premium editions. Instead, say hello to Smart Device Framework Standard Edition and Professional Edition. Be sure to check out the new feature matrix to find out how each edition differs.

We've got some pretty cool stuff features in the libraries, notably OpenNETCF.Core which contains a dozen or so extension methods for common scenarios, as well as OpenNETCF.Net.Mail, for sending mail via SMTP directly from the device -- this eliminates the need to configure a mail account on the device.

posted @ Wed, 26 Nov 2008 11:09:47 GMT by Neil
tags: .NET Compact Framework

HOWTO: Prevent ResolveAssemblyReferences warnings in Visual Studio 2008

When you reference an assembly compiled against .NET Compact Framework 2.0 in a project targeting .NET Compact Framework, it's quite likely you will receive a number of ResolveAssemblyReferences warnings, similar to this:

ResolveAssemblyReferences:
  Consider app.config remapping of assembly "System.Windows.Forms, Culture=neutral, 
  PublicKeyToken=969db8053d3322ac, Retargetable=Yes" from Version "2.0.0.0" [] to 
  Version "3.5.0.0" [C:\Program Files\Microsoft.NET\SDK\CompactFramework\v3.5\
  WindowsCE\System.Windows.Forms.dll] to solve conflict and get rid of warning.

This warning occurs when the compiler has loaded the .NET Compact Framework 3.5 base class libraries (BCLs) and the referenced assembly, but the metadata contained in the referenced assembly references the .NET Compact Framework 2.0 BCLs.

To remove the warnings you can add an App.Config to your project and redirect the assembly bindings from the 2.0 versions to the 3.5 equivalents. Below is an example of the XML required in the App.Config to redirect the 2.0 version of System.dll to the 3.5 version.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentassembly>
        <assemblyidentity name="System" culture="neutral" publickeytoken="969db8053d3322ac" />
        <bindingredirect  newVersion="3.5.0.0" oldVersion="2.0.0.0" />
      </dependentassembly>
    </assemblybinding>
  </runtime>
</configuration>

You will need to add a dependentassembly element for each of the ResolveAssemblyReferences warnings that you receive.

Make sure the Build Action property of the App.Config is set to Content and the Copy To Output Directory property is set to Only if newer. Then, rebuild your solution and the warnings should not appear.

posted @ Tue, 12 Aug 2008 10:09:06 GMT by Neil
tags: .NET Compact Framework

Lambda expressions in .NET Compact Framework 2.0

There's been a lot of internal discussion today on how to leverage C# 3.0 features without requiring .NET Compact Framework 3.5. Mark has the low down on using extension methods with a little compiler misdirection hack.

The discussions kicked off because I discovered that you can use lambda expressions with .NET Compact Framework 2.0 projects in Visual Studio 2008. I even twittered about it yesterday. (Note: it didn't take me too long to realize it's not a bug, but due to Visual Studio 2008 using the C# 3.0 compiler.) Code like the following just works -- no hacks required:

delegate double PowerOf(double x, double y);

static void Main() 
{
    PowerOf pwr = (x, y) => Math.Pow(x, y);
    double result = pwr(2, 3);
}

If you are using Visual Studio 2008 and still need to target .NET Compact Framework 2.0, the little things like this go a long way to creating and maintaining reusable code.

posted @ Wed, 23 Jul 2008 11:13:23 GMT by Neil
tags: .NET Compact Framework

OpenNETCF is now a Microsoft Gold Partner

Over the last few months we've been working hard to attain the Gold Level partner status in the Microsoft Partner Program and I'm extremely pleased to say that we've done it! For our customers, this is an assurance that by choosing to work with OpenNETCF products and our consultants, you really are choosing a high calibre company.

Massive amounts of credit for Mark for driving this internally. Good job!

posted @ Wed, 16 Jul 2008 05:04:10 GMT by Neil
tags: General

Mark your calendars - Smart Device Development Chat, July 16.

The next Smart Device Development Chat will take place on MSDN at 10am PST on Wednesday, July 16.

Please join experts from the Windows Mobile, Windows CE, SQL Server CE and .NET Compact Framework communities in a chat around application development for smart devices. These chats are a great opportunity to have your questions answered by experts from around the world.

Add to Calendar

If you cannot attend the MSDN Chat, there is a permanent chat room available on the web and via IRC (irc://irc.freenode.net/mobiledev). Engage with your peers online today!

posted @ Fri, 11 Jul 2008 05:05:14 GMT by Neil
tags: Mobility/Embedded

Chat Transcript: May 13, 2008 - Smart Device Development Chat

A little later than I intended, but here is the transcript to Smart Device Development chat from May 13, 2008: Read it here

posted @ Mon, 16 Jun 2008 11:41:58 GMT by Neil
tags: Mobility/Embedded

Book: Professional Microsoft Embedded CE 6.0

I was browsing around over lunch when I came across an upcoming title from Wrox that I thought might be interesting to someone out there.

The book, being writing by Samuel Phung of ICOP, is titled Professional Microsoft Embedded CE 6.0. A book like this is sorely needed as most of the knowledge exists primarily in the embedded newsgroup or scattered around in a handful of blogs.

The 20-chapter book will cover everything from creating an image to development in C# and VB.NET, as well as C++ and is scheduled to be released in November. Wrox have made a number of chapters available through their Wrox First subscription service.

posted @ Fri, 06 Jun 2008 09:03:39 GMT by Neil
tags: Books

 

© 2009 OpenNETCF Consulting, LLC
OpenNETCF Consulting is available for Windows Mobile and Windows CE projects, strategy, and training. Email dcs@opennetcf.com today.