Get-WindowsFeature Wow64*

While trying to download and install some Windows updates on a machine running Windows 2008 R2 Server Core, I got the following message and the updates failed.

This program can’t start because mscoree.dll is missing from your computer.

The updates in question are listed below.

  1. KB2468871 – Update for Microsoft .NET Framework 4 on Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008, Windows Server 2008 R2 for x64-based Systems

  2. KB2533523 – Update for Microsoft .NET Framework 4 on Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008, Windows Server 2008 R2 for x64-based Systems

  3. KB2539636 – Security Update for Microsoft .NET Framework 4 on Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008, Windows Server 2008 R2 for x64-based Systems

I couldn’t find anything on Google that was relevant so I started poking around in the Windows system directories, .NET Framework directories, and the registry to see what was going on.

The machine itself is running the x64 flavor of Windows, but apparently I did not install the WoW64 support for .NET and PowerShell.

A quick check at a PowerShell prompt confirmed this.

PS> Get-WindowsFeature Wow64*

Display Name                                            Name
------------                                            ----
[X] WoW64 Support                                       WoW64-Support
    [X] WoW64                                           WoW64-ServerCore
    [ ] WoW64 for .NET Framework 2.0 and Windows Pow... WoW64-NetFx2-Support
        [ ] WoW64 for .NET Framework 2.0                WoW64-NetFx2
        [ ] WoW64 for Windows PowerShell                WoW64-PowerShell
    [ ] WOW64 for .NET Framework 3.0 and 3.5            WoW64-NetFx3
    [ ] WoW64 for Print Services                        WoW64-PrintServices
    [ ] WoW64 for Input Method Editor                   WoW64-InputMethodEditor
    [ ] WoW64 for Subsystem for UNIX-based Applications WoW64-SUA

Once I installed those features (and restarted the server for good measure) all was well.

PS> Get-WindowsFeature Wow64-NetFx*,Wow64-PowerShell | Add-WindowsFeature
PS> Restart-Computer

Just putting this out there in the hopes that it helps someone else.

Sometimes it’s fun to do something that any self-respecting developer would cringe if they saw someone else do it. That’s kind of how I feel about abusing the capabilities of C# 4′s dynamic binding capabilities. Even though I stubbornly resisted the idea of adding dynamic binding to C#, I find myself playing around with it every now and then to make really ugly code look nicer.

For example, let’s consider the case where you’re matching a US telephone number (with optional extension) against a regular expression and separating the individual components into separate variables. In the US telecom industry it’s very common to deal with 10 digit numbers without having to worry about international phone formats, but the regular expression is still ugly. Unfortunately there’s nothing I can do about that, but this is about making code pretty, not making regular expressions pretty.

(?<npa>\d{3})-?(?<nxx>\d{3})\-?(?<line>\d{4})( x(?<ext>\d+))?

Let’s look at the implementation of such a task in PowerShell vs. C#.

Here is how the code would look in PowerShell. It’s elegance gets me sexually aroused.

if ('555-123-4567' -match $PhoneRegex) {
    $npa = $matches.npa
    $nxx = $matches.nxx
    $line = $matches.line
    $ext = $matches.ext
}

Here is how the equivalent code would look in C#.

var match = Regex.Match("555-123-4567", PhoneRegex);
if (match.Success) {
    string npa = match.Groups["npa"].Value;
    string nxx = match.Groups["nxx"].Value;
    string line = match.Groups["line"].Value;
    string ext = match.Groups["ext"].Success ?
                     match.Groups["ext"].Value :
                     null;
}

It’s not the end of the world, but it still feels like it could be so much more concise. Well with C# 4 I can create an object that derives from DynamicObject and wraps a System.Text.RegularExpressions.Match object to provide a much more “scripty” feel to the above code.

var match = DynamicRegex.Match("555-123-4567", PhoneRegex);
if (match) {
    string npa = match.npa;
    string nxx = match.nxx;
    string line = match.line;
    string ext = match.ext;
}

Note that a static method called DynamicRegex.Match is returning an object of type dynamic. The actual implementation is my wrapper class called DynamicMatch. It overrides the TryGetMember and TryConvert calls that make the above possible. It simply directs property and indexer calls into the Match.Groups collection and has some special logic for conversion to Boolean.

Anyhow, to get into detail about how C# does dynamic binding at runtime would take a series of posts in itself. I just thought this was a pretty interesting use of the dynamic binding that wasn’t yet another dynamic XML wrapper. Yeah I know it defeats the purpose of using a strongly-typed language like C# but oh well I thought it was interesting. Source is below.

public sealed class DynamicMatch : DynamicObject
{

    private readonly Regex _Regex;
    private readonly Match _Match;

    public DynamicMatch( Regex regex, Match match )
    {

        Contract.Requires( regex != null, "Regex cannot be null." );
        Contract.Requires( match != null, "Match cannot be null." );

        _Regex = regex;
        _Match = match;

    }

    public override IEnumerable GetDynamicMemberNames( )
    {
        // i honestly don't know where the hell this is used
        return _Regex.GetGroupNames( );
    }

    public override bool TryConvert( ConvertBinder binder, out object result )
    {

        // supports casting back to the original Match object
        if ( binder.Type == typeof( Match ) ) {
            result = _Match;
            return true;
        }

        // supports casting the match to its string representation
        // is the complete match result
        if ( binder.Type == typeof( String ) ) {
            if ( _Match.Success ) {
                result = _Match.Value;
                return true;
            }
            else {
                result = null;
                return true;
            }
        }

        // supports casting the match to a boolean indicating success
        if ( binder.Type == typeof( Boolean ) || binder.Type == typeof(Boolean?) ) {
            result = _Match.Success;
            return true;
        }

        return base.TryConvert( binder, out result );

    }

    public override bool TryGetIndex( GetIndexBinder binder, object[] indexes, out object result )
    {

        // supports 'match[x]' where x is a named capture group
        // or 'match[n]' where n is an implicit capture group index

        if ( indexes.Length == 1 ) {
            Group group = _Match.Groups[Convert.ToString( indexes[0] )];
            if ( group != null && group.Success ) {
                result = group.Value;
                return true;
            }
            else {
                result = null;
                return true;
            }
        }

        return base.TryGetIndex( binder, indexes, out result );

    }

    public override bool TryGetMember( GetMemberBinder binder, out object result )
    {

        // supports 'match.x' where x is a named capture group

        Group group = _Match.Groups[binder.Name];
        if ( group != null && group.Success ) {
            result = group.Value;
            return true;
        }
        else {
            result = null;
            return true;
        }

    }

    public override bool TryUnaryOperation( UnaryOperationBinder binder, out object result )
    {

        // supports 'if (match) {...}'
        if ( binder.Operation == ExpressionType.IsTrue ) {
            result = _Match.Success;
            return true;
        }

        // supports 'if (!match) {...}'
        if ( binder.Operation == ExpressionType.IsFalse || binder.Operation == ExpressionType.Not ) {
            result = !_Match.Success;
            return true;
        }

        return base.TryUnaryOperation( binder, out result );

    }

    public static bool operator ==( DynamicMatch x, bool y )
    {
        // supports 'if (match == true) {...}'
        return x._Match.Success == y;
    }

    public static bool operator !=( DynamicMatch x, bool y )
    {
        // supports 'if (match != true) {...}'
        return x._Match.Success != y;
    }

    public static bool operator ==( DynamicMatch x, string y )
    {
        // supports 'if (match == "foo") {...}'
        return x._Match.Value == y;
    }

    public static bool operator !=( DynamicMatch x, string y )
    {
        // supports 'if (match != "foo") {...}'
        return x._Match.Value != y;
    }

}

public static class DynamicRegex
{

    public static dynamic Match( string input, string pattern )
    {
        var regex = new Regex( pattern );
        var match = regex.Match( input );
        return new DynamicMatch( regex, match );
    }

}
[TestClass]
public class DynamicRegexTests
{

    [TestMethod]
    public void DynamicMatchConvertsToMatch( )
    {

        var dynamicMatch = DynamicRegex.Match( "Hello World", @"H[A-Za-z]+" );
        Match regularMatch = dynamicMatch;

        Assert.IsTrue( regularMatch.Success );
        Assert.AreEqual( "Hello", regularMatch.Value );

    }

    [TestMethod]
    public void SuccessfulMatchConvertsToTrue( )
    {

        var match = DynamicRegex.Match( "Hello World", @"H[A-Za-z]+" );

        // Convert To Boolean
        Assert.IsTrue( (bool)match, "Successful match should convert to true." );

        // Compare To Boolean
        if ( !match ) { Assert.Fail( "Successful match should convert to true." ); }
        if ( match == false ) { Assert.Fail( "Successful match should convert to true." ); }
        if ( match != true ) { Assert.Fail( "Successful match should convert to true." ); }

    }

    [TestMethod]
    public void UnsuccessfulMatchConvertsToFalse( )
    {

        var match = DynamicRegex.Match( "Hello World", @"^H[A-Za-z]+$" );

        // Convert To Boolean
        Assert.IsFalse( (bool)match, "Unsuccessful match should convert to false." );

        // Compare To Boolean
        if ( match ) { Assert.Fail( "Unsuccessful match should convert to false." ); }
        if ( match == true ) { Assert.Fail( "Unsuccessful match should convert to false." ); }
        if ( match != false ) { Assert.Fail( "Unsuccessful match should convert to false." ); }

    }

    [TestMethod]
    public void SuccessfulMatchConvertsToString( )
    {

        var match = DynamicRegex.Match( "Hello World", @"H[A-Za-z]+" );

        // Convert To String
        Assert.AreEqual( "Hello", (string)match, "Successful match should convert to Match.Value." );

        // Compare To String
        if ( match != "Hello" ) { Assert.Fail( "Successful match should convert to Match.Value." ); }

    }

    [TestMethod]
    public void UnsuccessfulMatchConvertsToNull( )
    {

        var match = DynamicRegex.Match( "Hello World", @"^H[A-Za-z]+$" );

        // Convert To String
        Assert.IsNull( (string)match, "Unsuccessful match should convert to null." );

        // The following will always fail - C# does the null check without converting
        // if (match != null) { Assert.Fail("..."); }

    }

    [TestMethod]
    public void SuccessfulCapturesAccessedAsProperties( )
    {

        var match = DynamicRegex.Match( "123-456-7890", @"(?\d{3})-?(?\d{3})-?(\d{4})" );

        Assert.AreEqual( "123", match.npa, "Capture group npa could not be accessed by name." );
        Assert.AreEqual( "456", match.nxx, "Capture group nxx could not be accessed by name." );

    }

    [TestMethod]
    public void SuccessfulCapturesAccessedAsIndexer( )
    {

        var match = DynamicRegex.Match( "123-456-7890", @"(?\d{3})-?(?\d{3})-?(\d{4})" );

        Assert.AreEqual( "123", match["npa"], "Capture group npa could not be accessed by name." );
        Assert.AreEqual( "456", match["nxx"], "Capture group nxx could not be accessed by name." );
        Assert.AreEqual( "7890", match[1], "Unnamed capture group could not be accessed by number." );
        Assert.AreEqual( "123-456-7890", match[0], "Capture group 0 should return entire match." );

    }

    [TestMethod]
    public void UnsuccessfulMatchReturnsPropertiesAsNull( )
    {

        // Must match 123-456-7890
        // Last 4 digits will cause unsuccessful match
        var match = DynamicRegex.Match( "123-456-XXXX", @"(?\d{3})-?(?\d{3})-?(\d{4})" );

        Assert.IsNull( match.npa, "Unsuccessful match must return all properties as null." );
        Assert.IsNull( match["npa"], "Unsuccessful match must return all properties as null." );
        Assert.IsNull( match["1"], "Unsuccessful match must return all properties as null." );
        Assert.IsNull( match["0"], "Unsuccessful match must return all properties as null." );

    }

    [TestMethod]
    public void SuccessfulMatchReturnsOptionalGroupAsNull( )
    {

        // Must match at least 123-456-
        // Last 4 digits are optional
        var match = DynamicRegex.Match( "123-456-XXXX", @"(?\d{3})-?(?\d{3})-?(\d{4})?" );

        Assert.AreEqual( "123", match["npa"], "Successful match should return captured groups as string." );
        Assert.AreEqual( "456", match["nxx"], "Successful match should return captured groups as string." );
        Assert.AreEqual( "123-456-", match[0], "Successful match should return entire match as string." );

        Assert.IsNull( match[1], "Successful match should return missing optional groups as null." );

    }

}

In the OData specification, the $format parameter can be passed on the query string of the request to tell the server that you would like the response to be serialized as JSON. Normally, to get JSON-formatted data, you have to specify "application/json" in your "Accept" header. The query string feature is handy in situations when it’s not easy or possible to modify the request headers.

Unfortunately, if you try to pass $format on a WCF Data Services query, you will get a response that looks like:

<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <code /> 
    <message xml:lang="en-US">
        The query parameter '$format' begins with a system-reserved 
        '$' character but is not recognized.
    </message> 
</error>

Unfortunately, WCF Data Services doesn’t support this OData convention. But with a little bit of trickery, you can make it work by modifying the request in an ASP.NET HTTP module.

The trick is to check for the query string parameter before the request gets to WCF Data Services and modify the request headers accordingly. Normally, the Request.Headers collection is read-only. You’ll need to use some simple reflection to make it writable but once you do, it’s just a matter of setting the appropriate Accept header, then rewriting the URL to remove the $format parameter so WCF Data Services doesn’t bitch and moan.

The entire HTTP module is shown below. Like it? Hate it? Let me know in the comments.

<!-- add to web.config -->
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="ODataFormatModule" type="YourNamespace.ODataFormatModule, YourAssembly" />
    </modules>
</system.webServer>
/// <summary>
/// Intercepts WCF Data Services requests that include a $format parameter on the query
/// string and alters the request headers according to the OData specification.
/// </summary>
public sealed class ODataFormatModule : IHttpModule
{

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="T:ODataFormatModule"/> class.
    /// </summary>
    public ODataFormatModule( )
    {
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the application instance.
    /// </summary>
    public HttpApplication Application
    {
        get;
        private set;
    }

    /// <summary>
    /// Gets the current HTTP context.
    /// </summary>
    public HttpContext Context
    {
        get
        {
            return HttpContext.Current;
        }
    }

    /// <summary>
    /// Gets the current request.
    /// </summary>
    public HttpRequest Request
    {
        get
        {
            return HttpContext.Current.Request;
        }
    }

    #endregion

    #region Methods

    /// <summary>
    /// Initializes a module and prepares it to handle requests.
    /// </summary>
    /// <param name="context">An <see cref="T:HttpApplication"/> that provides access to the methods, 
    /// properties, and events common to all application objects within an ASP.NET application</param>
    public void Init( HttpApplication context )
    {

        Application = context;
        Application.BeginRequest += Application_BeginRequest;

    }

    /// <summary>
    /// Disposes of the resources (other than memory) used by the module that implements
    /// <see cref="T:IHttpModule"/>.
    /// </summary>
    public void Dispose( )
    {
        Application.BeginRequest -= Application_BeginRequest;
        Application = null;
    }

    /// <summary>
    /// Forces the <see cref="T:NameValueCollection"/> to allow modifications by using reflection to
    /// set the IsReadOnly property to false.
    /// </summary>
    /// <param name="collection">The collection to make writable.</param>
    /// <returns>The original collection after the IsReadOnly property has been hacked.</returns>
    private static NameValueCollection MakeWritable( NameValueCollection collection )
    {

        var collectionType = collection.GetType( );
        var isReadOnlyProperty = collectionType.GetProperty(
            "IsReadOnly",
            BindingFlags.Instance |
            BindingFlags.IgnoreCase |
            BindingFlags.NonPublic
        );

        isReadOnlyProperty.SetValue( collection, false, null );

        return collection;

    }

    /// <summary>
    /// Gets a content type for the corresponding format parameter according to the OData specification
    /// http://www.odata.org/developers/protocols/uri-conventions#FormatSystemQueryOption
    /// </summary>
    /// <param name="format">The value of the $format querystring parameter.</param>
    /// <returns>The corresponding Accept request header value.</returns>
    private static string MapToMediaType( string format )
    {

        Contract.Requires( format != null );

        switch ( format.ToLowerInvariant() ) {
            case "atom":
            return "application/atom+xml";
            case "xml":
            return "application/xml";
            case "json":
            return "application/json";
            default:
            return format;
        }   // switch

    }

    #endregion

    #region Event Handlers

    /// <summary>
    /// Handles the BeginRequest event of the Application.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="T:EventArgs"/> instance containing the event data.</param>
    private void Application_BeginRequest( object sender, EventArgs e )
    {

        var format = Request.QueryString["$format"];

        if ( !String.IsNullOrWhiteSpace(format) ) {

            // Ordinarily, Request.Headers is read-only so we need to
            // use some reflection to get around that. Ugly, I know.
            var requestQuery = MakeWritable( Request.QueryString );
            var requestHeaders = MakeWritable( Request.Headers );

            // Set the Accept header the way a well-behaved json client
            // would have done, which WCF Data Services does support
            requestHeaders["Accept"] = MapToMediaType( format );

            // Use URL-rewriting to remove the $format part of the querystring
            // Otherwise, if it gets to WCF Data Services, it barfs
            requestQuery.Remove( "$format" );
            Context.RewritePath( Request.FilePath, Request.PathInfo, requestQuery.ToString( ) );

        }   // if

    }

    #endregion

}   // class
Apr 072010

Okay, I get the idea but come on… Talk about verbose errors. I guess it’s better than “Argument out of range.”

Custom tool warning: There was a validation error on a schema generated during export: Validation Error: Wildcard ‘##any’ allows element ‘Account’, and causes the content model to become ambiguous. A content model must be formed such that during validation of an element information item sequence, the particle contained directly, indirectly or implicitly therein with which to attempt to validate each item in the sequence in turn can be uniquely determined without examining the content or attributes of that item, and without any information about the items in the remainder of the sequence.

I wanted to post this last night but I did not have an internet connection.

The best part about being a developer is that when software drives you nuts, many times you can do something about it that mere mortals cannot. That’s the case with TweetDeck. I love it but I am sick of having to move windows around to keep it in view. I have a wide screen so I wanted to dedicate a band of space to it, much like how the Vista sidebar worked. When I maximize other windows, they should not obscure the taskbar or TweetDeck.

The title of this post is a little misleading for two reasons…

  1. PowerShell really has nothing to do with it. It’s just the method I chose to kick off this little hack. The actual implementation is all Win32 API via C#.
  2. TweetDeck is just the application that happened to drive me to write this. You could just as easily change one line to dock Windows Live Messenger instead.

So the code is shown below. It’s nearly all in C# but PowerShell will dynamically compile it when you run the script. No exe’s needed. Just run the script and…

  • TweetDeck’s caption and window border will be removed
  • It will be docked against the right hand side of your primary screen (hard coded, sorry)
  • Maximized windows will adjust to the new workspace size

A couple caveats though.

  • Resize TweetDeck to the size you want it before doing this
  • Once docked, there’s currently no way to undock. So just close it from the taskbar.
  • TweetDeck is buggy in "single column view" as many UI elements are cut off. It’s best to turn off "use narrow columns" first.

Code is below. Enjoy.

$DockProcessName = 'tweetdeck'

Add-Type -Language CSharpVersion3 @"
using System;
using System.Runtime.InteropServices;

public static class WindowDockUtil
{

    #region Public Methods

    /// <summary>
    /// Docks the window to the right side of the screen.
    /// </summary>
    /// <param name="hWnd">The window handle.</param>
    public static void Dock( IntPtr hWnd )
    {

        if ( hWnd == IntPtr.Zero ) {
            return;
        }   // if

        ulong windowLong = GetWindowLong( hWnd, GWL_STYLE );
        windowLong &= ~WS_BORDER;
        windowLong &= ~WS_CAPTION;
        windowLong &= ~WS_THICKFRAME;

        SetWindowLong( hWnd, GWL_STYLE, windowLong );

        var abd = new APPBARDATA( );
        abd.cbSize = Marshal.SizeOf( abd );
        abd.hWnd = hWnd;
        abd.uCallbackMessage = RegisterWindowMessage( "AppBarMessage" );

        // Create AppBar
        SHAppBarMessage( ABMsg.ABM_NEW, ref abd );

        // Get the Window's size
        RECT wc = new RECT( );
        if ( !GetWindowRect( hWnd, ref wc ) ) {
            return;
        }   // if

        int screenWidth = GetSystemMetrics( SM_CXSCREEN );
        int screenHeight = GetSystemMetrics( SM_CYSCREEN );
        int borderWidth = GetSystemMetrics( SM_CXSIZEFRAME );

        // Set the app bar to dock to the right
        abd.uEdge = ABEdge.ABE_RIGHT;
        abd.rc.top = 0;
        abd.rc.bottom = screenHeight;
        abd.rc.right = screenWidth;
        abd.rc.left = abd.rc.right - ( wc.right - wc.left ) + ( borderWidth * 2 );

        // Set AppBar Size
        SHAppBarMessage( ABMsg.ABM_SETPOS, ref abd );

        // Move Window to New Position
        MoveWindow( abd.hWnd, abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, true );

    }

    ///// <summary>
    ///// Removes the window from the side of the screen.
    ///// </summary>
    ///// <param name="hWnd">The handle.</param>
    //public static void UndockWindow( IntPtr hWnd )
    //{

    //    if ( hWnd == IntPtr.Zero ) {
    //        return;
    //    }   // if

    //    var abd = new APPBARDATA( );
    //    abd.cbSize = Marshal.SizeOf( abd );
    //    abd.hWnd = hWnd;

    //    // Remove AppBar
    //    SHAppBarMessage( ABMsg.ABM_REMOVE, ref abd );

    //    // How should I store state between Dock and Undock?
    //    ulong windowLong = GetWindowLong( hWnd, GWL_STYLE );
    //    windowLong |= WS_BORDER;
    //    windowLong |= WS_CAPTION;

    //    SetWindowLong( hWnd, GWL_STYLE, windowLong );

    //}

    #endregion

    #region Interop

    #region AppBar

    [StructLayout( LayoutKind.Sequential )]
    private struct APPBARDATA
    {
        public int cbSize;
        public IntPtr hWnd;
        public int uCallbackMessage;
        public ABEdge uEdge;
        public RECT rc;
        public IntPtr lParam;
    }

    private enum ABMsg : int
    {
        ABM_NEW = 0,
        ABM_REMOVE = 1,
        ABM_QUERYPOS = 2,
        ABM_SETPOS = 3,
        ABM_GETSTATE = 4,
        ABM_GETTASKBARPOS = 5,
        ABM_ACTIVATE = 6,
        ABM_GETAUTOHIDEBAR = 7,
        ABM_SETAUTOHIDEBAR = 8,
        ABM_WINDOWPOSCHANGED = 9,
        ABM_SETSTATE = 10
    }

    private enum ABNotify : int
    {
        ABN_STATECHANGE = 0,
        ABN_POSCHANGED = 1,
        ABN_FULLSCREENAPP = 2,
        ABN_WINDOWARRANGE = 3
    }

    private enum ABEdge : int
    {
        ABE_LEFT = 0,
        ABE_TOP = 1,
        ABE_RIGHT = 2,
        ABE_BOTTOM = 3
    }

    [DllImport( "Shell32", CallingConvention = CallingConvention.StdCall )]
    private static extern uint SHAppBarMessage( ABMsg dwMessage, ref APPBARDATA pData );

    #endregion

    #region Window Management

    [DllImport( "User32" )]
    private static extern int RegisterWindowMessage( string msg );

    [DllImport( "User32" )]
    private static extern IntPtr FindWindow( string lpClassName, string lpWindowName );

    [DllImport( "User32" )]
    private static extern bool MoveWindow( IntPtr hWnd, int x, int y, int cx, int cy, bool repaint );

    [DllImport( "User32" )]
    private static extern bool GetWindowRect( IntPtr hWnd, ref RECT rect );

    [StructLayout( LayoutKind.Sequential )]
    private struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [DllImport( "User32" )]
    private static extern int GetSystemMetrics( int Index );

    private const int SM_CXSCREEN = 0;
    private const int SM_CYSCREEN = 1;
    private const int SM_CXSIZEFRAME = 32;

    #endregion

    #region GetWindowLong/SetWindowLong

    [DllImport( "User32", EntryPoint = "SetWindowLongPtr" )]
    private static extern ulong SetWindowLong64( IntPtr hWnd, int nIndex, ulong dwNewLong );

    [DllImport( "User32", EntryPoint = "GetWindowLongPtr" )]
    private static extern ulong GetWindowLong64( IntPtr hWnd, int nIndex );

    [DllImport( "User32", EntryPoint = "SetWindowLong" )]
    private static extern uint SetWindowLong32( IntPtr hWnd, int nIndex, uint dwNewLong );

    [DllImport( "User32", EntryPoint = "SetWindowLong" )]
    private static extern uint GetWindowLong32( IntPtr hWnd, int nIndex );

    private const int GWL_WNDPROC =    ( -4 );
    private const int GWL_HINSTANCE =  ( -6 );
    private const int GWL_HWNDPARENT = ( -8 );
    private const int GWL_STYLE =      ( -16 );
    private const int GWL_EXSTYLE =    ( -20 );
    private const int GWL_USERDATA =   ( -21 );
    private const int GWL_ID =         ( -12 );

    private static ulong GetWindowLong( IntPtr hWnd, int nIndex )
    {
        if ( IntPtr.Size == 4 ) {
            return GetWindowLong32( hWnd, nIndex );
        }   // if
        else if ( IntPtr.Size == 8 ) {
            return GetWindowLong64( hWnd, nIndex );
        }   // else if
        else {
            throw new NotSupportedException( "Unsupported platform." );
        }   // else
    }

    private static ulong SetWindowLong( IntPtr hWnd, int nIndex, ulong dwNewLong )
    {
        if ( IntPtr.Size == 4 ) {
            return SetWindowLong32( hWnd, nIndex, (uint)dwNewLong );
        }   // if
        else if ( IntPtr.Size == 8 ) {
            return SetWindowLong64( hWnd, nIndex, dwNewLong );
        }   // else if
        else {
            throw new NotSupportedException( "Unsupported platform." );
        }   // else
    }

    #endregion

    #region Window Styles

    private const ulong WS_OVERLAPPED = 0x0000;
    private const ulong WS_POPUP = 0x80000000;
    private const ulong WS_CHILD = 0x40000000;
    private const ulong WS_MINIMIZE = 0x20000000;
    private const ulong WS_VISIBLE = 0x10000000;
    private const ulong WS_DISABLED = 0x8000000;
    private const ulong WS_CLIPSIBLINGS = 0x4000000;
    private const ulong WS_CLIPCHILDREN = 0x2000000;
    private const ulong WS_MAXIMIZE = 0x1000000;
    private const ulong WS_BORDER = 0x800000;
    private const ulong WS_DLGFRAME = 0x400000;
    private const ulong WS_VSCROLL = 0x200000;
    private const ulong WS_HSCROLL = 0x100000;
    private const ulong WS_SYSMENU = 0x80000;
    private const ulong WS_THICKFRAME = 0x40000;
    private const ulong WS_GROUP = 0x20000;
    private const ulong WS_TABSTOP = 0x10000;
    private const ulong WS_MINIMIZEBOX = 0x20000;
    private const ulong WS_MAXIMIZEBOX = 0x10000;
    private const ulong WS_CAPTION = WS_BORDER | WS_DLGFRAME;
    private const ulong WS_TILED = WS_OVERLAPPED;
    private const ulong WS_ICONIC = WS_MINIMIZE;
    private const ulong WS_SIZEBOX = WS_THICKFRAME;
    private const ulong WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;
    private const ulong WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
    private const ulong WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU;
    private const ulong WS_CHILDWINDOW = WS_CHILD;

    #endregion

    #endregion

}   // class
"@

if ($DockProcess = Get-Process $DockProcessName -ea 0) {
   [WindowDockUtil]::Dock($DockProcess.MainWindowHandle)
}
else {
    Write-Warning "Cannot find the $DockProcessName process."
}

image

I recently blogged about a new method I noticed in .NET 4 on the Enum class. One of the great things about .NET 4 is that it is a new version of base class library too. In .NET 3.0 and 3.5 as we all know, the CLR and BCL was left at version 2.0 which meant there were practically no improvements to core system classes and such.

Well I just stumbled upon another welcome upgrade to a rusty old class. Path.Combine in .NET 4 takes a parameter array of parts.

// so code that used to look like this...
string documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filename =
    Path.Combine(documents,
        Path.Combine("Visual Studio 2008",
            Path.Combine("Projects", "My Project");

// now looks like this...
string documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filename = Path.Combine(documents, "Visual Studio 2008", "Projects", "MyProjects");

Shh… hear that? It’s the sound of a million developers ripping out their home-grown HasFlag, IsFlagSet, CheckFlag, etc helper methods. Just noticed that in .NET 4 System.Enum now has a built-in HasFlag method. As Forrest Gump would say “Lt. Dan says we don’t have to worry about enum flags no more. That’s good. One less thing.”

These ones are pretty simple in implementation but go a long way to cleaning up your code. In some cases, the slight performance overhead may not be acceptable but I haven’t run into any real-world problems with them. Check out the usage below.

int x = 3;

// is x either 1, 3, or 5?
if (x.In(1, 3, 5)) {
    // yes!
}

// is x between 1 and 5?
if (x.Between(1, 5)) {
    // yes!
}

The In method works with any kind of object and uses the default EqualityComparer<T> implementation for the type. But there are overloads that specify common types such as int, byte, long, etc. These overloads will perform much better than the generic overload. There is also an overload for String that takes a comparer so that you can specify case-insensitive matching as needed.

The Between method works on any type implementing IComparable. It also has overloads for commonly used types to get better performance than using the default IComparable implementation.

The code for both extension methods is shown below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Einstein
{

    /// <summary>
    /// Extension methods for <see cref="T:IComparable"/> types.
    /// </summary>
    public static class ComparableExtensions
    {

        #region Methods

        #region In

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <typeparam name="T">The type of the value to compare and the values in the set.</typeparam>
        /// <param name="value">The value.</param>
        /// <param name="comparer">The comparer to use.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In<T>( this T value, IEqualityComparer<T> comparer, params T[] set )
        {
            
            // Use default comparer
            if ( comparer == null ) {
                comparer = EqualityComparer<T>.Default;
            }   // if

            // Constant false
            if ( set.Length == 0 ) {
                return false;
            }   // if

            for ( int i = 0; i < set.Length; i++ ) {
                if ( comparer.Equals( value, set[i] ) ) {
                    return true;
                }   // if
            }   // for

            return false;

        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this byte value, params byte[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this short value, params short[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this int value, params int[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this long value, params long[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this string value, params string[] set )
        {
            return In<string>( value, StringComparer.OrdinalIgnoreCase, set );
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <typeparam name="T">The type of the value to compare and the values in the set.</typeparam>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In<T>( this T value, params T[] set )
        {
            return In<T>( value, EqualityComparer<T>.Default, set );
        }

        #endregion

        #region Between

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <typeparam name="T">The type of values to compare.</typeparam>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between<T>( this T value, T minValueInclusive, T maxValueInclusive ) where T : IComparable
        {

            ParameterValidation.ThrowIfNull( value, "value" );

            int o1 = value.CompareTo( minValueInclusive );
            int o2 = value.CompareTo( maxValueInclusive );

            return ( o1 >= 0 && o2 <= 0 ) || ( o1 <= 0 && o2 >= 0 );

        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this byte value, byte minValueInclusive, byte maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this short value, short minValueInclusive, short maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this int value, int minValueInclusive, int maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this long value, long minValueInclusive, long maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this decimal value, decimal minValueInclusive, decimal maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this float value, float minValueInclusive, float maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this double value, double minValueInclusive, double maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this DateTime value, DateTime minValueInclusive, DateTime maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and 
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this TimeSpan value, TimeSpan minValueInclusive, TimeSpan maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }
        
        #endregion

        #endregion

    }   // class

}   // namespace

There are all sorts of official ways of doing this implementing various IE hosting interfaces in order to handle the presentation of the UI. But if you’re trying to automate a web page and a pesky window.alert is blocking your progress, the following code will supress it for the current page.

/// <summary>
/// Handles the Navigated event of the browser control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="T:WebBrowserNavigatedEventArgs"/> instance containing the 
/// event data.</param>
private void browser_Navigated( object sender, WebBrowserNavigatedEventArgs e )
{

    if ( browser.Document != null ) {

        // kills messagebox functionality by disabling the "window.alert()" function
        object window = browser.Document.Window.DomWindow;
        if ( window != null ) {
            Type windowType = window.GetType();
            BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Instance;
            string[] args = { "window.alert=function() {};", "JScript" };
            windowType.InvokeMember( "[DispID=1165]", flags, null, window, args );
        }   // if

    }   // if

}

.NET 3.5 brought a bunch of great extension methods to the framework, most of which extended the IEnumerable<T> (or IQueryable<T>) interfaces implemented by just about every collection type. These include simple ones such as Where, OrderBy, FirstOrDefault, etc as well as more complex ones like Aggregate, GroupBy, etc. The Enumerable class really covers a lot of ground, but I’ve created a couple more that I use from time to time in my “Common” assembly.

The extension method I’m writing about today is called Batch. It allows you to take any input sequence (array, collection, iterator, etc.) and process it in batches of a specified size.

Many times you will have an input sequence that contains a lot of items but for various reasons, you can’t process the entire sequence at once (memory constraints, you want to update a console with progress, etc.) and processing one at a time is too slow.

Before, I used to write code that would look like this.

var batch = new List();

foreach (var item in sequence) {

    batch.Add(item);

    if (batch.Count == 100) {
        BulkInsert(batch);
        batch.Clear();
    }

}

This isn’t too bad but it’s a lot of ceremony and extension methods are all about turning globs like that into more readable, concise code. The method signature for the Batch method looks like the following.

/// <summary>
/// Enumerates a sequence in chunks, yielding batches of a certain size to the enumerator.
/// </summary>
/// <typeparam name="T">The type of item in the batch.</typeparam>
/// <param name="sequence">The sequence of items to be enumerated.</param>
/// <param name="batchSize">The maximum number of items to include in a batch.</param>
/// <returns>A sequence of arrays, with each array containing at most
/// <paramref name="batchSize"/> elements.</returns>
public static IEnumerable<T[]> Batch<T>( this IEnumerable<T> sequence, int batchSize )

As the summary suggests, it converts an input sequence into a sequence of arrays of a specified size. The last array in the sequence will have fewer items than the batch size if the input count is not evenly divisible by batchSize. Calling it is very simple. The first example can be rewritten as the following.

foreach (Record[] batch in sequence.Batch(100)) {
    BulkInsert(batch);
}

The complete code example is shown below.

/// <summary>
/// Enumerates a sequence in chunks, yielding batches of a certain size to the enumerator.
/// </summary>
/// <typeparam name="T">The type of item in the batch.</typeparam>
/// <param name="sequence">The sequence of items to be enumerated.</param>
/// <param name="batchSize">The maximum number of items to include in a batch.</param>
/// <returns>A sequence of arrays, with each array containing at most
/// <paramref name="batchSize"/> elements.</returns>
public static IEnumerable<T[]> Batch<T>( this IEnumerable<T> sequence, int batchSize )
{

    var batch = new List<T>( batchSize );

    foreach ( var item in sequence ) {

        batch.Add( item );

        // when we've accumulated enough in the
        // batch, send it out
        if ( batch.Count >= batchSize ) {
            yield return batch.ToArray( );
            batch.Clear( );
        }   // if

    }   // foreach

    // send out any leftovers
    if ( batch.Count > 0 ) {
        yield return batch.ToArray( );
        batch.Clear( );
    }   // if

}