# Friday, October 09, 2009

My first Ruby application recently went live a month or two back. I’ve been meaning to get some experience with Ruby for quite a while now, but it took a real project to actually get a chance to really do something with it. Of course, “real project” in this case is a project that just as easily could have been coded in static HTML :-).

The project turned out to building a website for Arkansas Pediatric Therapy, which is the company that my wife does speech therapy for. The initial requirements for the site were to just get some static content out there, but it still gave me an opportunity to use some Ruby to build the site.

Because the site really has no database needs of any kind yet, I ended up choosing to use Sinatra instead of Rails. For deployment, I used Heroku. I was also able to incorporate some basic integration with the Google Maps API. For my JavaScript framework, I used jQuery. For the web design, I ended up asking one of my coworkers, Tim Franklin, to help me out. His web design skill far exceed mine, so that was definitely the right choice.

So, basically, I took the initial requirements to build an easy static HTML site and ran! Was it overkill? I don’t think so – I ended up learning a lot and I don’t have duplication of HTML all over the place. It should be pretty easy to add dynamic content later if I wish to. It really didn’t take a lot more time either. (NOTE: I did use webgen at first to build a static HTML version of the site. If you really just want static content, I can definitely recommend using it to take advantage of templates.)

But… the post title is about IronRuby… did I use IronRuby for this site? Actually, I didn’t. I might’ve tried it, but I’m pretty sure that Heroku doesn’t support IronRuby currently. Maybe some future site can take advantage of IronRuby. What I want to do is share some of this cool Ruby knowledge with my predominantly .NET readership using IronRuby.

So, here are the steps you can take to build your first Sinatra application using IronRuby!

Downloading, Installing IronRuby, and Adding it Your Path

First, you’ll have to download IronRuby. At the time of this post, it looks like the most current version is 0.9.1 though I used 0.9.0 for the post. The release is just a ZIP file, so all you have to do is extract it and go. I would recommend extracting the zip to your C:\ drive (or root somewhere) as opposed to somewhere under Program Files. Why? Well, I initially dropped mine under Program Files and received an error when trying to install the sinatra gem. I ended up finding this post to fix it – the problem is that the one of the paths is too long (check out all the information about the infamous MAX_PATH constant).

You should have a directory that looks something like c:\ironruby-0.9.1 with the rest of the files underneath it. Next, you’ll need to add the bin directory to your path. For now, I’m just going to add it to my PowerShell profile instead of adding it for the entire system. Here’s all you have to do:

$env:path += ';C:\ironruby-0.9.0\bin'

Once this is done, the IronRuby commands should all be in scope. You can verify this by running “Get-Command ir*” which should return all of the commands under the IronRuby bin directory.

Installing the Sinatra Gem

.NET developers share code by sharing their assemblies. Ruby developers share code by using gems. If you wish to use a .NET library, you usually have to pull up a browser, download a zip file, extract it and then add a reference to the assembly. If you wish to use a gem, you use the gem command and ask it to install it for you. Like so:

gem install sinatra

Then, to actually “reference” the gem in your code, you just “require” the dependencies you have.

require 'rubygems'
require 'sinatra'

Of course, we’re using IronRuby, so the commands are slightly different.

igem install sinatra

If you wish to see all of the gems installed locally, just run:

igem list –local

After installing Sinatra, you should see at least the following gems installed:

igem list --local

NOTE: If you happen to be at work and are behind a proxy, you might have trouble with the gem install command. Ruby and RubyGems take the Unix/Linux approach to proxies. That is, they’re expecting you to have an environment variable set up named HTTP_PROXY. I have a PowerShell script that I run to initialize this for me, but it basically just does this (assuming you have populated the required PowerShell variables):

$env:http_proxy = "http://$username:$password@$proxy:$proxyPort"

I use the Get-Credential cmdlet so that I don’t have to hardcode my username and password anywhere.

Patching Sinatra to run with IronRuby First

Now… you’re not done with installing Sinatra yet. Sinatra doesn’t yet support IronRuby out of the box (as of sinatra 0.9.4 anyway). Check out the IronRuby documentation on patching Sinatra to get it to run under IronRuby. Basically, you can open the base.rb code file (mine was under C:\ironruby-0.9.0\lib\IronRuby\gems\1.8\gems\sinatra-0.9.4\lib\sinatra) and paste in the patched code. Comment on the post if you’re unsure how to read and apply a patch.

Your First Sinatra Application in IronRuby

Now, we’re ready to create the first IronRuby code file. Below is the code:

require 'rubygems'
require 'sinatra' 

get '/' do
  "My machine name is #{System::Environment::machine_name}"
end

Pretty easy, huh? I’ve already pointed out the require statements further up the post. The next three lines illustrate the magic and simplicity of sinatra (and of Ruby). Sinatra bills itself as a “DSL for quickly creating web applications in Ruby with minimal effort.”

What those lines say is, when the ‘/’ path (the root of the site) receives an HTTP GET, respond with the string “My machine name is” and then the evaluated machine name that sinatra is running on. Note that I’m using System.Environment.MachineName from the .NET Framework. Note also that I reference the MachineName property using machine_name instead. This illustrates IronRuby’s name mangling feature which maps CLR property and method names to use Ruby’s naming standards.

Running It!

To run your code in sinatra, you use the ir command (ir = IronRuby) against your Ruby source file. You should see something like the following when you run it:

ir .\myironrubyapp.rb

In case you missed it from the screenshot, sinatra outputs that it “has taken the stage on 4567 for development.” 4567 is the port that sinatra is listening on. This means you can browse to http://localhost:4567.

You should see something like the following when you browse to this address.

Sinatra Running!

So, there you go. Your first Sinatra app with IronRuby. If there is interest, I’ll share more about how you can use Sinatra including how to use ERB to have templates with Sinatra.

posted on Friday, October 09, 2009 9:41:10 AM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Tuesday, May 19, 2009

I’ve been attempting to learn NHibernate lately. One of the big draws for me was the ability to write unit tests that did hit a database, but an in-memory one. Ayende recently posted on how to use SQLite to get in-memory unit tests. His example assumed standard hbm mappings and configuration.

I was curious how hard it would be port his example over to Fluent NHibernate. Not surprisingly, it was quite easy actually!

Here’s the Blog entity I used, which is based on the usage I saw from Ayende’s post:

And here is the mapping:

As you can see, it is pretty straight forward so far. The next piece of code is the Fluent NHibernate implementation of Ayende’s InMemoryDatabaseTest.

There aren’t too many differences really. We’re using the same SchemaExport, but we do need to call ExposeConfiguration so that we can store off a reference to the Configuration to be used by the SchemaExport instance.

The final piece, the actual test itself, is identical to Ayende’s example, except that I’m using MbUnit instead of xUnit:

Nice and easy! I like it!

As you can also tell, I’m experimenting with using github’s gist feature. I’ve been using github to store off my dot files and other environment-related settings as well as my presentations, but the gist feature seems pretty nice.

posted on Tuesday, May 19, 2009 12:34:06 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, February 25, 2009

I couldn’t resist borrowing my title from Christopher Bennage’s post entitled “An Essential Tip for Working with XAML.” My “essential tip” is identical to what he has already shown for WPF (and Fabrice originally) – it just applies to Windows Forms instead of WPF :-)

I’ll mix it up some and show with pictures instead of text, though.

Step 1. Right click on a Form, UserControl, or Component and select “Open With…”

image

Step 2. Select “CSharp Editor” and click “Set as Default” - (note that this setting only applies to C# code, though you can perform the identical setup for VB.NET as well)

image

Step 3. Enjoy your delicious, hot meal of faster Visual Studio!

In case you missed it, the real benefit that you get from this setting is that double clicking a file in the Solution Explorer will now go directly to the code instead of defaulting to the designer view. If you want to get to the designer view, just right click and select “View Designer.”

Thanks again to Christopher and Fabrice who did the real work here!

posted on Wednesday, February 25, 2009 10:32:12 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, December 05, 2008

This post presents a problem that has been approached by others before, but I thought I’d offer yet another possible solution. But first, let’s introduce the problem!

In my experience, real world applications (aka NOT demos) don’t display data that was hard-coded in an application. For my part, the data is usually coming from some remote service or endpoint, so I’m either working with some proxy to a WCF, ASMX, or remoting endpoint. It seems that most WPF demos that showcase data-binding imagine a scenario where the data is readily available to the designer which allows them, at design-time, to see what the application might look like with real data loaded.

Check out the below screenshot of an amazing application that I created this morning.

image

As you can tell, I’m displaying a list of accounts by name and balance. The UI on this thing is unbelievable, too, because it also makes the balance red when their balance is below zero. Go WPF!

Seriously, though, I’ve tried to structure this like I might a real application. I’m a huge fan of the CompositeWPF library (*cough* Prism *cough*), so I’m using a Model-View-Presenter approach here, where the View is binding to a PresentationModel. You can see some examples of this in the StockTrader reference application that ships with CompositeWPF. The presenter’s only job is to hook up the data binding to the view and then load the PresentationModel up with data from the service. (Note that it would be very easy to add threading support here so that, while pulling data from IService, we don’t lock up the UI)

public class Presenter  
{  
    private readonly IView _view;  
    private readonly IService _service;  
    private readonly PresentationModel _presentationModel;  
  
    public Presenter(IView view, IService service, PresentationModel presentationModel)  
    {  
        _view = view;  
        _service = service;  
        _presentationModel = presentationModel;  
    }  
  
    public void Run()  
    {  
        _view.Model = _presentationModel;  
        LoadAccounts();  
    }  
  
    private void LoadAccounts()  
    {  
        foreach (var acct in _service.GetAccounts())  
            _presentationModel.Accounts.Add(acct);  
    }  
}

The PresentationModel only exposes an ObservableCollection of Accounts.

public class PresentationModel  
{  
    private readonly ObservableCollection<Account> _accounts = new ObservableCollection<Account>();  
    public ObservableCollection<Account> Accounts  
    {  
        get  
        {  
            return _accounts;  
        }  
    }  
}

The code for Window1.xaml is below.

<Window  
  x:Class="WpfApplication1.Window1"  
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  xmlns:local="clr-namespace:WpfApplication1"  
  Title="Window1"  
  Height="300"  
  Width="300">  
    
  <local:AccountDisplay  
    DataContext="{Binding}" />  
</Window>

I’m just tying the DataContext for my AccountDisplay UserControl to whatever Binding is set to the Window. This allows the data binding to just flow through the rest of the application. This is very flexible. But what about the code behind? It is pretty basic, too.

public partial class Window1 : Window, IView  
{  
    public Window1()  
    {  
        InitializeComponent();  
  
        var presenter = new Presenter(this, new RealService(), new PresentationModel());  
        presenter.Run();  
    }  
 
    #region IView Members  
  
    public object Model  
    {  
        get { return DataContext; }  
        set { DataContext = value; }  
    }  
 
    #endregion  
}

The sample isn’t using CompositeWPF, but if you’re familiar with it, you should realize that it would be very easy to plug it in. In fact, my example is screaming Inversion of Control because of the Dependency Injection that I’m already using with the Presenter. A conversion to using the CompositeWPF would start with replacing the local declaration of the AccountDisplay user control with a region and associated module and you’ll be well on your way.

The real display is in AccountDisplay. Here is its source:

<UserControl  
  x:Class="WpfApplication1.AccountDisplay"  
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  xmlns:local="clr-namespace:WpfApplication1"  
  Height="300"  
  Width="300">  
    
  <UserControl.Resources>  
    <local:BalanceToBrushConverter  
      x:Key="BalanceToBrushConverter" />  
  </UserControl.Resources>  
  
  <ItemsControl  
    ItemsSource="{Binding Path=Accounts}">  
  
    <ItemsControl.ItemTemplate>  
      <DataTemplate>  
  
        <StackPanel  
          Orientation="Horizontal">  
          <Border  
            CornerRadius="5"  
            Padding="5"  
            BorderBrush="Black"  
            BorderThickness="2">  
            <TextBlock  
              Text="{Binding Path=Name}" />  
          </Border>  
          <Border  
            CornerRadius="5"  
            Padding="5"  
            BorderBrush="Black"  
            BorderThickness="2">  
            <TextBlock  
              Foreground="{Binding Path=Balance, Converter={StaticResource BalanceToBrushConverter}}"  
              Text="{Binding Path=Balance}" />  
          </Border>  
        </StackPanel>  
      </DataTemplate>  
    </ItemsControl.ItemTemplate>  
  
  </ItemsControl>  
</UserControl>

Here, I’m just using relative binding (Binding Path=Property) here. This means I’ll pick up data binding from the DataContext, which was set back in Window1.xaml (once again, a result of that flowing data binding).

So, where’s the problem? Let’s look at this from the designer perspective by opening AccountDisplay.xaml in Blend.

image

It… it looks really great. So… white and everything. Anyone know what the problem is? My Presenter is the guy who does the work to return accounts to bind to, but Blend is just showing us the XAML. This is good – we don’t want the fact that we’re designing this to actually run our code and hit our services. But… we still want some test data to design with, right? We could add some data to our XAML file… but then that affects us when we actually run the application. Besides, I personally want test data to match the structure of the model I’m binding to.

Here’s what I’m doing to fix this right now. I added the following 3 lines of code to AccountDisplay.xaml.

<local:Designer.DataContext>  
  <local:BlendPresentationModel />  
</local:Designer.DataContext>

That doesn’t tell you much, so I’ll show you the Designer class that is being referenced now.

/// <summary>  
/// Allows the use of design-time only data binding... seems to only work  
/// in Blend and not the VS designer...  
/// </summary>  
public static class Designer  
{  
    public static readonly DependencyProperty DataContextProperty =  
        DependencyProperty.RegisterAttached("DataContext", typeof (object), typeof (Designer),  
                                            new PropertyMetadata(OnDataContextChanged));  
  
    private static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
    {  
        SetDataContext(d, e.NewValue);  
    }  
  
    public static void SetDataContext(DependencyObject d, object value)  
    {  
        var element = d as FrameworkElement;  
        if (element == null) return;  
  
        if (DesignerProperties.GetIsInDesignMode(element))  
            element.DataContext = value;  
    }

    public static object GetDataContext(DependencyObject d)
    {
        var element = d as FrameworkElement;
        if (element == null) return null;

        if (!DesignerProperties.GetIsInDesignMode(element))
            return null;

        return element.DataContext;
    }  
}

A few of things to note. I have a Dependency Property called DataContext first. I’m using a Dependency Property so that WPF data binding works. It can take any object (hence the typeof(object) parameter. When it changes, I call off to SetDataContext with the new value. Next important thing to note – DesignerProperties.GetIsInDesignMode. I try to cast the owner of my Designer instance (which is typically going to be a UserControl or Window or other UI element) to a FrameworkElement. I’m using FrameworkElement because it is the highest object in the hierarchy that provides the DataContext property. Then, if we’re in Design mode, I override the DataContext with my Designer DataContext.

In the XAML, what ends up getting set is a BlendPresentationModel, which looks like this:

public class BlendPresentationModel : PresentationModel  
{  
    public BlendPresentationModel()  
    {  
        var accounts = new List<Account>  
                           {  
                               new Account  
                                   {  
                                       Name = "Bob's Stuff",  
                                       Balance = 1000000  
                                   },  
                               new Account  
                                   {  
                                       Name = "Cheap Skate",  
                                       Balance = -100  
                                   }  
                           };  
        foreach (var acct in accounts)  
            Accounts.Add(acct);  
    }  
}

With my approach, I’ve created an object that inherits from my PresentationModel, so the object I’m binding my UI to is the same type that I’m using when running, but I’m providing test data instead. This is what it looks like in Blend now:

image

In one of my projects, I’ve been dropping these guys around in various UserControls and even one at the top level Window so that I can see what it all looks like together. So far, it is working well.

The biggest problem I’ve got with this solution so far is that the Visual Studio designer doesn’t render the test data. I would guess that this would be fixed at some point – honestly, the rendering of XAML should be the same between Blend and Visual Studio and, if it isn’t, it should be fixed.

Karl Shifflett posts a solution to this as well – my solution is basically just my own take on what he’s already done, so thanks to him for the initial idea. I wasn’t using Resources for binding, which is the primary reason I started with my own solution.

Also, Laurent Bugnion has a great article on various methods to accomplish this as well. I particularly like the feature he shares where Blend can create sample data. I’m very hopeful that this functionality is improved and expanded in future versions of Blend.

I hope this post helps out! Also, if I’m doing something that doesn’t make sense or if there is a better way to do something, please let me know.

UPDATE:
Thanks to Brian Genisio for the suggestion to add the GetDataContext method to my Designer class.

posted on Friday, December 05, 2008 1:13:38 PM (Central Standard Time, UTC-06:00)  #    Comments [4]
# Thursday, December 04, 2008

Thought I’d share the below LINQ statement I wrote recently:

var filesToBeMoved =  
    from networkFile in network  
    join localFile in local  
        on networkFile.Name equals localFile.Name into localToNetwork  
    from localMatchesNetwork in localToNetwork.DefaultIfEmpty()  
    // Handle files that are on the network but don't exist locally  
    where localMatchesNetwork == null  
          // Handle files that are newer on the network that they are locally  
          || (localMatchesNetwork.LastWriteTime < networkFile.LastWriteTime)  
    select networkFile;  
  
foreach (var file in filesToBeMoved)  
    file.MoveTo(_directoryProvider.LocalDirectory);

In this case, the files that are being returned are actually IFileProvider instances, which are basically wrappers around the System.IO.File instances for testability.

Oh, and this post is an excuse to see if I set SyntaxHighlighter up correctly :-)

posted on Thursday, December 04, 2008 7:55:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, November 19, 2008

I’ve been doing some WPF work lately. WPF is ridiculously powerful and provides a lot more than WinForms. On the other hand – wow, the learning curve is quite steep. I think I’m improving, though.

So, the scenario. I wanted to be able to let a user click on an item in a ListBox and drag across, selecting multiple items in the process. Basically, I want to emulate the behavior that the Outlook calendar provides.

I ended up coding up the following XAML to get the behavior:

<ListBox
  x:Name="myListBox"
  SelectionMode="Multiple"
  ItemsSource="{Binding Path=SomeIEnumerableOnMyDataContext}"
  >
  <ListBox.Resources>
    <Style
      TargetType="{x:Type ListBoxItem}"
      >
      <EventSetter
        Event="PreviewMouseLeftButtonDown"
        Handler="ListBoxItem_PreviewMouseLeftButtonDown" />
      <EventSetter
        Event="PreviewMouseUp"
        Handler="ListBoxItem_PreviewMouseUp" />
      <EventSetter
        Event="PreviewMouseMove"
        Handler="ListBoxItem_PreviewMouseMove" />
      <EventSetter
        Event="PreviewMouseRightButtonDown"
        Handler="ListBoxItem_PreviewMouseRightButtonDown" /> 
    </Style>
</ListBox>

The problem with this code is that Blend (currently v2 SP1) doesn’t like EventSetters.

image

I wanted to keep the events hooked up so that, while testing, I could keep the behavior but, at the same time, I want to be able to at least try to design in blend. So I took to implementing the above XAML in code.

Sacha Barber has a good article on converting from XAML to code and back that helped a lot but it didn’t get me quite there.

Here is how to programmatically create one of the EventSetters in code:

var style = new Style(typeof (ListBoxItem)); 
 
style.Setters.Add(
    new EventSetter(PreviewMouseLeftButtonDownEvent,
                    new MouseButtonEventHandler(OnPreviewMouseLeftButtonDown)));

It’s pretty straightforward, but actually hooking this style into my ListBox was what got me confused next.

Setting the ListBox’s style to my style instance didn’t work and then I got stuck on how to plug my style into the ListBox’s ResourceDictionary (via the Resources property). The XAML doesn’t specify a Key anywhere, but the Resources’s Add method requires a key. I tried creating my own key and also specifying a null key, but I still didn’t get the behavior I wanted.

StackOverflow’s goal of being the place for one-off questions like this is starting to work because I stumbled across my answer via Google. I didn’t realize that, in the above XAML, when the Style specifies its TargetType, the type is implicitly the Key in the ResourceDictionary.

So the solution is this:

Resources.Add(typeof (ListBoxItem), style);

Easy enough.

posted on Wednesday, November 19, 2008 12:01:01 PM (Central Standard Time, UTC-06:00)  #    Comments [2]
# Thursday, July 10, 2008

I was going through some code today and stumbled across the following:

Mmmmm... that was a good exception

Hilarious.

posted on Thursday, July 10, 2008 10:09:37 AM (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Wednesday, June 18, 2008

A couple of weeks ago, I was fortunate enough to attend the Tech Ed 2008 Developer conference. It was my first Tech Ed conference and I had a great time. (Yes, I still need to blog about my experiences there overall and I’m still planning on doing that.) One thing I wanted to bring up if you’ve never been to Tech Ed before is the great experience that the Hands on Labs (HOLs) provided. Basically, you walked up to the HOL computer and, in a few short steps, you had a full development virtual machine ready to go. It was a really nice experience and ensured that you could try out new features without having to set up your own VM or worse, download and install a lot of betas on your own development machine.

Apparently, Microsoft is using the same setup over the web. Maybe I’ve been in the dark for a long time, but I’ve never used a VM in a browser window before. Check the screenshot out:

image

Seriously, look at the browser title – this is in IE. On the right side of the screen, you’ve got the lab walkthrough, too. If you’ve been unable to look at new technology like .NET 3.5, LINQ, WPF, WCF, etc, you should check out Microsoft’s Virtual Labs. The MSDN Virtual Labs are at http://msdn.microsoft.com/en-us/virtuallabs/default.aspx, but TechNet also has labs for things like Windows Server 2008.

image

posted on Wednesday, June 18, 2008 8:01:36 AM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Wednesday, May 07, 2008

A coworker swung by a few days ago to ask some questions about using Reflection. I learn really well by example so I decided to use Powershell to show using Reflection. Below is the session I used and later emailed to him. You can see a few spots at the bottom of the example where I was unsure of the syntax on passing an empty parameter array, but I figured it out.

This is a good example of why I like Powershell :-)

  1 [1] » "haha".gettype()
  2
  3 IsPublic IsSerial Name                                     BaseType
  4 -------- -------- ----                                     --------
  5 True     True     String                                   System.Object
  6
  7
  8 [2] » $temp = "haha".gettype()
  9 [3] » $temp.GetProperties()
10
11
12 MemberType    : Property
13 Name          : Chars
14 DeclaringType : System.String
15 ReflectedType : System.String
16 MetadataToken : 385875994
17 Module        : CommonLanguageRuntimeLibrary
18 PropertyType  : System.Char
19 Attributes    : None
20 CanRead       : True
21 CanWrite      : False
22 IsSpecialName : False
23
24 MemberType    : Property
25 Name          : Length
26 DeclaringType : System.String
27 ReflectedType : System.String
28 MetadataToken : 385875995
29 Module        : CommonLanguageRuntimeLibrary
30 PropertyType  : System.Int32
31 Attributes    : None
32 CanRead       : True
33 CanWrite      : False
34 IsSpecialName : False
35
36
37
38 [4] » $temp.GetProperties()[0]
39
40
41 MemberType    : Property
42 Name          : Chars
43 DeclaringType : System.String
44 ReflectedType : System.String
45 MetadataToken : 385875994
46 Module        : CommonLanguageRuntimeLibrary
47 PropertyType  : System.Char
48 Attributes    : None
49 CanRead       : True
50 CanWrite      : False
51 IsSpecialName : False
52
53
54
55 [5] » $temp.GetProperties()[0].name
56 Chars
57 [6] » $temp.GetProperties()[1].name
58 Length
59 [7] » $temp.GetProperties()[1].GetGetMethod()
60
61
62 Name                       : get_Length
63 DeclaringType              : System.String
64 ReflectedType              : System.String
65 MemberType                 : Method
66 MetadataToken              : 100663629
67 Module                     : CommonLanguageRuntimeLibrary
68 MethodHandle               : System.RuntimeMethodHandle
69 Attributes                 : PrivateScope, Public, HideBySig, SpecialName
70 CallingConvention          : Standard, HasThis
71 ReturnType                 : System.Int32
72 ReturnTypeCustomAttributes : Int32
73 ReturnParameter            : Int32
74 IsGenericMethod            : False
75 IsGenericMethodDefinition  : False
76 ContainsGenericParameters  : False
77 IsPublic                   : True
78 IsPrivate                  : False
79 IsFamily                   : False
80 IsAssembly                 : False
81 IsFamilyAndAssembly        : False
82 IsFamilyOrAssembly         : False
83 IsStatic                   : False
84 IsFinal                    : False
85 IsVirtual                  : False
86 IsHideBySig                : True
87 IsAbstract                 : False
88 IsSpecialName              : True
89 IsConstructor              : False
90
91
92
93 [8] » $temp.GetProperties()[1].GetGetMethod().Invoke
94
95
96 MemberType          : Method
97 OverloadDefinitions : {System.Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo cu
98                       lture), System.Object Invoke(Object obj, Object[] parameters)}
99 TypeNameOfValue     : System.Management.Automation.PSMethod
100 Value               : System.Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo cul
101                       ture), System.Object Invoke(Object obj, Object[] parameters)
102 Name                : Invoke
103 IsInstance          : True
104
105
106
107 [9] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", [])
108 Unable to find type []: make sure that the assembly containing this type is loaded.
109 At line:1 char:65
110 + $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", []) <<<<
111 [10] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world")
112 Cannot find an overload for "Invoke" and the argument count: "1".
113 At line:1 char:47
114 + $temp.GetProperties()[1].GetGetMethod().Invoke( <<<< "hello world")
115 [11] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", {})
116 Exception calling "Invoke" with "2" argument(s): "Parameter count mismatch."
117 At line:1 char:47
118 + $temp.GetProperties()[1].GetGetMethod().Invoke( <<<< "hello world", {})
119 [12] » $temp.GetProperties()[1].GetGetMethod().Invoke("hello world", $Null)
120 11
121 [13] »
122

Note - I used the :toHTML command from Vim along with Peter Provost's Powershell syntax file to get the color. Powershell doesn't support color at the console like this yet without explicitly passing color arguments to Write-Host.

posted on Wednesday, May 07, 2008 8:51:00 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, April 24, 2008

(Warning - this post is both a rant against the Mutex as well as a guide for its usage. Also, don't blindly copy code, only the bottom code snippet works. :-) )

I'm a big fan of an API that is so easy to use that I don't have to look at the documentation.

I had to look up the documentation for System.Threading.Mutex... multiple times.

Taking a look at Mutex, I see that it implements IDisposable. Great, that means I can wrap it in a using block.

My first try:

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    MessageBox.Show("Press OK to release the mutex.");
}

Looks good, right? Nope, that is a big negative. Nowhere does this actually acquire the mutex. When you run this application twice, they both show the message box just fine. Maybe I should actually check the createdNew value?

Let's change the code to look like this:

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    if (!createdNew)
        mtx.WaitOne();
    MessageBox.Show("Press OK to release the mutex.");
}

However, that didn't work, either. It turns out that the createdNew parameter just tells you if you're the one who created the mutex, not if you currently own the mutex. That is what the purpose for the WaitOne method is for. Of course, the documentation just says that it "blocks the current thread until the current WaitHandle receives a signal." Okay. Well, I'm glad that I now know that it also waits for my thread to acquire a lock on the mutex. (note, if you pass in 'true' as the first parameter, you'll request to be the owner, but you'll only be the owner if the createdNew out parameter comes back with true)

Third try. Third time's the charm, right?

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    mtx.WaitOne();
    MessageBox.Show("Press OK to release the mutex.");
}

Great, now when I run my app twice, the second one is blocking on the WaitOne call. Cool. You can even tell in the below screenshot, because the button's paint event is blocked and is whiting out (like Solitaire does when you win!).

image

Let's click okay and see if the second form gets the mutex, thus displaying the message. That's weird - the form still isn't responding. Let's close the first form.

image

Ouch! That was unexpected. What? Abandoned mutex? This sounds like I never even released the mutex. Hmmm... ReleaseMutex? Shouldn't that be called from the Dispose (end of the Using block)? Might as well try it.

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    try
    {
        mtx.WaitOne();

        MessageBox.Show("Click OK to release the mutex.");
    }
    finally
    {
        mtx.ReleaseMutex();
    }
}

Finally! Now, it works like I'm wanting. I'm keeping the using block in place, because that disposes the WaitHandle that Mutex uses (Mutex in face inherits from WaitHandle).

Anyway, I'm hoping there is a reason for the API to be designed in this way, but man, it doesn't seem very intuitive to me.

While learning this, I unfortunately tried putting the Mutex in some of my code without trying it small scale first. After struggling for quite a while, I went to the small application and discovered everything that I've posted here. I hope this helps you with the Mutex when you have to deal with it.

posted on Thursday, April 24, 2008 3:48:19 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, March 28, 2008

Just a reminder to anyone in the Fort Smith area - we'll be meeting next Monday night at 6:00 to hear Chris Koenig talk about Silverlight. Chris is a Microsoft Developer Evangelist located out of Dallas. I got to meet Chris last year for a grand total of about 5 minutes when I went down for the .NET Roadshow that was hosted at Microsoft's office in Dallas. Chris got to escort me and the others between floors on the elevator :-)

Anyway, if you're in the area, swing by. We'd love to see you. For more information, check out the FSDNUG website.

posted on Friday, March 28, 2008 4:24:36 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, March 26, 2008

If you've been working with the .NET Framework for a while, you're hopefully already using some form of static analysis to help you catch problems with your code. One of the most well known is Microsoft's FxCop, which is now integrated as the Code Analysis feature in Visual Studio 2005 [1] and up. If you're not already using this tool, then please start because it can help you find problem areas like potential NullReferenceExceptions as well as globalization and security issues.

However, while FxCop is great at catching small problems and details, it isn't the best tool to see the big picture regarding your software. Enter NDepend by Patrick Smacchia. Chances are, you've already read Scott Hanselman's great review of NDepend a while back (or heard his podcast on static analysis with NDepend). If you haven't read it, go ahead and check it out. Scott uses NDepend to analyze dasBlog (which I'm running), so you can get the general feel for working with NDepend and what the reports look like.

I'd like to run through a few of the features of NDepend using Rhino Mocks as the target of my static analysis. Rhino Mocks is a neat example because it is only one assembly, but it is the result of an ILMerge of quite a few different libraries, so we get to see how NDepend handles this. Here is NDepend's class browser showing Rhino Mocks:

image

As you can see, it handles Rhino Mocks accurately. In fact, it almost feels like the class browser in Reflector, so that is already a plus. In fact, as you can see, the context menu supports jumping to Reflector for the selected type.

The "Who is directly using me?" option is also pretty cool and highlights the extensive use of CQL in NDepend:

image

CQL, or Code Query Language, is the centerpiece of NDepend and is how all of the analysis happens. You can think of it as SQL against IL. The massive benefit that NDepend has over FxCop IMHO is that you can create your own analysis rules in CQL instead of having to write and compile a DLL to extend FxCop (for an example of this, check out this FxCop rule that ensures that ArrayLists are List<T>s instead). Even better, NDepend provides a complete editor with intellisense that allows you to test your queries out against your assemblies.

image

Take a look at this screenshot. You can see the intellisense at the bottom right hand of the screen. At the top left is the CQL Query Results. The top right is all of the types in the assemblies, but the highlighted ones in blue are those that were returned by the query. This all happened as I typed the query in. Actually, I got red when I typed it in the first time, because my query had some mistakes in it, but NDepend was very helpful in showing me how to correct my query.

The query editor also has different types of intellisense depending on the value.

image

I'll admit that it might seem weird to have a slider when you're just typing a number in, but the cool part is when you change the value, the query results automatically change to reflect the new value. In this case, you can watch the results of the query to get a feel for which types have the most methods.

From an agile coding perspective, NDepend ties in well with Continuous Integration. It ships with both a NANT and an MSBuild task to run the NDepend console against an NDepend project file (which is just XML). The report that it provides is insanely detailed. I'd say this where the value of application-specific CQL queries would come in handy, because you can come up with some detailed queries that are run on every CI build to ensure that the code still matches whatever design criteria was decided upon when the queries were written.

 image

For future versions of the tool, I'd think it would be neat to have a lightweight version of the CQL tool that you could ad hoc queries against assemblies, like as a Reflector addin or something. That'd be cool. Or maybe a Powershell cmdlet/PSDrive provider so that you could do something like this:

Get-ChildItem -Include *.dll -Recurse | Select-Cql -Top 10 -Methods -Where MethodCa -ge 5

Or maybe:

Get-ChildItem -Include *.dll -Recurse | Select-Cql -Top 10 -Methods | Where { $_.MethodCa -ge 5 }

I'm not sure exactly how the syntax might look, but it would be really cool :-)

Hopefully, I've given you a good picture of the some of the features of NDepend. If your interest is at all piqued, there is a "Trial / Open Source / Academic Edition" that you can download for free. Its feature set isn't quite as broad as the Professional edition, but I've used it before and it still provides a lot of functionality. Check it out!

 

Full Disclosure - I used a review copy of NDepend for this post. My company is not (yet) using this tool, but I think that there is interest. I wasn't paid to do this. <kidding>If you, dear reader, would like to pay me, please contact me.</kidding>

 

[1] I don't believe that all of the SKUs of Visual Studio have the Code Analysis feature.

Technorati Tags: ,
posted on Wednesday, March 26, 2008 7:58:49 AM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Tuesday, March 04, 2008

Last night kicked out the Fort Smith .NET User Group's first meeting. It went great! I would guess that we had at least 20 or 30 people show up.

Raymond Lewallen spoke to us about Behavior Driven Design (BDD). I thought I'd share links to a few of the resources that he brought up last night.

All in all, a great presentation. Considering the breadth of information that BDD covers, I think Raymond did a great job. I hope that FSDNUG can continue to bring topics like this to the area.

posted on Tuesday, March 04, 2008 7:31:09 AM (Central Standard Time, UTC-06:00)  #    Comments [2]
# Monday, February 11, 2008

Last week, a small group of us traveled up to hear Jean-Paul Boodhoo present to the Northwest Arkansas .NET User Group. JP presented on advanced uses of generics in .NET (i.e. more than just strongly typed collections) though we also had a great look at Test Driven Development as well as some of the new features in C# 3.0.

The presentation was great and it got me really excited about user groups in general, which is why I'm also excited to announce that Fort Smith will be getting its own user group! Many thanks to Michael Paladino for doing a lot of the work in getting this started. FSDNUG went live last week. I'm hoping to add a feed to the site at some point so that news can easily be pushed out without continually checking the site, but for now, it is just static HTML.

Raymond Lewallen will be kicking off the group with a presentation on Behavior Driven Development. I've read about BDD and am attempting to practice TDD, so I'm excited to hear Raymond's talk. If you live in the area, be sure to come out for the meeting!

posted on Monday, February 11, 2008 12:43:38 PM (Central Standard Time, UTC-06:00)  #    Comments [4]
# Thursday, December 06, 2007

In case you've been under a rock recently, Visual Studio 2008 was released recently which supports a lot of functional capabilities like lambda expressions. I've been playing around with the lambda syntax in both C# and VB.NET recently and the addition to the languages is great. I did run into one thing that is still frustrating me in VB.NET, though.

Check out the below C# snippet:

TryTimes(() =>
{
   Console.WriteLine("hi there.");
   throw new Exception("haha");
   Console.WriteLine("hi there after   .");
}, 5);

This is the prototype for the usage of a function that could try an operation a certain number of times and then fail if the operation didn't succeed after N number of tries. Obviously, the above code sample will fail every time, but the idea could work alright for file I/O if you're unsure if anyone else might have locks on the file.

The above is impossible to do in VB.NET, though, because VB.NET does not support multi-line lambda expressions. The C# supports them by wrapping the expressions in curly braces, essentially making the lambda expression a block. I wanted to emulate the same thing with VB.NET, but after some fruitless web searches, I came across this MSDN forum posting on VB.NET and lambdas which then pointed to Paul Vick's post on the VB 2008 features that are still in.

I've been wanting the equivalent of anonymous delegates in VB for a long time and I thought, with lambda expressions, I might finally get them. We are a lot closer, but they still don't provide quite the benefit that they could have had we gotten multi-line lambda support. I guess those annoying line continuation characters in VB mess this all up. I think if I could change anything about VB, it would be to make those optional.

On the positive side, though, the intellisense support for VB.NET has increased substantially. For that, I am thankful.

posted on Thursday, December 06, 2007 9:56:03 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, October 26, 2007

Ayende is the man. Seriously.

Today, he released Rhino Mocks 3.3 to great fanfare.

If there wasn't great fanfare, there should be. My favorite new feature - mocking objects that inherit from MarshalByRefObject. You might be asking yourself, why does this matter? Doesn't that only apply to remoting? Well, yes, sort of. The thing is, a huge number of the built-in classes in the CLR support this remoting infrastructure. You know the ones I'm talking about - the built-in classes that are hard to mock and test.

At least they didn't let you mock them out until today. Here's an example of something that might have been harder to test before today:

[TestFixture]
public class Tests
{
    [Test]
    public void TestingCoolRhinoMocksStuff()
    {
        MockRepository mocks = new MockRepository();

        Process p = mocks.CreateMock<Process>();
 
        using (mocks.Record())
        {
            Expect.Call(p.Responding).Return(false);
        }
 
        using (mocks.Playback())
        {
            Assert.IsFalse(p.Responding);
        }
    }
}

Yeah, I'm mocking System.Diagnostics.Process. Sweet.

Take a look in Reflector and you'll find out just how many objects actually inherit from MarshalByRefObject. I think you'll be quite surprised.

Thanks Ayende!

posted on Friday, October 26, 2007 11:56:32 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, September 28, 2007

One of the banes of my existence (okay, not that bad but fun to say) is supporting Windows 2000 at work. Yes, there are still Win2K machines out there - not many, but enough to make a difference. One problem is that .NET 3.0/3.5 isn't supported on Win2K, so we're limited in what we can do, at least on the client-side. Another problem is just strange issues with the framework. 99% of the stuff we write works great, but there are a few things that don't.

Here is one that caused mass confusion recently.

Check out the code for this incredibly simple console application that I wrote:

Module Module1
 
    Sub Main()
 
        Console.WriteLine(">>Environment.CommandLine = {0}", Environment.CommandLine)
        Console.WriteLine(">>Environment.GetCommandLineArgs()(0) = {0}", Environment.GetCommandLineArgs()(0))
 
        Dim commandLineFileName As String = System.IO.Path.GetFileName(Environment.GetCommandLineArgs()(0))
        Console.WriteLine(">>commandLineFileName = {0}", commandLineFileName)
 
        Console.WriteLine(">>ProcessName = {0}", Process.GetCurrentProcess.ProcessName)
 
        Console.WriteLine("Press enter to continue....")
        Console.ReadLine()
 
    End Sub
 
End Module

What would you expect the output to be?

Here's what it does on Windows XP:

>>Environment.CommandLine = ConsoleApplication1.exe
>>Environment.GetCommandLineArgs()(0) = ConsoleApplication1.exe
>>commandLineFileName = ConsoleApplication1.exe
>>ProcessName = ConsoleApplication1
Press enter to continue.... 

On Windows 2000, it does the same thing. Super.

Let's change the name of the executable to ThisIsALongNameForAnExe.exe and run it again.

>>Environment.CommandLine = ThisIsALongNameForAnExe.exe
>>Environment.GetCommandLineArgs()(0) = ThisIsALongNameForAnExe.exe
>>commandLineFileName = ThisIsALongNameForAnExe.exe
>>ProcessName = ThisIsALongNameForAnExe
Press enter to continue.... 

Once again, Windows 2000 behaves the same way. Great.

Let's try one more thing. Let's change the name of the executable to This.Is.A.Long.Name.For.An.Exe.exe and run it one last time.

Windows XP looks like this:

>>Environment.CommandLine = This.Is.A.Long.Name.For.An.Exe.exe
>>Environment.GetCommandLineArgs()(0) = This.Is.A.Long.Name.For.An.Exe.exe
>>commandLineFileName = This.Is.A.Long.Name.For.An.Exe.exe
>>ProcessName = This.Is.A.Long.Name.For.An.Exe
Press enter to continue.... 

However, Windows 2000 looks like this:

>>Environment.CommandLine = This.Is.A.Long.Name.For.An.Exe.exe
>>Environment.GetCommandLineArgs()(0) = This.Is.A.Long.Name.For.An.Exe.exe
>>commandLineFileName = This.Is.A.Long.Name.For.An.Exe.exe
>>ProcessName = This.Is.A.Long
Press enter to continue.... 

Can you tell the difference? System.Diagnostics.Process.ProcessName is truncated when running on Win2K. The only thing I can tell is that the periods in the process name throw it off. Granted, hopefully you don't have anything secure relying on the name of your process (cough, rename, cough), but it still came across as very unexpected.

Note - the results can be different depending on how you actually execute the program. The command line and command line arguments are literally what was typed when the program is executed.

posted on Friday, September 28, 2007 2:21:13 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, August 30, 2007

I was messing around with some unit tests this week and I came across an unexpected benefit while working on code that worked with a COM object. When you add a reference to a COM library in .NET, you'll get an interface as well an implementation of that interface that forwards the calls to the COM objects.

Because an interface is created for the COM objects as well as the implementation, you can mock the COM dependency with Rhino Mocks or some other mocking framework. Just code against the interface instead of the concrete implementation and inject the concrete implementation via dependency injection for the normal scenario.

Let's say you wanted to unit test some code that had a dependency on the Windows Media Player COM object. Here's how you could do it.*

image

// Code to be tested
public class SomeClass
{
   private WMPLib.WindowsMediaPlayer _player;

   public SomeCode(WMPLib.WindowsMediaPlayer player)
   {
      _player = player;
   }

   public void DoSomething()
   {
      _player.enabled = false;
   }
}

// Unit test
[TestFixture()]
public class SomeCodeTest
{
   [Test()]
   public void PlayerEnabledShouldBeSetCorrectly()
   {
      MockRepository mocks = new MockRepository();

      // Mock the WMP interface... note that even 
// though it doesn't start with an 'I', // it is still an interface... WMPLib.WindowsMediaPlayer player = mocks.CreateMock(); // Inject the mocked WMP object SomeClass sc = new SomeClass(player); using (mocks.Record()) {
// Expect player.enabled to be set to false player.enabled = false; } using (mocks.Playback()) { sc.DoSomething(); } } }

I tried this code out and the test runs fine. Note the comment where the mock object is actually being created. For some reason, the interface to the COM object isn't named with an 'I'. It still is an interface, though. And you can create the COM object by saying 'new WMPLib.WindowsMediaPlayer' though I think that is some COM interop magic going on there (I'm guessing the CoClass attribute on the interface has something to do with this magic).

* I'm not actually mocking Windows Media Player in any of my code and I have no idea how well it will work. I do know that I can mock some of our own COM objects without any problems, though.

posted on Thursday, August 30, 2007 4:36:44 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, August 21, 2007

I found myself writing the following code this evening:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
 
    return (T)GetConverter(typeof(T)).ConvertFromString(result);
}
 
private TypeConverter GetConverter(Type objectType)
{
    if (objectType.Equals(typeof(int)))
        return new Int32Converter();
    else if (objectType.Equals(typeof(bool)))
        return new BooleanConverter();
    else if (objectType.Equals(typeof(string)))
        return new StringConverter();
    else
        throw new ArgumentException("Does not support casting to " + objectType.Name);
}

Don't ever write code like this. Read the documentation which explicitly says that "you should never create an instance of a BooleanConverter". If you follow their advice, your code will become much cleaner. Like so:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(result);
}
posted on Tuesday, August 21, 2007 9:39:58 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, August 02, 2007

(note - if you're reading this in a feed reader like Google Reader, sorry - the code snippets look awful... if anyone has any suggestions on good ways to get code to look good in the webpage and feed readers, I'd appreciate it)

Given this:

    delegate void WorkDelegate();
    interface ISomeInterface
    {
        void Execute();
    }

 

What is the difference between this class

    class TestCaseOne
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseOne()
        {
            BackgroundWorker wkr = new BackgroundWorker();
            wkr.DoWork += new DoWorkEventHandler(wkr_DoWork);
            wkr.RunWorkerAsync();
        }

        void wkr_DoWork(object sender, DoWorkEventArgs e)
        {
            something.Execute();
        }
    }

and this class?

    class TestCaseTwo
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseTwo()
        {
            WorkDelegate dlg = new WorkDelegate(something.Execute);
            dlg.BeginInvoke(MyCallback, new object[] { dlg });
        }

        private void MyCallback(IAsyncResult iar)
        {
            object[] asyncState = iar.AsyncState as object[];
            WorkDelegate dlg = asyncState[0] as WorkDelegate;

            dlg.EndInvoke(iar);
        }
    }

 

Both classes have a field named something that is a reference to an HTTP remoting proxy that has been published at http://some.url.com. Let's assume that the the HTTP Remoting configuration has already been set up. Both call the Execute method defined on the interface, but one is using a BackgroundWorker for threading and the other is using the BeginInvoke/EndInvoke means of threading. Big deal, right?

There isn't a huge difference just looking at the code -- except that with TestCaseOne, the remoting call will result in a blocked thread whereas TestCaseTwo will not. In TestCaseOne, the background thread will block on the something.Execute() call and wait for it to return. In TestCaseTwo, the WorkDelegate BeginInvokes on the transparent remoting proxy. There isn't any code to block on. Instead, the framework will let you know when your remoting call returns.

Why does this matter? When you have a blocked thread, you basically have wasted CPU cycles where it is blocking instead of working. This likely won't matter much if you're not working with a lot of threads, but it can cause performance problems if you're working with a lot of threads.

On the other hand, when TestCaseTwo calls back to let you know the remoting call has completed, it will not call back on the calling thread. BackgroundWorker is smart enough to invoke back to the UI thread if needed. Both have their pluses and minuses. The BackgroundWorker component does make the code a little more easy to read and it handles invoking back to the UI thread. However, if you're working with a lot of threads, you might try using the delegate approach instead, so as to avoid any blocked threads.

posted on Thursday, August 02, 2007 10:40:25 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, May 01, 2007

I just finished reading this post from the BCLTeam blog on the Silverlight 1.1 Alpha release that was announced at MIX07. It sounds like there is a new security model that is being introduced with Silverlight as a replacement for CAS (Code Access Security). I haven't done any research yet, but it looks like we'll be able to just decorate methods with attributes like Transparent or SafeCritical.

From just a cursory glance, it sounds like this will be much easier to work with than CAS. I couldn't ever really follow CAS very well - usually I just followed the FxCop guidelines and left it at that. I found the MSDN documentation on developing Silverlight applications with the .NET Framework, but there isn't much on the security side of things yet. I'm interested to see if Microsoft will start to move away from CAS to a more developer-friendly model.

Sounds interesting.

posted on Tuesday, May 01, 2007 9:41:38 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, April 03, 2007

Read it here:  http://weblogs.asp.net/scottgu/archive/2007/04/03/expression-added-to-msdn.aspx

Woohoo!

This is a great move by Microsoft and I really appreciate it.

I wonder how many other people are firing up their blogs to post this, too.

posted on Tuesday, April 03, 2007 12:51:46 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, March 27, 2007

Lately, I've been working on performance enhancements to one of the projects at work. Our users had all mentioned that the application's startup time was pretty slow and wanted to know if we could do anything to speed it up. Of course, when all of your users have been using green screen applications, even native C applications will likely seem slow to them... but anyway. We started digging in and found a few places where we could optimize our code but our form still took a while to load.

While testing, I happened to have Process Explorer up and noticed that our process was kicking off csc.exe, which is the C# compiler.

This is one of those instances where some (if not all) of you will know what I was seeing here. You see, we were using XML serialization in our project. When you do XML serialization, some code-gen happens to make the serialization magic work. If you have FileMon or ProcMon up, you'll actually see a temporary C# file being written out and compiled. I might have remembered this (Scott Hanselman has a lot of posts on the XmlSerializer) if I had thought about the temp file aspect, but I was wondering more about the C# compiler.

Anyway, the best way to avoid this precompilation step is to do the precompilation yourself using sgen. Basically, if you give it an assembly named Foo.dll, you'll get back an assembly named Foo.XmlSerializers.dll.

My only question regarding sgen is why standard compilation doesn't do this for you automatically. I'm sure there is some reason why, but I haven't thought of it yet. Regardless, I went ahead and added it to our build script and we've seen increased performance.

As a side-note, Red Gate's ANTS Profiler is an awesome profiler tool to help you find bottlenecks in your code. It will put big red lines next to the code that takes a long time to run.

posted on Tuesday, March 27, 2007 7:55:46 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, February 12, 2007

Lately, I've been doing some work with the WebBrowser control (new in the 2.0 framework). It really does offer a lot of benefits over directly using the underlying ActiveX web browser control. And when the new functionality doesn't cover a need you may have, you can always get at the ActiveX control (though you'll need plenty of COM interface definitions - hello pinvoke.net!).

The typical usage scenario with the WebBrowser control is that, if you want more than just a basic control, you're going to inherit from it. I was wanting to be able to provide a custom context menu instead of using the default IE one. Here comes MSDN documentation to the rescue! According to the documentation on the protected CreateWebBrowserSiteBase method, the method can be overridden to provide a custom WebBrowser.WebBrowserSite object. Here's the quote from the documentation:

To use this feature, implement classes that inherit from the WebBrowser and WebBrowser.WebBrowserSite classes. The unmanaged WebBrowser ActiveX control uses the protected CreateWebBrowserSiteBase method to retrieve extensibility interfaces implemented by the WebBrowser.WebBrowserSite class. Override the CreateWebBrowserSiteBase method to return an instance of your own class that inherits from the WebBrowser.WebBrowserSite class. The WebBrowser.WebBrowserSite class provides default implementations of the OLE IDocHostUIHandler. You can provide your own implementation of this interface or implement any other WebBrowser ActiveX control interface in order to customize the behavior of the control.

Super!

Because the WebBrowserSite class is protected and internal to the WebBrowser, your implementation must be internal to your inherited WebBrowser class to have access to it. Like so:

public class CustomWebBrowser : WebBrowser
{
	private class CustomBrowserSite : WebBrowserSite
	{
		// Your implementation
	}
}

So, I happily pulled up the interface definition for IDocHostUIHandler, coded it up and made my custom WebBrowserSite implement it. To verify that it was working, I just stuck a message box to tell me hello in the ShowContextMenu method. When I ran my test, I right clicked and saw a context menu... the default context menu! Huh?!?

I was positive I must have missed something, because the documentation is CLEAR on the fact that this scenario is possible.

And yet... and yet... WHAT IS THIS?!?

More searching and I find that there is a bug reported for this exact scenario on Microsoft Connect! And what's more, it has been closed because it has been postponed!!!

This wouldn't really irk me so much except that the documentation specifically says that it can be done. Here is a snippet of the reasoning behind closing the bug:

... The bug you entered has been reproduced, but our evaluation determined that it does not meet the criteria to be addressed in this release. The main reason for this is that in this release, our webBrowser control is tightly tied to the IDocHostUIHandler not leaving much room for such customization. ...

Why, oh why wasn't this tested? The documentation says THAT THIS CAN BE DONE! Don't post documentation that says that you can do this and then tell us that you can't because your implementation won't allow it!

Luckily, there are 2 workarounds listed that let you hook your own IDocHostUIHandler implementation in (it involves implementing ICustomDoc and calling the SetUIHandler method, see this CodeProject article for more details). Tightly tied my butt... the workaround gets the same results just fine.

posted on Monday, February 12, 2007 1:01:36 PM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Tuesday, January 16, 2007

We're in the process of migrating to .NET 2.0 at work and one of the the things we've encountered is a problem with remoting between .NET 1.1 and 2.0 frameworks.

This is our scenario in a nutshell.

An application is upgraded to 2.0 but is still referencing a 1.1 component. This works fine until the 1.1 component remotes to a 1.1 server. The client is running under the 2.0 framework while the server is running under the 1.1 framework. We can't upgrade the server because there are still other 1.1 clients out there as well.

What's funny about this is that it will work sometimes. Interoperability between 1.1 and 2.0 is actually fairly solid... unless you're serializing a DateTime across the wire. If you're sending a DateTime between the two frameworks, you'll see this error:

Exception: System.ArgumentOutOfRangeException
Message: Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
Parameter name: ticks

If you were to change the server side over to run under .NET 2.0, you won't see the problem anymore. On the plus side, Microsoft has released a hotfix to address this issue (and even more information here) that specifically patches the 1.1 framework. The problem is that you've got to contact Microsoft to get the hotfix.

I'm hoping that by posting this, I will let others know about it and maybe even to get Microsoft to release it for download.

Then again, maybe no one else has to deal with this issue :-)

posted on Tuesday, January 16, 2007 12:38:32 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, December 11, 2006

I'll tell you what it looks like.

It looks like -1.#IND.

That's what it looks like. At least if the code is using the Double.NaN constant. I sure didn't know that before I saw it and, I can tell you, it sure freaked me out when I saw that in the immediate window in Visual Studio. I was working on speeding up another dev's code here and apparently they were using NaN to signify the difference between 0 and "not yet initialized." It works pretty well for them in that case, but as I said, if you're not expecting that, it very well may throw you off.

And PowerShell is smart enough to just say NaN instead of this -1.#IND stuff.

Along the same lines, -1.#INF is apparently how Infinity is represented.

(IND would be indefinite whereas INF is infinite... makes sense I guess.)

posted on Monday, December 11, 2006 2:34:15 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Sunday, September 24, 2006

Last month (almost two months ago!), I posted on how to programmatically get the caption for an image in C#. I haven't posted much more on the subject lately, because I've been busy with other things like playing with Vista RC1 and different unit testing frameworks. I also have learned a lot more about the different methods for storing metadata in images. My previous method ONLY works for images where the metadata is in the EXIF format. There are a variety of different metadata formats available and I discovered that not all of my digital pictures use EXIF. In other words, my previous post DOES NOT WORK for those images. I also discovered that there is no reason to use my previous method, because Omar Shahine has already done all of the hard work here.

If you're interested in EXIF metadata, use his PhotoLibrary. It is a very well designed library for setting and retrieving EXIF metadata on images. I really wish I had known about it a couple of months ago, but at least I learned some stuff on my own. That's always nice. The problem is, once again, that it only works with EXIF metadata. Basically, I wanted a solution that gave me the same results that Windows Explorer file properties provides. I wanted the caption regardless of the metadata format.

The solution? Windows Presentation Foundation!!! WPF provides a completely new way to look at images. There is a great overview in the MSDN documentation here.

The short of it is that you can write code like this, though:

ImageSource src = this.image1.Source;

BitmapMetadata bm = ((BitmapMetadata)this.image1.Source.Metadata);

MessageBox.Show(bm.Title);

Neat, eh? What's even better is that it works for every image I've tested with it so far. The only other code in my small example is some XAML to get an image loaded and the code to get a click event handler so I could see the results of my test.

Nice!

I guess my new Gallery Manager application will target the .NET 3.0 Framework!

Note - for uncommon metadata attributes, there is a GetQuery property that BitmapMetadata provides. I haven't looked into much, but it looks like it covers many of the various metadata formats available. You just have to know the query syntax... which I currently don't. If anyone knows of any good resources on this, please let me know!

posted on Sunday, September 24, 2006 10:12:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, September 07, 2006

When you're creating a GUI control in Visual Studio, your public properties will be displayed in the Property Grid and you can customize this by using attributes such as the Category attribute or the DisplayName attribute. Another nice attribute to use sometimes is the Browsable attribute. If you set the Browsable attribute to false (i.e. <Browsable(False)> in VB.NET), it won't be displayed in the property grid. I typically use this to hide properties that really have no function from the GUI side.

Here's the point of the post though: even if you set a property's Browsable attribute to false, it will still be accessed by the designer. In other words, if you've got code like a Debug.Assert or something in there, it will still fire, regardless of the Browsable attribute's value. So, you might consider putting a DesignMode check around code like that because it will give you some weird behavior when running in the designer.

UPDATE:
No one ever told me about the DesignerSerializationVisibilityAttribute! You can set DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) on a property and it won't get serialized into code!

posted on Thursday, September 07, 2006 8:53:25 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, August 21, 2006

(After yesterday's post on getting metadata from images in .NET, I've decided to continue to post some of the information I find regarding working with images in .NET.)

As I mentioned yesterday, I'm working on an application to export a folder of images over to a webpage or something (I haven't decided on the output format, whether to a database, XML, or what). I've been learning quite a bit about .NET image support (primarily from GDI+) and it really provides a lot right out of the box. Today's post is on resizing an image without losing too much quality in the process.

The first resource I found was System.Drawing.Image.GetThumbmailImage. My first thought was, "Surely it isn't this easy!" I was right - it wasn't that easy. Check out this quote from the remarks section of the documentation:

The GetThumbnailImage method works well when the requested thumbnail image has a size of about 120 x 120 pixels. If you request a large thumbnail image (for example, 300 x 300) from an Image that has an embedded thumbnail, there could be a noticeable loss of quality in the thumbnail image.

My first test was resizing an image that was originally 2580 x 1932 down to 640 x 483. It looked quite nasty after trying to call GetThumbnailImage. Back to Google I went, but thankfully I soon hit paydirt. I found the "Resizing a Photographic image width GDI+ for .NET" article by Joel Neubeck on CodeProject. The meat of the functions he provides are that they give examples on how to carry the resolution of the original image over and also how to use bicubic interpolation. With his code, my 640 x 483 picture still looks great - just as good as Picasa does for its export code!

I will say that I am still using the GetThumbnailImage method for what it was primarily designed for: thumbnails. As the documentation says, it works fine up to about 120 x 120. I'm personally using a max width/height of 90 for my thumbnails right now. Here's an example of a call to GetThumbnailImage just so we'll get some code in this post:

private static void CreateThumbnail(Image img, string path, Size imageSize)
{
    // Only call this to create thumbnails smaller than 120 x 120! Otherwise, check out 
    // http://www.codeproject.com/csharp/imageresize.asp.
    
Image thumbnail = img.GetThumbnailImage(
        imageSize.Width,
        imageSize.Height,
        (
delegate { return false; }),
        
IntPtr.Zero);
    thumbnail.Save(path);
}

As you can see, I'm using an anonymous delegate for the 3rd parameter, which presumably only exists for backwards compability, because it isn't called. It makes more sense to me to do it this way than to add a function that won't even be called.

posted on Monday, August 21, 2006 10:12:41 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Sunday, August 20, 2006

So, this is a little off-topic compared to some of the other posts I have done lately, but it was something new to me and I thought I'd share it for information... and as a means of helping me remember it later!

At home, I have been using both Microsoft Digital Image Library 2006 and Picasa to manage my digital pictures because I like features in both. Microsoft's product provides some nice editing features and tagging while I've been using Picasa's export as a webpage in an XML format for mine and my wife's blog. One of the hassles between the two, though, is that they store captions for images differently. I was having to manually copy and paste captions between both programs, which is huge time waster. Because I wanted to continue using Digital Image Library, I decided to write a program to export the gallery. (I know there are programs out there that can do this for me... I've got the programmers' disease!)

To write this program correctly, I wanted to still be able to pull out information like the captions I had set for each picture. I ended up digging around a little bit researching the different implementations for storing metadata in the files and it would appear that Microsoft's implementation seems more standard than that of Picasa. In fact, some digging in one of my pictures using a hex editor shows the proprietary <picasastamp> enclosing a <caption> tag. At least that means it will be easier to pull the caption out.

Probably one of the best places to start for researching this is the MSDN how to: Read Image Metadata. It details the PropertyItem that you can get off of the System.Drawing.Image class. There is actually a collection of PropertyItem objects from the PropertyItems collection. Basically, you can loop through the collection and inspect each item's Id property until you find the one you are looking for. That's the easy part. The hard part is figuring out which Id you're interested in because they don't have user-friendly names like "Caption" or "Title" - they're in hex. Thanks to this sort of random post, I was able to find out that the captions I was looking for were 0x9c9b.

So, without further ado, here's a very simple GetCaption method that will return the caption/title based on an Image passed to you:

public static string GetCaption(Image img)
{
    if (img == null) 
        throw new ArgumentNullException("img");

    Encoding enc = Encoding.UTF8;

    foreach (PropertyItem prop in img.PropertyItems)
    {
        if (prop.Id == 0x9c9b)
        {
            return enc.GetString(prop.Value).Replace("\0", "").Trim();
        }
    }

    return string.Empty;
}

Let me know what you think!

If you're interested in more about the PropertyItem class, check out these pages - they've got some nice information on them as well.

- http://www.codeproject.com/cs/media/photoproperties.asp
- http://www.pixvillage.com/blogs/devblog/archive/2005/03/27/176.aspx

posted on Sunday, August 20, 2006 9:21:59 PM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Friday, August 18, 2006
This post is just as much for me as it is to share...

I was attempting to create a automatically resizing GroupBox control that would let users drop controls on it and it would grow as the controls dropped. I also wanted to offer a FlowLayoutPanel-like ability so that it would slide controls that were lower up if higher controls were hidden. Doesn't sound too bad and we would use it enough that it made sense to encapsulate it in a custom control. I started looking into inheriting from GroupBox and adding a FlowLayoutPanel to it's control collection. Then I hooked into the ControlAdded event for the GroupBox so that I could move the control from the GroupBox to the FlowLayoutPanel. I'm just walking you through the steps in my thinking process here... this apparently isn't how it should be done, because though it worked if controls were added at run-time, it gave me a weird designer error that said "'child' is not a child control of this parent" (like these guys did).

What research I came up with looked like I would have to create my own custom designer to support code like this, that would also include code serialization into InitializeComponent. Yay. A little more research brought me this link, though. It details how to drop controls onto a UserControl at design time. It is a slightly different approach, but it provided what I needed. Basically, the solution also involves using a ControlDesigner, but the code seems much less involved than if I were handling code serialization.

Here's a code snippet to give you an idea of what I did:
<Designer(GetType(AutoResizeGroupBoxDesigner))> _
Public Class AutoResizeGroupBox
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property FlowPanel() As FlowLayoutPanel
Get
' Where _flowPanel has already been added to the designer
Return _flowPanel
End Get
End Property

' code snipped...

End Class

Public Class AutoResizeGroupBoxDesigner
Inherits ControlDesigner
Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
MyBase.Initialize(component)
Dim autoGroupBox As AutoResizeGroupBox = DirectCast(component, AutoResizeGroupBox)
EnableDesignMode(autoGroupBox.FlowPanel, "FlowPanel")
End Sub
End Class
posted on Friday, August 18, 2006 7:58:52 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, July 20, 2006
Like many other users of Visual Studio 2005, I've occasionally received the WSoD (White Screen of Death) while using the designer. And like a typical user, I blamed it on Visual Studio. That's what users do, right? They blame the program, because the user is always right. The same behavior that frustrates me to no end when users enter invalid data into MY program and then blame MY program (of course, if my UI were better, it wouldn't be as difficult to use, but that is another story). Anyway, my frustrations with VS2005 crashing and the WSoD's were in fact a problem with the user - me.

In one of my forms, I had some background threading work that was started when the form loaded. Like a good programmer, I had wrapped this threading work in a check against Me.DesignMode to ensure that it wouldn't try to do this work while in the designer. What I didn't know at the time is that the DesignMode property isn't set until AFTER the constructor fires. I checked around with some guys at work and I discovered that I wasn't the first one to discover this. They had already put a check against Application.ExecutablePath to see if it was devenv.exe. If it is, then we're in DesignMode. Simple as that!

So, all of my VS crashes and weird WSoD's have now been tracked back to my OWN code. HOWEVER, I would like to say that it would have been nice if Visual Studio had given me a better message to inform me that my designer code was trying to run background threads or something - in much the same way that my own code should work better and give my users better messages.

Ah, the joys of user interaction.

Note: This fixed the problem suggested after sending error reports that link to this hotfix (http://support.microsoft.com/?kbid=915038). If you're running into this, check and double-check the code in your UI constructors, INCLUDING base class constructors!
posted on Thursday, July 20, 2006 11:22:10 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, July 13, 2006

Yesterday, I downloaded the Developer Productivity Tools video from the Wrox website that Scott Hanselman did for one of his presentations with a user group. He had a lot of great resources in the video but the command prompt tips he had were new to me. I've done some work with the console, but I've only recently been using it more, particularly with PowerShell coming along.

Scott's tip about customizing your prompt (from c:\dir\> to whatever) was really cool (also posted here). I knew that the prompt could be customized, but at the time I saw someone do it, I didn't have a good grasp of environment variables so it didn't really make sense what was going on, but Scott's video and his post have helped out a lot. They also prompted me to want to do the same with my PowerShell prompt!

The PROMPT environment variable trick doesn't work for the PowerShell prompt, but after a little digging around with Google, I discovered this post from Lee Holmes about the prompt function. If you have a function named prompt declared, PowerShell will use the value returned by that function to alter the display of your prompt. Here's my prompt function, which I have saved in PowerShell profile so that it will load every time (mine is located here C:\Documents and Settings\David\My Documents\PSConfiguration\Microsoft.PowerShell_profile.ps1)

# Initialize custom prompt
function prompt
{
   "PS " + (get-location).Path + [System.Environment]::NewLine + ">".PadLeft((get-location -stack).Count + 1, "+")
}

The only thing I haven't figured out yet is how to get a visual indication of how far in the stack you are (by using pushd and popd). Once I figure that out, I'll have a PowerShell prompt customized just like my cmd prompt!

UPDATE: I did some more research and discovered get-location -stack which will return everything on the pushd/popd stack. I've updated my prompt function accordingly. Now it matches my cmd prompt in every way!

posted on Thursday, July 13, 2006 1:00:39 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, July 05, 2006
Just a short note, but for those who have been waiting for a version of NDoc that supports .NET 2.0 assemblies, there is a separate project out on SourceForge called NDoc 2005. It is still in beta, but it may be the way to go until NDoc gets moving again. Per comments at MSDN forums, it looks like the best way to go is to download the source and recompile it yourself. The binaries (at least the GUI binary) looks like it still has some issues.

Note: unfortunately, it still doesn't completely work for me... *sigh*

(from DotNetKicks)
posted on Wednesday, July 05, 2006 12:37:04 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, June 30, 2006

If anyone out there knew about the BindingList before today, I sure wish one of you would have told me. Now I know, if you had known I was looking for something like the BindingList, you would have told me, but still...

Okay, all joking aside, the BindingList is what I've been trying to find for a long time. With Visual Studio 2005, the option to bind to an object data source is now possible (see screenshot).

The typical usage scenario for me with this data binding option is that I have just used .NET remoting to pull a collection of business objects back from a remote server. After that, I usually want to bind this collection to a datagrid or something like. For the past few months, I had used the new BindingSource object and set its DataSource property to my collection (usually a System.Collections.Generic.List<T> or a System.Collections.ObjectModel.Collection<T>). The problem I had was that any changes to either of those collections later would not fire ListChanged events. I had settled myself to the fact that I would have to reset the binding everytime.

Well, not so!

Dinesh Chandnani posted to his MSDN blog over a year ago about this subject. Too bad I didn't find it until today. In his post, he provides some very simple code examples, one of which details how to get a "DataGridView bound to business objects." *gasp!* Where have I been? This is what his code looks like:            

            DataGridView dgv = new DataGridView();

            BindingSource bs = new BindingSource();

            BindingList<Customer> bList = new BindingList<Customer>();

           

            // Fill bList with Customers

 

            bs.DataSource = bList;

            dgv.DataSource = bs;

 

I wish I known about the System.ComponentModel.BindingList<T> before now. It would've saved me so much time. If you're still trying to bind to a List or Collection like I was, take that guy out and bind to the BindingList instead! It really works the way you would expect it to!
posted on Friday, June 30, 2006 12:31:42 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
I don't like repeating myself, but I need to again: if you're not subscribed to the PowerShell blog, then why in the world not?!? The PowerShell team has been on top of it lately providing some GREAT one-liner PowerShell scripts such as listing all of the sub-directories from the current directory or, as in the case today, listing all of the PROGIDs that you can use to instantiate your own COM objects from PowerShell script.

Sure, the scripts are fairly simple and are clearly obvious once you see them, but it displays the power right at your fingertips that PowerShell gives you. Currently, I'm not using it for any projects. I'm just using it as a productivity tool! The parsing you can do with directories and files is great and you can very quickly leverage your knowledge of .NET in the process.
posted on Friday, June 30, 2006 7:35:10 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, June 27, 2006
I'm not sure how often people run into situations where the ManualResetEvent is needed, but I have a few times. System.Threading.ManualResetEvent provides an easy way to allow cross-thread communication and to let other threads know when something has completed. Most of the time that I've needed it, I have a property in a class that is loaded in another thread, but I want to prevent access to the property until it is loaded. From what I've seen, this is a great time to use the ManualResetEvent.

It is easiest to explain with some code snippets. Here's how you create the ManualResetEvent.

Private _dataLock As New ManualResetEvent(False)

The constructor takes a boolean that signifies whether the object is signaling or not. A signaling object implies that the action has been completed... we're done with the work. If signaling is false, the work hasn't finished yet.

To wait on the signal, use this code:

_dataLock.WaitOne()

You can also specify a period of time to wait instead of waiting indefinitely.

Once your background work is completed, you can call Set like so:

_dataLock.Set()

This begins signaling, so any calls to wait will stop blocking and will continue execution.

Here's a full code sample that shows how it would work and also gives a short example on the BackgroundWorker.

Imports System.ComponentModel
Imports System.Threading

Module Module1

    
Private _dataLock As New ManualResetEvent(False)

    
Sub Main()

        Thread.CurrentThread.Name =
"[Main]"

        Dim wkr As New BackgroundWorker
        
AddHandler wkr.DoWork, AddressOf wkr_DoWork
        
AddHandler wkr.RunWorkerCompleted, AddressOf wkr_RunWorkerCompleted

        wkr.RunWorkerAsync(
"Get to work!")

        Write(
"Waiting on the lock...")
        _dataLock.WaitOne()
        Write(
"we're back!")


        Console.WriteLine(vbNewLine &
"Press any key to continue...")
        Console.ReadLine()
    
End Sub

    Private Sub wkr_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
        Thread.CurrentThread.Name =
"[Work]"

        Write("DoWork just received this value: " & CStr(e.Argument))
        Thread.Sleep(
5000)

        e.Result =
"DoWork finished!"

        Write("DoWork is done so start signaling completion.")
        _dataLock.Set()
    
End Sub

    Private Sub wkr_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
        
Dim wkr As BackgroundWorker = DirectCast(sender, BackgroundWorker)
        
RemoveHandler wkr.DoWork, AddressOf wkr_DoWork
        
RemoveHandler wkr.RunWorkerCompleted, AddressOf wkr_RunWorkerCompleted
        wkr.Dispose()
    
End Sub

    Private Sub Write(ByVal s As String)
        Console.WriteLine(
String.Format("Thread: {0}, Message: {1}", Thread.CurrentThread.Name, s))
    
End Sub

End
Module

The output from running looks like this:
Thread: [Main], Message: Waiting on the lock...
Thread: [Work], Message: DoWork just received this value: Get to work!
Thread: [Work], Message: DoWork is done so start signaling completion.
Thread: [Main], Message: we're back!

Press any key to continue...
One thing to remember: do NOT put the call to Set (i.e. _dataLock.Set()) in the thread where you are waiting (i.e. _dataLock.WaitOne())! You'll never get the signal because that thread is already blocking! Because of this, make sure your call to Set always happens in the DoWork event of the BackgroundWorker instead of the RunWorkerCompleted event.
posted on Tuesday, June 27, 2006 12:59:56 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, June 15, 2006

We were working with partial classes recently at work and we came up with a best practice usage for naming them, at lease for our needs, and I thought I would share it with you.

Basically, do it the way Visual Studio does. For example, with GUI components such as forms, VS2005 names the main class Form1.vb, while it names the partial class Form1.designer.vb. So, if you want to make your Shipment class have a partial piece, have a file that is Shipper.vb and Shipper.stuff.vb.

This way, it is clear by the naming that the files are related. Otherwise, I would think there would be a lot of confusion on how the files are related.

Any thoughts on this?

posted on Thursday, June 15, 2006 12:44:28 PM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Tuesday, June 06, 2006

I don't have much experience with XPath expressions. This was further illustrated to me recently when I was attempting to use XPath to programmatically parse an MSBuild project file. Yeah... I couldn't find anything. So, when presented with a problem, what do all programmers do? They write a program to solve the problem!

Here's a screenshot of my XPath Helper:

As you can see, I learned how to use XPath to parse MSBuild project files. My problem was not using XML namespaces correctly. XPath Helper attempts to automatically find XML namespaces and then add them to an XmlNamespaceManager (see the ListBox on the right - it lists all namespaces that it found). That way, when an XPath expression is used, it will know to use the XmlNamespaceManager. I'm confident that it won't work in all situations, but it is a nice learning tool to play around with XPath.

If anyone is interested, I can post the code... but if I do, don't count on it having any unit tests or anything. This guy is NOT production quality.

posted on Tuesday, June 06, 2006 12:52:27 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, May 16, 2006
Anyone checked out CodePlex yet?

Looks like a Microsoft site for sharing open source applications, sort of like SourceForge, except a lot more user friendly! Apparently, it is built on Team Foundation Server, too. I just found the 1.0 release of MSBee (target .NET 1.1 with Visual Studio 2005) on there.

Check it out!
posted on Tuesday, May 16, 2006 7:51:53 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, May 15, 2006
If you've ever wondered why the increment and decrement operators weren't included in VB.NET, here's a post explaining why.

Coming from the C/C++ world, I still miss the increment (++) and decrement (--) operators, but I definitely understand why after reading. Basically, it has to do with the fact that assignments in VB are done at the statement level instead of the expression level. If you're not following, consider how you can have things like (if (x = 5) ...) in C, but you can't in VB because the = sign is used for both assignment and equality, depending on the STATEMENT. There isn't any problems in C, because equality is checked with the == sign.

Interesting.
posted on Monday, May 15, 2006 12:54:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Thursday, May 11, 2006

Prompted primarily by Karl Sequin's excellent "Understanding and Using Exceptions" post, I was recently attempting to clean up some of the generic exceptions being throw in some code and I was having trouble deciding which exception to use.

I had a BackgroundWorker that could potentially throw an exception (can't everything?) that was doing some remoting to another process. As additional information, the BackgroundWorker exposes any exceptions that might occur in the Error property off of the RunWorkerCompletedEventArgs. I didn't want to just throw e.Error because, as Karl points out, this modifies the call stack making it look my code was the source of the exception. At the same time, I couldn't just use throw, because the exception had basically already been caught and been given to me to handle.

I ended up pulling up the Object Browser in Visual Studio and filtered the list down by searching on "exception" - a nice trick to see all currently accessible exceptions. I ended up using the System.Runtime.Remoting.RemotingException, because it described exactly what I was looking at. Here's the description for it:

Public Class RemotingException

          Inherits System.SystemException

     Member of: System.Runtime.Remoting

Summary:

The exception that is thrown when something has gone wrong during remoting.

If you exclude the "during remoting" part, it basically describes any exception that can be thrown. It's almost funny in a way, because that's exactly the type of thing I was looking for. I was able to set the InnerException to my e.Error which provided me with all the information I needed.

posted on Thursday, May 11, 2006 9:27:20 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, May 05, 2006
Many thanks to Robert W. Anderson for this solution.

In his post VS2005 PowerShell Prompt, Robert details how to create your PowerShell profile script which will add the VS2005 environment variables to the PowerShell process. Quite nifty.

As a note, after setting this up, you may get a message about how your script isn't signed so it won't run. One solution is to run "Set-ExecutionPolicy RemoteSigned". I wouldn't recommend going farther than that, though. It will allow local scripts to run unsigned and will warn you if a script that was downloaded tries to run. There are still vulnerabilities, so be careful. The other alternative is to sign your script.
posted on Friday, May 05, 2006 9:42:14 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, April 26, 2006
Never heard of PowerShell you say?

I hadn't either, at least until today. That's because it used to be called Monad. Microsoft released the RC1 of PowerShell today and it is pretty sweet. Basically, it offers scripting and CLI access to the .NET Framework. Instead of using cmd.exe, you'll be using PowerShell.exe. I haven't used it much yet, but it is really cool. Just as a quick example, try this out in PowerShell:

$var = "This is a sweet"

Now, type $var. and then hit tab.

OH WOW! Tab completion for System.String from the command line!

Check it out!
posted on Wednesday, April 26, 2006 12:44:27 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, April 21, 2006
Continuing in the tradition of posts on Visual Studio WSoD's, I ran into another one today that gave me this error: "Object does not match target type."

Okay... super.

Luckily, I got some warnings with line numbers. They pointed me to a line in my designer code that looked like this:

CType(Me.MyUserControlInstance, System.ComponentModel.ISupportInitialize).BeginInit()

The other error was the same line except it was the matching EndInit call.

Similar to before, I was working with code that was in the process of being updated to the .NET 2.0 Framework. I had been working with a control that was inheriting from a .NET 1.1 control. The ISupportInitialize code had been in there for the 1.1 parent. The designer didn't mind at all until I moved the parent control over to 2.0. The solution was easy enough... just take the ISupportInitialize code out. I'm not sure if this is the recommended solution or not (I didn't Google it for too long), but it works.
posted on Friday, April 21, 2006 3:34:20 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, April 14, 2006

Ever seen this error in Visual Studio 2005?

I've seen it all too often and it is really annoying.

However, I did find a possible fix today. I was working in a project that had multiple assembly references. One of the references was using a 1.1 assembly, so it came along for the ride. By simply removing that reference, I was able to view my form without any problems. If I tried to add the reference back, I would get the designer error again. I reworked the assembly being referenced to not use any 1.1 components and... lo and behold... the designer errors stopped.

Is this just a really random bug or is this a subtle way to push people to migrate to .NET 2.0?

posted on Friday, April 14, 2006 3:09:51 PM (Central Daylight Time, UTC-05:00)  #    Comments [3]
I had some code that I was porting from .NET 1.1 to .NET 2.0 today. The code I had was checking the version of comctl32.dll to see if it was version 6 or greater to determine if the application supported visual styles or not. As I didn't write that code, I'm not sure if that is a valid way to check for visual style support in .NET 1.1.

I DO know that in .NET 2.0, that check doesn't necessarily work correctly; however, there is a new way to check that is much easier and more reliable -- Application.RenderWithVisualStyles. If you call Application.EnableVisualStyles in your Sub Main method, this boolean will be set to true. That's all you need to check!

See MSDN documentation here.
posted on Friday, April 14, 2006 11:50:11 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, April 13, 2006
I stumbled across this post by Mike Woodring today. Apparently, the UserState property from the BackgroundWorker isn't accessible from the RunWorkerCompleted event. What in the world???

Anyway, I wasn't actually looking for information on the UserState property -- I was trying to find some information on the Error property off of RunWorkerCompletedEventArgs. It gets populated when an exception is thrown in your background thread. The weird thing is, I couldn't get my code to fall in there. The debugger kept popping up on the line where I was actually throwing the exception. Believe it or not, but that is actually the intended behavior... IF you're running in the debugger. Check out this post on the MSDN forums. If you're running standalone, then the Error property will be set as expected and you can check it. I wonder if you can continue on the exception and get to the RunWorkerCompleted event. I'll have to try that.

One last potential gotcha involving using the Error property: make sure it is the FIRST thing you check in your RunWorkerCompleted event handler. See this post on the MSDN forums for details there. According to Mike Woodring's post referenced above, if you access the Result property off of the RunWorkerCompletedEventArgs parameter and the Error property is populated or the Cancelled property is true, you'll get an invalid operation exception.

So now you know... and knowing is half the battle!
posted on Thursday, April 13, 2006 12:48:15 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, April 11, 2006

MSBuild is a great tool. If you're not familiar with it, it is Microsoft's new build engine which was released with .NET 2.0. Visual Studio 2005 uses it behind the scenes. If you'd like to see it in action, pull up a VS2005 Command Prompt and type "msbuild YourSolution.sln" and watch the magic. It provides a much faster way of recompiling solutions and projects than reopening Visual Studio.

MSBuild runs off XML files. If you'd like to see one, just open up one of your vbproj or csproj files. Visual Studio projects default to the MSBuild format. Unfortunately, the solution files still aren't in an XML format. Because it uses XML, you can extend a build to do any number of tasks. I'll walk you through a very simple example.

My task is a Replace task that simple takes an input string (likely a file path or assembly name), an old value, and a new value and returns a value with all old values replaced with new values. It works exactly like the Replace method off of String objects.

First off, create a new Class Library project in Visual Studio. You'll need to add a reference to Microsoft.Build.Framework and to Microsoft.Build.Utilities. Next, for your class, inherit from Microsoft.Build.Utilities.Task. You'll be forced to override an Execute method. That's really all it takes to get a custom task. Everything else is driven off of public properties that are described by specific MSBuild attributes like "Required" or "Output".

Here's the source for my Replace task:

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

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

namespace Tasks
{
    
/// <summary>
    /// Custom MSBuild task to perform String replacement. Primarily used for
    
/// Namespace to directory replacement (DTC.NRA.App -> DTC\NRA\App).
    
/// </summary>
    public class Replace : Task
    {
        
string _input;
        [
Required]
        
public string Input
        {
            
get { return _input; }
            
set { _input = value; }
        }

        
string _oldValue;
        [
Required]
        
public string OldValue
        {
            
get { return _oldValue; }
            
set { _oldValue = value; }
        }

        
string _newValue;
        [
Required]
        
public string NewValue
        {
            
get { return _newValue; }
            
set { _newValue = value; }
        }

        
string _results;
        [
Output]
        
public string Results
        {
            
get { return _results; }
            
set { _results = value; }
        }

        
public override bool Execute()
        {
            
bool success = true;
            
try
            {
                Results = Input.Replace(OldValue, NewValue);
            }
            
catch (Exception e)
            {
                Log.LogErrorFromException(e);
            }
            
return success;
        }
    }
}

The XML below is how I'm currently using this task.

<UsingTask TaskName="Tasks.Replace" AssemblyFile="C:\Development\References\MSBuildTasks.dll" />
<
PropertyGroup>
  <
RootDirectory>C:\Development\Build\</RootDirectory>
</
PropertyGroup>
<
Target Name="AfterBuild">
  <
Replace Input="$(RootNamespace)" OldValue="." NewValue="\">
    <
Output TaskParameter="Results" PropertyName="NamespaceDirectories" />
  </
Replace>
  <
CreateItem Include="$(OutputPath)\**\*.*">
    <
Output TaskParameter="Include" ItemName="FilesToArchive" />
  </
CreateItem>
  <
Copy SourceFiles="@(FilesToArchive)" DestinationFolder="$(RootDirectory)$(NamespaceDirectories)\%(FilesToArchive.RecursiveDir)" />
</
Target>

As you can see, I've got the UsingTask which references the assembly I built. Then you can use the Replace task like any other provided task. The above exactly can be copied into a Visual Studio project and it will copy the output files from your build into the RootDirectory you specify with the root namespace making up the folders beneath it (i.e. give the namespace System.Windows.Forms, this will copy your compiled assemblies to c:\Development\Build\System\Windows\Forms\*).

posted on Tuesday, April 11, 2006 12:43:25 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, March 31, 2006

Recently, I was adding the ability to open files from an application at work. Luckily, I had run into this situation before, so I knew that you could run a Process.Start on the file in question and have Explorer open it for you. What I didn't know was that it would throw a Win32Exception if the file didn't have an associated program to open it. My next step was what any good developer would do: Google it.

Fairly early on in my searching, I came across a post by Ned Batchelder that described the EXACT same scenario I was working on! Ned wanted to open a file with an unknown extension from a managed application just like me. He details his Google search and explains how he discovered information about the API functions, ShellExecute and ShellExecuteEx. Basically, you can call ShellExecuteEx with an "open" verb and Explorer will attempt to open the file. If it fails with an SE_ERR_NOASSOC error, then call ShellExecuteEx again but using an "openas" verb. Doesn't sound too bad, though some code snippets still would've sped the process up for me :-) I did learn it better this way, though.

Anyway, here's where I started. First, I pulled in the definition for the SHELLEXECUTEINFO structure.

Friend Structure SHELLEXECUTEINFO
    
Public cbSize As Integer
    Public fMask As SEE_MASK
    
Public hwnd As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpVerb As String
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpFile As String
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpParameters As String
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpDirectory As String
    Dim nShow As Integer
    Dim hInstApp As SE_ERR
    
Dim lpIDList As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpClass As String
    Public hkeyClass As IntPtr
    
Public dwHotKey As Integer
    Public hIcon As IntPtr
    
Public hProcess As IntPtr
End Structure

Next, I created definitions for the SW, SEE_MASK, and SE_ERR constants.

#Region " SW Constants "
    Friend Enum SW As Integer
        HIDE = 0
        SHOWNORMAL = 1
        NORMAL = 1
        SHOWMINIMIZED = 2
        SHOWMAXIMIZED = 3
        MAXIMIZE = 3
        SHOWNOACTIVATE = 4
        SHOW = 5
        MINIMIZE = 6
        SHOWMINNOACTIVE = 7
        SHOWNA = 8
        RESTORE = 9
        SHOWDEFAULT = 10
        FORCEMINIMIZE = 11
        MAX = 11
    End Enum
#End Region

#Region " SEE_MASK Constants "
    Friend Enum SEE_MASK As Integer
        CLASSNAME = &H1
        CLASSKEY = &H3
        IDLIST = &H4
        INVOKEIDLIST = &HC
        ICON = &H10
        HOTKEY = &H20
        NOCLOSEPROCESS = &H40
        CONNECTNETDRV = &H80
        FLAG_DDEWAIT = &H100
        DOENVSUBST = &H200
        FLAG_NO_UI = &H400
        UNICODE = &H4000
        NO_CONSOLE = &H8000
        ASYNCOK = &H100000
        HMONITOR = &H200000
        NOZONECHECKS = &H800000
        NOQUERYCLASSSTORE = &H1000000
        WAITFORINPUTIDLE = &H2000000
        FLAG_LOG_USAGE = &H4000000
    End Enum
#End Region

#Region " SE_ERR Constants "
    Friend Enum SE_ERR As Integer
        SE_ERR_FNF = 2              ' file not found
        SE_ERR_PNF = 3              ' path not found
        SE_ERR_ACCESSDENIED = 5     ' access denied
        SE_ERR_OOM = 8              ' out of memory
        SE_ERR_DLLNOTFOUND = 32
        SE_ERR_SHARE = 26
        SE_ERR_ASSOCINCOMPLETE = 27
        SE_ERR_DDETIMEOUT = 28
        SE_ERR_DDEFAIL = 29
        SE_ERR_DDEBUSY = 30
        SE_ERR_NOASSOC = 31
    End Enum
#End Region

Finally, I created my definition for the ShellExecuteEx function.

<DllImport("shell32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Friend Shared Function ShellExecuteEx( _
        
ByRef lpExecInfo As SHELLEXECUTEINFO) As Boolean
End Function

I stuck all of this into a NativeMethods class and tried the code below:

Dim info As New NativeMethods.SHELLEXECUTEINFO
info.cbSize = Marshal.SizeOf(info)
info.lpDirectory = Path.GetDirectoryName(fileToStart)
info.lpFile = Path.GetFileName(fileToStart)
info.nShow = NativeMethods.SW.SHOWDEFAULT
info.lpVerb =
"open"
info.fMask = NativeMethods.SEE_MASK.FLAG_NO_UI Or NativeMethods.SEE_MASK.FLAG_DDEWAIT

If Not NativeMethods.ShellExecuteEx(info) Then
    If info.hInstApp = NativeMethods.SE_ERR.SE_ERR_NOASSOC Then
        Dim sinfo As New NativeMethods.SHELLEXECUTEINFO
        sinfo.cbSize = Marshal.SizeOf(info)
        sinfo.lpVerb =
"openas"
        sinfo.lpDirectory = Path.GetDirectoryName(fileToStart)
        sinfo.lpFile = Path.GetFileName(fileToStart)
        sinfo.nShow = NativeMethods.SW.SHOWDEFAULT
        NativeMethods.ShellExecuteEx(sinfo)
    
End If
End If

UPDATED (9/12/2006): Many thanks to Michael and his comment regarding using the SEE_MASK.FLAG_DDEWAIT. That fixed all of the problems I was running into regarding the above code. (see the usage on info.fMask)

A quick note about the code: Ned mentioned in his post that he got the ERROR_NO_ASSOCATION error instead of SE_ERR_NOASSOC. Well, the ERROR_NO_ASSOCATION is what is returned in the Win32 error (Marshal.LastWin32Error). The SE_ERR_NOASSOC is returned in the hInstApp (see MSDN documentation here).

See any problems with that? I certainly didn't (and still don't). It works like a charm for files with associations... however, it would only work one time for files without any associated program. Afterwards, it wouldn't give me anything... no errors, nada, zilch. After a few tries, an AccessViolationException would get thrown. Why? I have no idea. I tried various things to see if I should be cleaning up memory somewhere but I couldn't find anything. I did find out that if I just called ShellExecuteEx with the "openas" verb the first time, I wouldn't get any problems at all. What in the world???

As a result of the strange behavior, I changed my code slightly to look like this:

Try
    Using p As New Process
        p.StartInfo.FileName = fileToStart
        p.StartInfo.UseShellExecute =
True
        p.Start()
   
End Using
Catch win32Ex As Win32Exception
   
Dim sinfo As New NativeMethods.SHELLEXECUTEINFO
    sinfo.cbSize = Marshal.SizeOf(sinfo)
    sinfo.lpVerb =
"openas"
    sinfo.lpDirectory = Path.GetDirectoryName(fileToStart)
    sinfo.lpFile = Path.GetFileName(fileToStart)
    sinfo.nShow = NativeMethods.SW.SHOWDEFAULT

   
If Not NativeMethods.ShellExecuteEx(sinfo) Then
        Throw New Win32Exception
   
End If
End Try

The above code is working like a charm. I still have no idea why my first example won't work for me. If anyone has any ideas or suggestions, please let me know. I haven't worked with Interop between managed and unmanaged code very much. My experience up to this point has primarily been an entirely managed project or an entirely unmanaged project (and that only in college).

NOTES: Here are some resources I found while researching this:

[http://www.nedbatchelder.com/blog/20050318T070512.html]
[http://www.pinvoke.net/default.aspx/shell32/ShellExecuteEx.html]
[http://www.pinvoke.net/default.aspx/Constants/SW.html]
[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/structures/shellexecuteinfo.asp]

Also, be sure to look at the ShellAPI.h header file!

posted on Friday, March 31, 2006 9:08:06 AM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Friday, March 24, 2006
I've been using the System.Collections.Generic namespace an awful lot lately. I really like it, too. I use the List<T> collection all the time. It is so much better than inheriting from the CollectionBase to get a type-safe collection. I won't go into the reasons here, though. This post is about Predicates. If you have a List<T> collection, you'll notice it exposes a Find method that takes a Predicate as an argument. A Predicate is just a delegate that takes an object of type T and returns a boolean. When you call the Find method, it will call your Predicate for each object in its collection until your Predicate returns true. Looks like a nice, clean way to search collections, right?

Well, if you're using C# anyway.

Compare the following VB.NET code and C# code:

VB.NET :

    1 Module Module1

    2     Sub Main()

    3         Dim tests As New List(Of Test)

    4         tests.Add(New Test("test"))

    5         tests.Add(New Test("test2"))

    6         tests.Add(New Test("test3"))

    7 

    8         toSearchFor = "test2"

    9         Console.WriteLine(tests.Find(AddressOf FindTest).ID)

   10     End Sub

   11 

   12     Private toSearchFor As String = ""

   13     Private Function FindTest(ByVal val As Test) As Boolean

   14         Return val.ID = toSearchFor

   15     End Function

   16 

   17     Private Class Test

   18         Public ID As String

   19         Public Sub New(ByVal id As String)

   20             Me.ID = id

   21         End Sub

   22     End Class

   23 End Module


C# :

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 

    5 namespace CSPredicateExample

    6 {

    7     class Program

    8     {

    9         static void Main(string[] args)

   10         {

   11             List<Test> tests = new List<Test>();

   12             tests.Add(new Test("test"));

   13             tests.Add(new Test("test2"));

   14             tests.Add(new Test("test3"));

   15 

   16             string toSearchFor = "test2";

   17             Console.WriteLine(tests.Find(delegate(Test val) { return val.ID == toSearchFor; }).ID);

   18         }

   19 

   20         class Test

   21         {

   22             public string ID;

   23             public Test(string id)

   24             {

   25                 this.ID = id;

   26             }

   27         }

   28     }

   29 }


I've bolded the important part. In case you missed it, it is the toSearchFor variable. The only way for a predicate to find a value is to compare it to another value; however, there is no way to pass this value to the predicate outside of an external variable. In C#, this isn't a problem because of closures. In C#, the wrapping of the toSearchFor variable so that it is accessible to the inner anonymous delegate is the closure. VB.NET does not have this feature (yet!). Because of this limitation in VB.NET, you have to have a class-level variable or global variable to effectively use predicates so that your predicate has something to compare to! It seems to me that the lack of closures effectively cripples the use of predicates in VB.

Because of features like this, I am really looking forward to the next release of VB. Of course, with LINQ, will I even care about predicates then?

I would be very interested to know if anyone has any other suggestions on ways to effectively use the predicate model in VB.

UPDATE: Wow, go Paul Stovell! Instead of complaining like I did, Paul actually did something to get around this limitation in the current version of VB.NET and created an implementation of "Almost-anonymous" methods! His method also shows how to use the Widening overloaded operator in VB.NET, which I haven't seen much of. Cool!
posted on Friday, March 24, 2006 5:58:16 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, March 22, 2006
I've blogged about FileHelpers before. I like it a lot.

Since then, Marcos has added even more great features to it including support for .NET 2.0 Generics and a new Wizard application that really increases the speed in developing new records.

Marcos has an article up on CodeProject as well as a FileHelpers website with examples and a support forum.

Seriously, if you're still using String.Substring calls to parse out flat files, give the library a try.
posted on Wednesday, March 22, 2006 2:02:17 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
I remember the first time I ran into an ASP.NET error talking about event validation (specifically while playing with CommunityServer). The solution I discovered at the time was to just disable event validation by setting enableEventValidation to false in the web.config file.

Well, thanks to a couple of posts from K. Scott Allen, I now have a much better understanding of event validation and why it is a really good thing. Check out his posts here and here.

Thanks Scott!
posted on Wednesday, March 22, 2006 8:35:30 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, March 08, 2006

I've blogged about the FlowLayoutPanel in the past. It is a highly useful control in certain circumstances, but it doesn't behave as expected a lot of the time. In trying to better explain how it works, I created a small test program to show what it is doing. Here is what it looks like:

It primarily demonstrates how FlowDirection and WrapContents affect controls in the FlowLayoutPanel, particularly dynamically added controls. If you click one of the dynamically added buttons, it will pull up that buttons PropertyGrid, which will allow you to edit its properties. This is useful to examine the effects of sizing, anchoring, and docking.

Here's the link to the VS2005 solution if you're interested in playing around with it. It's in C#. I wanted to play around with anonymous delegates :-)

posted on Wednesday, March 08, 2006 8:33:27 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, March 06, 2006
This may not be new for everyone, but I just learned it today. In webpages, to set focus to a control after a page has loaded, you handle the body's onload event and then call the focus method off of the control.

In .NET, there is a focus method off of controls, but it doesn't work if the control isn't visible... i.e. in the constructor or in the Load event. To get around this, use the ActiveControl property off of the Form or UserControl, like so:

  105 Me.ActiveControl = Me.txtTo

Not too bad, eh? In this example, Me.txtTo will have focus when the Form or UserControl is displayed. Just make sure it is in the Load event. It didn't seem to work for me in the constructor (even after the InitializeComponent call). Of course, I only tried it once...

(Google'd and found via here)
posted on Monday, March 06, 2006 4:49:13 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

Lately, I've been doing some work with integrating some of my managed applications with Outlook. There are a lot of code examples and articles out there on using the Outlook COM interop library for tying into Outlook, but be prepared for a lot of security prompts for the user. I understand the reasoning behind those security prompts, but man are they annoying.

You basically have two options at this point if you don't like the prompts. Extended MAPI or Outlook Redemption. Seriously, those seem to be the only two options available, unless your application is actually an add-in using VSTO. Extended MAPI is essentially the low-level side of Outlook. To program against it, you're looking at using C/C++ or Delphi, because your only interface is header files. I took a look at it and it is HAIRY. If you are interested in that option, though, check out MAPIEx at the Code Project. It has some great examples of using Extended MAPI and also showed me enough to scare me away from this option. I would love to spend my company's time and resources learning this and code in C++, but I don't think they would appreciate that very much.

Okay, next. Outlook Redemption. It is a COM wrapper around the Extended MAPI interface that works great. Dmitry Streblechenko created a lot of safe objects around their Extended MAPI counterparts. You code against the Outlook Interop library (add a COM reference to "Microsoft Outlook 11.0 Object Library") and tie that in with Redemption. Everyone uses this thing. Just about every newsgroup post, website, etc. that mentions tying into Outlook recommends this library. I guess this is another recommendation.

My only real complaint with Redemption had to be the stupid Fields collection off of just about every Redemption object. For example, let's look at the Redemption.AddressEntry. It exposes a name, address, and a few other handy properties, but that is about it. If you want to get anything else, you have to use the Fields collection, which takes an Integer and returns an Object. The Fields collection could be compared to a Dictionary object in the .NET Framework. The name is a unique integer that is a lookup to a value. A little annoying but hey, if we have constants, who cares right? Right??? ... What do you mean we don't have any constants? Ohhh, we have to find those out for ourself or buy Outlook Spy! I hate magic numbers!

I was fairly confident that the lookup constants were defined somewhere so I began hunting them down and discovered the MAPITags.h file (mine was at C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include). All of the constants use a macro called PROP_TAGS (see MAPIDefS.h) that takes a ULong propID and a ULong propType. Internally, Outlook uses a multitude of different property types like PT_NULL, PT_LONG, PT_BOOLEAN, etc. The PROP_TAG macro takes the type and a unique lookup. That's why the Fields dictionary returns an Object: it might be a long or a boolean or a string or an internal Outlook structure. I ended up writing a console application that read in a header file and spit out a list of VB constants. The regular expression I used was "\#define\s+?(?<name>[\w|\d]+?)\s+PROP_TAG\(\s?(?<type>[\w\d]+?),\s?(?<id>[\w\d]+?)\)".

Anyway, long story short, I'm working with Outlook now and it is really cool. I'm able to, based on a name and my generated VB constants, lookup a property of a contact in my address book. Another programmer and I have been spamming each other testing with meeting appointments and emails ever since. Fun, eh?

posted on Monday, March 06, 2006 8:08:35 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, March 02, 2006
Thanks to a post from Jeff Atwood, I discovered the blog of Francesco Belana. He's the author of some great books including Programming Visual Basic.NET, which my company has been using to get our developers up to speed on .NET.

I'd like to point out a couple of posts of his that give great examples of using generics in .NET 2.0.

Check them out:
posted on Thursday, March 02, 2006 8:04:15 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, March 01, 2006
Roy Osherove posts today about different ways to accomplish thread-safe GUIs using .NET 2.0... and C#.

Since we're primarily using VB.NET at work, we don't get the anonymous delegate love... oh well. Ever since I discovered that JavaScript could do the same thing*, I've been wanting to use it in managed code as well. I guess I'll have to do it on my own time for now.

* like so:  document.body.onload = function () { alert("I've been loaded!") }
posted on Wednesday, March 01, 2006 7:46:28 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Saturday, February 18, 2006

I'd like to talk a little bit about what I did to get my personal site up and running.

First off, I wanted it to support blogging for my wife and I. I tried a lot of different ASP.NET blogging engines like CommunityServer and SUB (Single User Blog). CommunityServer is great, but it had way too much for my needs. I really liked SUB, particularly version 2 because it was in ASP.NET 2.0 and Master pages rule. My only problems with it were probably more my fault, but I had some weird issues with the ASP.NET Development Server (aka Cassini). Something about files existing in two different places. I imagine if I had installed the Web Application Project things might have worked better. Still, I would suggest checking out SUB if you can.

I ended up going with dasBlog. I was already somewhat familiar with it and it is extremely easy to set up. It allows multiple logins by adding multiple users to the siteConfig.config file. My only obstacle was encorporating my own pages (Photos) and creating my own theme. I'd like to say thanks to James Snape for the Project84 theme (the default here), because I based my new theme off of it. If you're going to create your own dasBlog theme, I recommend starting with one you already like. Copy it to a new directory under the themes folder and then started changing things. See what happens. That's really all I did. Since dasBlog is written under ASP.NET 1.1, we can't use Master pages, but we get something pretty close. dasBlog uses template files that are very easy to change and that give you almost complete control over the way your blog will look. If you're interested in using my theme, let me know and I'll zip it up and post it.

The other primary addition to the standard dasBlog setup is that I added a Photos page written in ASP.NET 2.0. It is proof that you can run ASP.NET 1.1 and 2.0 side by side for relatively simple applications. My photos page relies primarily on Picasa, which is a great photo album application. I'm relying primarily on the "Make a webpage..." ability, which will export a selected album into a directory with appropriately sized images, thumbnails, and an index file. The best part is that you can choose to export to an XML file. The XML file is very simple, but it provides a simple way to provide image galleries in a format other than the Picasa defaults. My page basically has a Galleries subdirectory with exported albums. It grabs all of the albums in the gallery and parses the XML file to display the images. All my wife has to do to add albums is export from Picasa and drop the folder into the Galleries directory. How easy is that?

I'll be the first one to admit that there are issues with my Photos page (the exported albums' name are exactly the safest for the web), but it works. At some point, I'd like to clean up the names and add the ability to display our comments as well as to take comments from visitors to the site.

That pretty much sums up what I've done with the site. If you'd like to know more, let me know!

posted on Saturday, February 18, 2006 8:24:05 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, February 16, 2006

Benjamin Wulfe wrote an article for the April issue of MSDN magazine about a utility called ManagedSpy, which is basically the managed version of Spy++. If you're unfamiliar with Spy++, it will let you look at running Windows processes and see messages, classes, and other WinAPI-related information. As the article notes, from a managed Windows Forms perspective, that isn't exactly where we typically work. ManagedSpy uses a TreeView and a Properties window to display controls and layout in a managed form. It can also listen and log events raised from the form and its controls.

One of the particularly interesting things to me is the ControlProxy, which is exposed from a managed C++ library called ManagedSpyLib. There is discussion about how to use Windows hooks to get to other windows currently running and even a section on using ManagedSpyLib for unit testing, because it has the ability to send Windows messages to other processes.

Check it out!

(via jfo's coding)

UPDATE: As an aside, be careful with this tool. I tried running it while RssBandit was running (which is a managed Windows application... and it blew up. Hard. As in, let's take them BOTH down. Luckily, it does come with code, so you can have fun with it. After all, I would like to learn some Managed C++ ;-).

posted on Thursday, February 16, 2006 7:20:43 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, February 15, 2006

Let's say you have the following class:

   51 Public Class Person

   52     Private _name As String

   53 

   54     Public Event NameChanged As EventHandler

   55 

   56     Public Property Name() As String

   57         Get

   58             Return _name

   59         End Get

   60         Set(ByVal value As String)

   61             _name = value

   62             OnNameChanged(EventArgs.Empty)

   63         End Set

   64     End Property

   65 

   66     Protected Sub OnNameChanged(ByValAs EventArgs)

   67         RaiseEvent NameChanged(Me, e)

   68     End Sub

   69 End Class

We've set up the [Property]Changed events so that DataBinding will work correctly. Now, let's assume you want to bind the name property over to the text property of your TextBox control. We'll go the simple data binding route here for simplicity.

    3 Public Class Form1

    4     Private txtName As New TextBox

    5     Private _person As New Person

    6 

    7     Public Sub New()

    8         ' This call is required by the Windows Form Designer.

    9         InitializeComponent()

   10 

   11         ' Add any initialization after the InitializeComponent() call.

   12         Me.Controls.Add(txtName)

   13 

   14         _person.Name = "cool"

   15         txtName.DataBindings.Add("Text", _person, "Name")

   16     End Sub

   17 

   18     Private Sub Form_Click(ByVal sender As ObjectByValAs EventArgs) _

   19         Handles Me.Click

   20         _person.Name = "clicked"

   21     End Sub

   22 End Class

There! Now the txtName will display "clicked" whenever you click on the form. Magic! Now, let's change that Click event like so to see what happens:

   18     Private Sub Form_Click(ByVal sender As ObjectByValAs EventArgs) _

   19         Handles Me.Click

   20 

   21         Dim newPerson As New Person

   22         newPerson.Name = "new person"

   23         _person = newPerson

   24     End Sub

Why would I ever want to do is this way? Well, let's say you're remoting somewhere to get your data and your background thread returns a fully populated object. The easiest thing to do is to just point to the new object... except that it doesn't work.

All we did was change our instance over, but the textbox never changed. Why not? Because of REFERENCES, POINTERS, and MEMORY ADDRESSES! That's why! Check this out:

   18     Private Sub Form_Click(ByVal sender As ObjectByValAs EventArgs) _

   19         Handles Me.Click

   20 

   21         Dim newPerson As New Person

   22         newPerson.Name = "new person"

   23 

   24         Debug.WriteLine("Are references equal? "Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))

   25         _person = newPerson

   26         Debug.WriteLine("Are references equal? "Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))

   27     End Sub

Whoa! The first Debug.Writeline will give you TRUE, but the second will give you FALSE. You see, understanding how references and pointers work is important. The textbox's DataSource is holding onto a reference of the old Person instance. You now have two different instances in memory, whether you like it or not.

What do you do about it? Well, as far as I can tell, you can either update your DataSource reference (it did change after all) or you can move your properties over manually so that your references don't change. I'm open to suggestions on other methods here.

posted on Wednesday, February 15, 2006 1:05:04 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, February 08, 2006

Visual Studio Hacks posted a new "Ask the Pros" article detailing some of the pros' favorite keyboard shortcuts. Check it out here. There are quite a few good shortcuts in there, like the Comment and Uncomment code blocks (Ctrl-K-C and Ctrl-K-U respectively). Some of my new favorites have to do with additional functionality provided by snippets in Visual Studio 2005, specifically the Edit.SurroundWith command, which is Ctrl-K-S by default. It makes it a cinch to add code to new regions, much like the Visual Studio 2003 Region add-in. As the article says, a nice way to learn more shortcuts is to check them out in Visual Studio for yourself - under Tools, Options, and Keyboard.

Try them yourself and become a true Keyboard Ninja!

posted on Wednesday, February 08, 2006 7:53:13 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Tuesday, January 24, 2006

I've been experimenting with the FlowLayoutPanel. There are a few catches to using it that can cause some confusion. In my case, the confusion came from anchoring and/or docking. I was dynamically adding some listviews to my panel to display results of data. There would be one to many listviews depending on the type of report the user requested. Having come from developing in ASP, it is still my first inclination to just create a table for each section and add it. The flow of the HTML would handle the rest. I figured I could get a FlowLayoutPanel and just add controls as needed and get similar functionality.

That was true to a degree; however, anchoring doesn't perform as you might think. If you anchor to the left and right after setting the width, if there is only one control in the panel, it will drop down to a zero width. The actual behavior is that, if you anchor to the left and right, it will assume the width of the widest control already on the FlowLayoutPanel. The same is true if you set the Dock property to Fill. Check out this article on MSDN to see what I mean. The behavior also depends on the FlowDirection property.

Everything works great if your panel isn't going to resize itself. You can just set the first control's width to the width of the panel minus a few pixels and Dock.Fill everything else. If you want it to resize as you resize the form, though, it is looking like you'll have to handle some layout events.

Here's some code to get you started:

Public Class Form1

    Private WithEvents flowPanel As New FlowLayoutPanel()

 

    Public Sub New()

        ' This call is required by the Windows Form Designer.

        InitializeComponent()

 

        ' Add any initialization after the InitializeComponent() call.

 

        ' DON'T FORGET THESE LINES!

        flowPanel.Dock = DockStyle.Fill

        flowPanel.FlowDirection = FlowDirection.TopDown

 

        Me.Controls.Add(flowPanel)

 

        AddListView()

        AddListView()

    End Sub

 

    Private Sub AddListView()

        Dim totalList As New ListView()

        totalList.View = View.Details

 

        ' If first control, then set a width; otherwise, Dock.Fill it.

        If Me.flowPanel.Controls.Count > 0 Then

            totalList.Dock = DockStyle.Fill

        Else

            totalList.Width = Me.flowPanel.Width - 10

        End If

 

        totalList.Columns.AddRange(New ColumnHeader() _

            {GetColumnHeader("Col 1"), _

            GetColumnHeader("Col 2"), _

            GetColumnHeader("Col 3")})

 

        Dim item As ListViewItem = totalList.Items.Add("Row 1")

        item.SubItems.Add("1234.00")

        item.SubItems.Add("5678.00")

 

        item = totalList.Items.Add("Row 1")

        item.SubItems.Add("1234.00")

        item.SubItems.Add("5678.00")

 

        item = totalList.Items.Add("Row 1")

        item.SubItems.Add("1234.00")

        item.SubItems.Add("5678.00")

 

        Me.flowPanel.Controls.Add(totalList)

    End Sub

 

    Private Function GetColumnHeader(ByVal text As String) As ColumnHeader

        Dim col As New ColumnHeader()

        col.Text = text

        Return col

    End Function

 

    Private Sub flow_Layout(ByVal sender As Object, _

        ByVal e As System.Windows.Forms.LayoutEventArgs) _

        Handles flowPanel.Layout

 

        Dim flowLayout As FlowLayoutPanel = DirectCast(sender, FlowLayoutPanel)

        If flowLayout.Controls.Count > 0 Then

            flowLayout.Controls(0).Width = flowLayout.Width - 10

        End If

    End Sub

End Class

Here's MSDN another article that gives some basic information on the FlowLayoutPanel.

posted on Tuesday, January 24, 2006 8:09:23 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, January 20, 2006
I discovered today that the new FtpWebRequest/FtpWebResponse classes might not be the best options for connecting to FTP servers, at least unless you're in control of the FTP server. The classes make some assumptions about the remote FTP server, like the server's file system.

I was working on converting an application that sends files to a customer's FTP server and I thought I would use the FtpWebRequest and FtpWebResponse classes. The problem is that the customer's FTP server is running on VMS! I know, that isn't very common, but the file system in VMS is NOT like Windows or Unix. Folders aren't separated by "\" or "/" so when a change directory (CWD) command is sent, you can't assume that folders are delimited by one of those characters! When you try to list the files in the directory, it sends a CWD command to change directory to the current directory (why, I don't know) with a "/" at the end. Predictably, I get a 550 error back with a "file specification syntax error."

I haven't found a workaround other than coding it myself. If anyone has any suggestions, let me know.


NOTE: I used Ethereal to observe what was being sent and received. It is a great utility for watching network traffic.
posted on Friday, January 20, 2006 4:03:07 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
Here is a little gotcha with some changes to the way that .NET 2.0 handles COM interoperability. You probably won't run into this problem unless you're converting a project from 1.1 to 2.0.

We had a little command line application that took did some background processing for us that was written in 1.1. We moved it over to 2.0 because we wanted to take advantage of the new FTP capabilities in the 2.0 framework (see FtpWebRequest/FtpWebResponse). If you add a reference to a COM object in .NET 1.1, the typical object that you'll create on the managed side will have a "Class" suffix (i.e. MyCoolComObjectClass as opposed to MyCoolComObject). If you convert to 2.0, it doesn't change that code either...

However, you might see an exception like this if you start using it:

"System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to class type 'ComLibrary.MyCoolComObjectClass'. COM components that enter the CLR and do not support IProvideClassInfo or that do not have any interop assembly registered will be wrapped in the __ComObject type. Instances of this type cannot be cast to any other class; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface."

What do you do? Take the class off the end of your COM object (MyCoolComObjectClass -> MyCoolComObject).

That's it.

AUTOMAGICAL!

(Thanks to this forum posting for the info!)

posted on Friday, January 20, 2006 10:57:24 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, January 13, 2006

Continuing on my thoughts from yesterday regarding Windows Forms validation, I first began using Michael Weinhardt's validation library on MSDN after doing a project conversion from 1.1 to 2.0, but there were a few things that I personally wanted to do that weren't currently supported, like validation on controls like the DateTimePicker. It would have been quite easy to add support, but I began developing a picture in my mind of a slightly different approach to validation. His solution was very designer oriented, but I wanted a more code-centric approach.

What I came up with was basically a GroupValidator class that took a control and a delegate to a provided validation function. The class took care of calling the validation function by hooking into the Validating event and then setting the appropriate error message. It added the control and delegate to a collection which could then be looped through so that you could check to see if the entire group was valid. It is pretty basic, but it works quite well so far. I'd like to expand it a little bit to add more automation, but it gets the job done right now.

Here's an example of usage:

Public Class Form1

    Private _validator As New GroupValidator()

 

    Public Sub New()

        ' This call is required by the Windows Form Designer.

        InitializeComponent()

 

        ' Add any initialization after the InitializeComponent() call.

        _validator.AddControl(Me.TextBox1, _

            AddressOf IsTextValid, "Text not valid")

        _validator.AddControl(Me.TextBox2, _

            AddressOf IsTextValid, "Test not valid2")

        _validator.AddControl(Me.TextBox3, _

            AddressOf IsTextValid, "Enter something")

        _validator.AddControl(Me.TextBox4, _

            AddressOf IsTextValid, "Please")

    End Sub

 

    Private Function IsTextValid(ByVal c As Control) As Boolean

        If c.Text.Length > 0 Then

            Return True

        Else

            Return False

        End If

    End Function

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        MessageBox.Show(_validator.IsValid.ToString)

    End Sub

End Class

It is pretty simple as you can see. If you're interested in the code, drop a line and I'll email it or post it.

posted on Friday, January 13, 2006 8:53:27 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, January 12, 2006

I've been doing some research on best practices for validation in Windows Forms, and I came across a nice set of MSDN articles by Michael Weinhardt where he shows how to create a validation framework that is very similar to the validators found in ASP.NET (i.e. required field validator, regular expression validator, etc). It includes container and form validators that basically manage the control validators already on the form. The link to the articles is to the third article in the series, but the download contains all of the source. His code was apparently incorporated into the Genghis framework as well.

I'm interested in something similar for 2.0, but I haven't found anything. I did see an older post from Chris Sells about moving Genghis over to 2.0, but I haven't seen any updates on that. I'm considering doing it myself, but if anyone has any better ideas, I'm open.

posted on Thursday, January 12, 2006 2:07:18 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, January 05, 2006

My post earlier today referred to the FileHelpers library by Marcos Meli.

Wow, do I wish I had known about this earlier. This thing is great! With a few easy attributes, you can use a business object as a layout for fixed-length files! Okay, I guess an example would help. Here's some VB code I whipped up to test this library out.

Imports FileHelpers

Public Class MainForm
    Private Sub MainForm_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Load

        Dim engine As New FileHelperEngine(GetType(Record))

        Dim records() As Record = _
            DirectCast(engine.ReadString("123456789  2005-01-01"), _
            Record())

        Debugger.Break()

        Dim res As String = engine.WriteString(records)

        Debugger.Break()
    End Sub
End
Class

<FixedLengthRecord()> _
Public
Class Record
    <FieldFixedLength(11)> _
    Public BillNumber As String

    <FieldFixedLength(10), _
    FieldConverter(ConverterKind.Date, "yyyy-MM-dd")> _
    Public BillDate As DateTime
End
Class

At each Debugger.Break line, I checked my values and this thing is great. records(0).BillNumber is "123456789  " and records(0).BillDate is a converted DateTime set to 1/1/2005.

If you deal with fixed-length or delimited files on a regular basis, this library might be a great option for you.

Thanks Marcos!

UPDATE: Version 1.3.1 was released recently, so I have updated my example code to use the new ReadString and WriteString methods.

posted on Thursday, January 05, 2006 1:53:42 PM (Central Standard Time, UTC-06:00)  #    Comments [1]

By way of Larkware, I came across the FileHelpers library written by Marcos Meli. It looks like a great solution for dealing with delimited or fixed length file formats. The majority of the output formats from our backend systems at work are fixed length file formats, which can be a pain to parse. I had actually written a library to parse them and reference portions of each line by name (sort of a named index to portions of a line), but this looks like a much cleaner approach. I'll dig into this some more and post my thoughts on it.

posted on Thursday, January 05, 2006 1:21:07 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Tuesday, January 03, 2006

I ran into a strange situation this afternoon with visual inheritance and threading. I've created a master form for my area at work so that we can have a common menu in all of our applications. It also provides a public readonly property that has information about the currently logged on user. The user's information is pulled using a BackgroundWorker so that the form can display promptly.

Here's the situation, a few days ago, I added a ManualResetEvent so that, if access to the User property was attempted before the thread completed, a NullReferenceException wouldn't occur. I had already put code in so that the initial loading of the user's information would not fire in design mode. The problem that began happening was that, every time I tried to open a form that inherited from my master form, Visual Studio would lock up. I pulled up a second devenv to see where the hanging was occurring and, sure enough, it was sitting on my ManualResetEvent inside my user property. Why in the world was the designer accessing my user property?

The more astute (or experienced) of you will realize that I hadn't marked my property with that oh so important System.ComponentModel.Browsable(False) attribute! The designer was accessing the property so that it could display it in the Properties Window!

Let me be an example of what perils can occur when you play with visual inheritance and the designer!

posted on Tuesday, January 03, 2006 2:21:26 PM (Central Standard Time, UTC-06:00)  #    Comments [0]