# Tuesday, October 06, 2009

When you hire a consultant you're not simply getting someone to sling code (if that's what you want, hire a contractor).  Sure we do that, but we bring along a lot of experience, and quite often a plethora of code libraries.  We tend to see a wide variety of applications and tend to build up wide repositories of knowledge.  For example we're just putting finishing touches on a C# wrapper for using the Anviz SM2000 fingerprint reader.  It's a low-cost OEM module that seems to perform pretty well.  So if you're building a custom Windows CE (now Windows Embedded Compact to be true to Microsoft's marketing engine) device where you need fingerprint authentication, we could have you enrolling and authenticating fingerprints from a managed application very, very quickly instead of you spending a week or more trying to build up code from a not-so-clear spec document.

Tuesday, October 06, 2009 9:34:25 AM (Central Daylight Time, UTC-05:00)  #     | 
# Friday, October 02, 2009

Very often we here at OpenNETCF work on projects that are internal to companies that is seen by relatively few people or we do infrastructure work that helps an app succeed, but it isn't the app itself. Sometimes, though, we do get an opportunity to write public, commercial applications.  We've just finished version 1 of Trapster for Windows Mobile, which chould hit the Windows Marketplace this month.  For more info on what Trapster is and how it works visit their website, or read one of their reviews such as that on PocketNow or CNET.

The pieces of note here are that we used the OpenNETCF IoC Framework for dependency injection and the Bing Maps web services for all of the mapping and navigation work.

Friday, October 02, 2009 7:58:57 AM (Central Daylight Time, UTC-05:00)  #     | 
# Monday, August 31, 2009

Today I came back to a project that I hadn't worked on in a few months.  I got latest from source control and tried to build, and the linker complained "Error 1 fatal error LNK1104: cannot open file 'secchk.lib' AudioControl AudioControl".

Now WTF?  I knew this was working before.  The error remindinded me vaguely of a previous problem I had, so I searched my blog and found this one.  The problem that time was that I was building for PPC03 and the project for some reason had not added secchk.lib to my platform.  THis time, however, I am building for a generic Windows CE device, and for some reason it *is* adding it.  Well CE doesn't have this lib, and I don't want it.  A quick scan through the project settings didn't turn up anything obvious, so I went with the more heavy-handed approach of adding the following to a common header file:

#pragma comment(linker, "/nodefaultlib:secchk.lib")
#pragma comment(linker, "/nodefaultlib:ccrtrtti.lib")

Done and done.  (the second is required because when you add the first and rebuild, the linker will then complain about not finding ccrtrtti.lib). No idea why I get the error (I'd love to know the root cause) but I don't have time to dig around.  Fortunately the #pragma directive overrides whatever project settings you have, which can be handy at times.

Monday, August 31, 2009 9:11:28 PM (Central Daylight Time, UTC-05:00)  #     | 
# Wednesday, August 26, 2009

I've pushed another ode update for the OpenNETCF IoC Framework into Codeplex.  Highlights in this one are the fact that I've added a WorkItems collection to the WorkItem class, meaning there's now the potential for parent/child relationships.

Wednesday, August 26, 2009 8:11:29 PM (Central Daylight Time, UTC-05:00)  #     | 
# Friday, August 14, 2009

Consider the following code:

public class MyAttribute : Attribute
{
  public MyAttribute(UnmanagedType foo)
  {
  }

  public int Bar { get; set; }
}

[StructLayout(LayoutKind.Sequential)]
public struct Test
{
  [CLSCompliant(false)]
  [MyAttribute(UnmanagedType.ByValArray, Bar = 4)]
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  public ushort[] ArrayShorts;
}

class Program
{
  static void Main(string[] args)
  {
    FieldInfo field_info = typeof(Test).GetField("ArrayShorts");
    object[] custom_attributes = field_info.GetCustomAttributes(typeof(MarshalAsAttribute), false);
    Debug.WriteLine("Attributes: " + custom_attributes.Length.ToString());
    custom_attributes = field_info.GetCustomAttributes(typeof(MyAttribute), false);
    Debug.WriteLine("Attributes: " + custom_attributes.Length.ToString());
    custom_attributes = field_info.GetCustomAttributes(typeof(CLSCompliantAttribute), false);
    Debug.WriteLine("Attributes: " + custom_attributes.Length.ToString());
  }
}

The code defines a custom attribute, then defices a struct that uses that attribute, along with some BCL-provided attributes.  It then uses reflection to get back those attributes. What would you expect the output to be?  Probably this:

Attributes: 1

Attributes: 1

Attributes: 1


And if you run it against the full framework, that's exactly what you get.  But if you run it against the Compact framework, you instead get this:

Attributes: 0

Attributes: 1

Attributes: 1

Yes, you're seeing it correctly, the MarshalAsAttribute doesn't show up.  So immediately I call this a bug since the frameworks differ and there is no documentation that says they should (even if it were documented I'd call it a bug).  So I did a little asking around and a little research.  It turns out that there is a difference between MarshalAs and the other attributes.  According to the ECMA-335 spec for the Common Language Interface, section 21.2

There are two kinds of custom attributes, called genuine custom attributes, and pseudo custom attributes.

Custom attributes and pseudo custom attributes are treated differently, at the time they are defined, as follows:

  • A custom attribute is stored directly into the metadata; the‘blob’ which holds its defining data is stored as-is. That ‘blob’ can be retrieved later.
  • A pseudo custom attribute is recognized because its name is one of a short list. Rather than store its ‘blob’ directly in metadata, that ‘blob’ is parsed, and the information it contains is used to set bits and/or fields within metadata tables. The ‘blob’ is then discarded; it cannot be retrieved later.

The spec goes on to say that the MarshalAsAttribute is a pseudo custom attribute, so it would fall into the second bullet above.  If you re-read the last sentence in that bullet  you'll see that "it cannot be retrieved later."  So, in fact, it seems like the full framework is the one in error here, at least per the spec! This attribute should not be readable at all at run time.

Now why the authors of the spec would have made such a strange exception is beyond me.  THe method in the language is clearly called GetCustomattributes, not "GetOnlySomeCustomAttributes" and this is the first I've even heard of pseudo cutom attributes, which tells me it's not well documented and likely not well known.  So while the Compact Framework follows the spec to the letter, if you go with reasonable expectations as a guideline, I'm going to have to say that it's behavior is wrong and that the spec is incorrect and needs revising.

Friday, August 14, 2009 10:15:23 AM (Central Daylight Time, UTC-05:00)  #     |