February 2007 - Posts

Do not use timers that prevent power state changes

Ran into an interesting FXCop rule today: Do not use timers that prevent power state changes.  According to the rule description:

Do not poll more often than once per second or use timers that occur more frequently than once per second. Higher frequency periodic activity will keep the CPU busy and interfere with power-saving idle timers that turn off the display and hard disks.

Very interesting.

Posted by PSteele | with no comments

Reflector 5.0 is out.

Just saw this on Jason Bock's blog.  Lutz Roeder has released version 5.0 of Reflector.  And getting it is so easy: Just launch your current version of Reflector (I assume you already have it!), go to the Help menu and select "Check for Updates".  It will download, install and re-start!

UPDATE: Check out Scott Hanselman's annoucement with a bunch of tips to get the most out of Reflector -- although I think world domination is a bit of a stretch!  :)

Posted by PSteele | with no comments

Feeling queasy about lambdas?

If the new C# 3.0 "=> operator makes you feel uneasy, check out Dustin Campbell's post where he gently introduces you to lambdas by taking a simple C# 2.0 algorithm using anonymous methods and converts it to lambdas in C# 3.0.

Posted by PSteele | with no comments

Using the StrongNameIdentityPermissionAttribute

In a recent thread on the .NET newsgroups, someone asked how they could create a "utility" assembly, but they only wanted their applications to be able to use the assembly.  I couldn't think of a good way, but Dave Sexton replied with an interesting little gem on the StrongNameIdentityPermissionAttribute.  After reading his response I made myself a little "to do" item to implement his idea and post some sample code.

Today, I came across a blog post from Morgan Skinner that explained the process and showed an example.  Very cool!

Posted by PSteele | 1 comment(s)

Day of .NET in Ann Arbor, MI - 2007

This year's Day or .NET is scheduled for Saturday, April 28th 2007 at Washtenaw Community College in Ann Arbor, Michigan.  This all day event is organized by developers for developers.  The event is FREE ($0, no cost!) to all of those interested in .NET development!

We've got tracks for Smart Client, Web, "Data, Business Intelligence and Connected Systems" as well as General sessions.  If you're interested in speaking, please see the official website for details.

Posted by PSteele | with no comments

A Generics Command Pattern Implementation

At this weeks GANG meeting, Martin Shoemaker will be presenting "Do, Undo, Redo, Do Over: A Generics Command Pattern Implementation".  He's going to use generics to build simple yet powerful implementation of the Command Pattern.  You won't want to miss this if you're in the area.

And please note that we've changed times!  Our meetings now start at 6:30pm (30 minutes later).  This gives everyone a little more time to avoid the rush hour traffic and also allows us to start eating pizza at the beginning of the meeting.  And remember, that's FREE pizza!

Posted by PSteele | with no comments

COM Interop does NOT like uninitialized arrays!

I've created a simple reproduction case highlighting a problem I recently had with COM interop.  I've got a VB6 app using a .NET 2.0 component exposed to COM.  The component in this sample is pretty simple:

using System;
using System.Runtime.InteropServices;

namespace DotNetLibrary
{
    [Guid("FF7E820A-9F60-4B4C-BE17-93704377A65F")]
    public interface IClass1
    {
        [DispId(0x60030011)]
        int TheMethod(
            [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
            ref string[] Parameters);
    }

    [Guid("FFA1B994-66A3-4715-91C9-91468961ADB2")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Class1 : IClass1  
    {
        public int TheMethod(
            [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
            ref string[] Parameters)
        {
            return 0;
        }
    }
}

This assembly is strong-named.  I use REGASM with the /codebase switch and generate a type library with the /tlb switch.  Here's the sample VB6 code that highlights the problem (the VB6 project has a reference to the generated type library).  NOTE: If you're going to test this, make sure you save your project before running since this sample blows up VB6.EXE...   ;)

Dim lateObj As Object
Dim earlyObj As DotNetLibrary.Class1

Dim parameters() As String

Set lateObj = CreateObject("DotNetLibrary.Class1")
Set earlyObj = CreateObject("DotNetLibrary.Class1")

Debug.Print earlyObj.TheMethod(parameters)
Debug.Print lateObj.TheMethod(parameters)

As you see I create two instance of the object.  One is early-bound, one is late-bound.  The first call (via the early-bound object) works fine.  The second (via the late-bound object) kills VB6.EXE (or kills the compiled application when run outside the VB6 IDE).  If I run the .NET component in debug mode inside VS.NET and set "VB6.EXE" as the startup project, the Managed Debugging Assistant pops up with a FatalExecutionEngineError:

-----------------
FatalExecutionEngineError was detected

Message: The runtime has encountered a fatal error. The address of the error was at 0x7a03d1be, on thread 0x1498. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
-----------------

Two things that don't make sense to me:

1) If I change the declaration of "parameters" in the VB6 code to include an upperbound (i.e. "Dim parameters(0) As String"), the code works in both early and late-bound.

2) #1 above leads me to believe it's something to do with null/non-null values -- but then why would it work when early-bound and not late-bound?

Has anyone ever seen anything like this before?  And why doesn't the framework catch this "bad interop" and handle it gracefully?

PS - The obvious solution of "always define an upperbound" isn't an option since there's already tons of code written (both by my client and other third parties) using the above style.  The .NET component is being developed to be binary-compatible with the old COM component so the VB6 client apps are not going to be recompiled.

Posted by PSteele | 2 comment(s)

Using Generics To See If A List Is Ordered.

I had some pretty simple code that checked if an array of integers was in ascending order.  I needed to check a second list to see if it was also in ascending order.  The only problem was that is was an array of doubles.  The logic is identical for both lists.  The only difference is the type of data acted on.  This is where generics shine!

I pulled the old code into its own static method and used generics so I could use it on any array of objects that are comparable (implement IComparable):

private static bool IsAscending<T>(T[] values) where T : IComparable
{
    for (int i = 0; i < values.Length - 1; i++)
    {
        if (values[i].CompareTo(values[i + 1]) > 0)
            return false;
    }

    return true;
}

Technorati tags: ,
Posted by PSteele | 9 comment(s)

Would Zune 2.0 pack a phone?

From CNET News:

Bloggers were agog about reports that Microsoft is planning a Zune phone, which could be ready in time for the 2007 holidays. CrunchGear quotes a tipster saying it would be a smart phone that works with the Zune marketplace, and would not run Windows Mobile.

Posted by PSteele | with no comments
More Posts