Regular Expression Capture Groups in C#

We all know regular expressions are great for matching patterns and parsing strings, but if you really want to take your Regex game to the next level, spend some time looking at capture groups. Using capture groups–more specifically, named capture groups–makes it easier to manipulate results and replacements, and it also has a fortunate side-effect of improving readability.

To create a named capture group in a .net regular expression, use the syntax “(?<Name>pattern).” The name acts like an inline comment and allows you to reference the group using that name by using “${Name}” in Result and Replace statements.

Let’s look at an example that uses Replace. Social Security numbers are a sensitive piece of information that is often masked when displaying details. Let’s use a regular expression to hide part of the number.

var ssn = "123-45-6789";
var re = new Regex(@"\d{3}-\d{2}-(?<lastFour>\d{4})");
var masked = re.Replace(ssn, "xxx-xx-${lastFour}");
Console.WriteLine("{0} -> {1}", ssn, masked);
123-45-6789 -> xxx-xx-6789

Another common scenario is to extract a piece of data from a string. Here’s another quick example that extracts the month and year from a date string (great for grouping items in a reporting scenario!).

var date = "01/15/2012";
var re = new Regex(@"(?<month>\d{1,2})/(?<day>\d{1,2})/(?<year>\d{4})");
var monthYear = re.Match(date).Result("${year}-${month}");
Console.WriteLine("{0} -> {1}", date, monthYear);
01/15/2012 -> 2012-01

Parse US Street Addresses with Regular Expression in VB6

I have a confession to make: this article was actually implemented in VB6 originally. The meat of it is the same, but here’s the VB6 edition in case it’s of interest to anybody.

Enjoy!

Private Sub Form_Load()
    
    Call ClearControls
    
End Sub

Private Sub ClearControls()
    uxHouseNumber = ""
    uxStreetPrefix = ""
    uxStreetName = ""
    uxStreetType = ""
    uxStreetSuffix = ""
    uxApt = ""
    uxAdditionalInfo = ""
End Sub

'---------------------------------------------------------------------------------------
' Procedure : ConstructRegex
' Purpose   : Returns a regular expression pattern for parsing US street addresses
'---------------------------------------------------------------------------------------
'
Private Function ConstructRegex() As String
    
'    ConstructRegex = "^" & _                           -> begin string
'        "(\d+)" & _                                    -> 1 or more digits
'        "(\s+(?:" & GetStreetPrefixes() & "))?" & _    -> whitespace + valid prefix (optional)
'        "(\s+.*?)" & _                                 -> whitespace + one or characters
'        "(?:" & _                                      -> group (optional) {
'            "(\s+(?:" & GetStreetTypes() & "))" & _    ->   whitespace + valid street type
'            "(\s+(?:" & GetStreetSuffixes() & "))?" & _->   whitespace + valid street suffix (optional)
'            "(\s+.*)?" & _                             ->   whitespace + anything else (optional)
'        ")?" & _                                       -> }
'        "$"                                            -> end string

    ConstructRegex = "^" & _
        "(\d+)" & _
        "(\s+(?:" & GetStreetPrefixes() & "))?" & _
        "(\s+.*?)" & _
        "(?:" & _
            "(\s+(?:" & GetStreetTypes() & "))" & _
            "(\s+(?:" & GetStreetSuffixes() & "))?" & _
            "(\s+.*)?" & _
        ")?" & _
        "$"


End Function

'---------------------------------------------------------------------------------------
' Procedure : GetStreetPrefixes
' Purpose   : Returns a pipe-delimited list of valid street prefixes
'---------------------------------------------------------------------------------------
'
Private Function GetStreetPrefixes() As String
    
    GetStreetPrefixes = "TE|NW|HW|RD|E|MA|EI|NO|AU|SE|GR|OL|W|MM|OM|SW|ME|HA|JO|OV|S|OH|NE|K|N"
    
End Function

'---------------------------------------------------------------------------------------
' Procedure : GetStreetTypes
' Purpose   : Returns a pipe-delimited list of valid street types
'---------------------------------------------------------------------------------------
'
Private Function GetStreetTypes() As String
    
    GetStreetTypes = "TE|STCT|DR|SPGS|PARK|GRV|CRK|XING|BR|PINE|CTS|TRL|VI|RD|PIKE|MA|LO|TER|UN|CIR|WALK|CO|RUN|FRD|LDG|ML|AVE|NO|PA|SQ|BLVD|VLGS|VLY|GR|LN|HOUSE|VLG|OL|STA|CH|ROW|EXT|JC|BLDG|FLD|CT|HTS|MOTEL|PKWY|COOP|ACRES|ESTS|SCH|HL|CORD|ST|CLB|FLDS|PT|STPL|MDWS|APTS|ME|LOOP|SMT|RDG|UNIV|PLZ|MDW|EXPY|WALL|TR|FLS|HBR|TRFY|BCH|CRST|CI|PKY|OV|RNCH|CV|DIV|WA|S|WAY|I|CTR|VIS|PL|ANX|BL|ST TER|DM|STHY|RR|MNR"
    
End Function

'---------------------------------------------------------------------------------------
' Procedure : GetStreetSuffixes
' Purpose   : Returns a pipe-delimited list of valid street suffixes
'---------------------------------------------------------------------------------------
'
Private Function GetStreetSuffixes() As String
    
    GetStreetSuffixes = "NW|E|SE|W|SW|S|NE|N"
    
End Function

'---------------------------------------------------------------------------------------
' Procedure : uxAddress_Change
' Purpose   : Parses user input and displays components to user
'---------------------------------------------------------------------------------------
'
Private Sub uxAddress_Change()
    
    Dim strInput As String
    Dim re As RegExp
    Dim mc As MatchCollection
    Dim ma As Match
    
    Call ClearControls
    
    strInput = UCase$(uxAddress.Text)
    
    Set re = New RegExp
    re.Pattern = ConstructRegex()
    re.Global = True
    
    If re.Test(strInput) Then
        Set mc = re.Execute(strInput)
        Set ma = mc(0)
        
        uxHouseNumber = Trim$(ma.SubMatches(0))
        uxStreetPrefix = Trim$(ma.SubMatches(1))
        uxStreetName = Trim$(ma.SubMatches(2))
        uxStreetType = Trim$(ma.SubMatches(3))
        uxStreetSuffix = Trim$(ma.SubMatches(4))
        uxApt = Trim$(ma.SubMatches(5))
        
        Set ma = Nothing
        Set mc = Nothing
    Else
        uxStreetName = strInput
    End If
    
    Set re = Nothing
    
End Sub

Unit Testing Stored Procedure Calls with Rhino Mocks

Database stored procedure calls are one of the trickiest things to unit test, and there are many different approaches that can be taken. My team has run the gamut: test DBs that rollback with each run, no testing for direct data access functions (!), virtual functions w/ partial mocks (see here).

The latest approach that I’ve been using is much more straightforward and feels like a more natural use of Rhino Mocks. Let’s look at some examples of how to test some common database stored procedure tasks. (Note that these examples assume use of the Microsoft Enterprise Library.)

Create a mockable Database

The primary challenge that I’ve found with testing database code is that Microsoft.Practices.EnterpriseLibrary.Data.Database isn’t mock-friendly. However, the other “pieces” such as DbCommand and DbCommandParameterCollection are very easy to work with. So, we can solve the Database problem by creating a simple wrapper (Important! Note that the methods have the virtual keyword, which will allow them to be overridden.):

public class DatabaseWrapper
{
    private Database _database;
    private Database Database
    {
        get { return _database = _database ?? DatabaseFactory.CreateDatabase(); }
        set { _database = value; }
    }

    public virtual DbCommand GetStoredProcCommand(string storedProcedureName)
    {
        return Database.GetStoredProcCommand(storedProcedureName);
    }

    public virtual void DiscoverParameters(DbCommand command)
    {
        Database.DiscoverParameters(command);
    }
}

Executing a stored procedure

Now that we are able to mock the database object, we can write some useful tests. Let’s say you want to execute a stored procedure named “MyStoredProcedure,” and you want to write a test to verify that your code handles an exception thrown when it’s executed. That’s very easy!

Here’s my class with the function I want to test:

public class MyDataAccess
{
    public DatabaseWrapper Database { get; set; }
    public Thingy GetThingy()
    {
        Thingy thingy = null;
        try
        {
            var dbCommand = Database.GetStoredProcCommand("MyStoredProcedure");
            Database.DiscoverParameters(dbCommand);
            var result = dbCommand.ExecuteNonQuery();
            // populate thingy
        }
        catch (Exception ex)
        {
            // handle exception
        }
        return thingy;
    }
}

And here’s my test that will throw an exception when the stored procedure is executed. I create my DatabaseWrapper as a PartialMock, allowing me to override its methods.

[TestMethod]
public void GetThingyHandlesException()
{
    // Arrange
    var target = new MyDataAccess();
    var mockDatabase = MockRepository.GeneratePartialMock<DatabaseWrapper>();
    target.Database = mockDatabase;

    // mock Database
    const string storedProc = "MyStoredProcedure";
    var mockDbCommand = MockRepository.GenerateMock<DbCommand>();
    mockDatabase.Expect(x => x.GetStoredProcCommand(storedProc))
        .Return(mockDbCommand);
    mockDatabase.Expect(x => x.DiscoverParameters(mockDbCommand));
    
    // mock DbCommand
    var ex = new Exception("Oh noes!");
    mockDbCommand.Expect(x => x.ExecuteNonQuery())
        .Throw(ex);

    // Act
    var actual = target.GetThingy();

    // Assert
    mockDatabase.VerifyAllExpectations();
    mockDbCommand.VerifyAllExpectations();
    Assert.IsNull(actual);
}

Setting input parameters

Need to set some input parameters? No problem!

dbCommand.Parameters["@id"].Value = id;

And, in your test, you add this:

var mockParams = MockRepository.GenerateMock<DbParameterCollection>();
var mockParam = MockRepository.GenerateMock<DbParameter>();

mockDbCommand.Expect(x => x.Parameters).Return(mockParams);

mockParams.Expect(x => x["@id"]).Return(mockParam);

const int id = 123;
mockParam.Expect(x => x.Value = id);

mockParams.VerifyAllExpectations();
mockParam.VerifyAllExpectations();

Reading output parameters

How about output parameters?

thingy.Value = dbCommand.Parameters["@Value"].Value as string;

Add the additional mocks and assertions:

var mockOutParam = MockRepository.GenerateMock<DbParameter>();

mockParams.Expect(x => x["@Value"]).Return(mockOutParam);

const string value = "MyValue";
mockOutParam.Expect(x => x.Value).Return(value);

mockParams.VerifyAllExpectations();
mockOutParam.VerifyAllExpectations();
Assert.AreEqual(value, actual.Value);

Working with sets of parameters

When you have more than a few parameters to work with, the unit test code can get quite lengthy. I like to keep it clean by extracting the duplicated logic into a separate function, like so:

var paramsToVerify = new List<DbParameter>();
mockParams.Expect(x => x["@whammyparammy"])
    .Return(MockParameter<int>(paramsToVerify));

My function allows you to specify and verify the type of each parameter, but you could easily modify it to expect a specific value.

private static DbParameter MockParameter<T>(List<DbParameter> paramsCollection)
{
    // set Expect with Arg<T>.Is.TypeOf to force the specific type
    var mockParam = MockRepository.GenerateMock<DbParameter>();
    mockParam.Expect(x => x.Value = Arg<T>.Is.TypeOf);

    if (paramsCollection != null)
        paramsCollection.Add(mockParam);

    return mockParam;
}

I keep the parameters in a list so I can verify them during my assertions.

paramsToVerify.ForEach(x => x.VerifyAllExpectations());

Custom Shaped Windows Forms From Images

One of the neat things you can do to make an application unique is give it a custom shape, and it’s surprisingly easy to do with windows forms. This article is going to show you how to make a ninja-shaped form in four ridiculously easy steps.

1. Find your image

This step is so simple, it’s almost not worth mentioning. You just need to find or create an image with the shape that you want. For the purposes of this article, I’m going to use this awesome ninja picture.

2. Edit the image

The next step is to edit your image by making undesired sections transparent. You can use Photoshop, Gimp, or any number of other editors to accomplish this. Here’s my transparent ninja image.

I added this image to my project and set its Copy to Output Directory property to Always so that it will be available in step 4. You could definitely compile it as a resource or handle this in a number of different ways if you didn’t want to deploy the image, though.

3. Create a region from your image

The third step is where you’ll actually have to do a little coding. The function below will scan through a provided bitmap pixel by pixel to create a region. (The original function comes from here. I made a slight adjustment to look for transparent pixels instead of a color provided as a parameter.)

private Region GetRegion(Bitmap _img)
{
    var rgn = new Region();
    rgn.MakeEmpty();
    var rc = new Rectangle(0, 0, 0, 0);
    bool inimage = false;
    for (int y = 0; y < _img.Height; y++)
    {
        for (int x = 0; x < _img.Width; x++)
        {
            if (!inimage)
            {
                // if pixel is not transparent
                if (_img.GetPixel(x, y).A != 0)
                {
                    inimage = true;
                    rc.X = x;
                    rc.Y = y;
                    rc.Height = 1;
                }
            }
            else
            {
                // if pixel is transparent
                if (_img.GetPixel(x, y).A == 0)
                {
                    inimage = false;
                    rc.Width = x - rc.X;
                    rgn.Union(rc);
                }
            }
        }
        if (inimage)
        {
            inimage = false;
            rc.Width = _img.Width - rc.X;
            rgn.Union(rc);
        }
    }
    return rgn;
}

4. Change the form’s region

That wasn’t so bad, was it? Now you’re basically done. The final step is simply to assign your newly created region to your form’s Region property.

private void Form1_Load(object sender, EventArgs e)
{
    var bitmap = new Bitmap("ninja.png");
    Region = GetRegion(bitmap);
}

Voila! You’re done, and now you have a sweet ninja form! (For added authenticity, modify the form’s opacity.)

Bonus material!

One of the problems with a custom shaped form is that you lose the title bar, so you can’t easily move it around. This can be remedied by adding some handlers to a few mouse events on the form, like so:

private bool _mouseDown;
private Point _startPoint;

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    _mouseDown = true;
    _startPoint = new Point(e.X, e.Y);
}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    _mouseDown = false;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (_mouseDown)
    {
        var p1 = new Point(e.X, e.Y);
        var p2 = PointToScreen(p1);
        var p3 = new Point(p2.X - _startPoint.X,
                             p2.Y - _startPoint.Y);
        Location = p3;
    }
}

With this code in place, you can click anywhere in the form to move it around.

Parse US Street Addresses with Regular Expression in C#

In my business, we do a lot with addresses. Generally, we rely on 3rd party products from companies like ESRI for what we need, but from time to time, we still need to parse an address the old-fashioned way. Something like US Address Parser is exactly what I need, but I can’t use it since it’s GPL’d. I didn’t need an exhaustive, perfect solution, so I thought I’d just whip one up with regular expressions.

Sample input:

  • 100 MAIN
  • 100 MAIN ST
  • 100 S MAIN ST
  • 100 S MAIN ST W
  • 100 S MAIN ST W APT 1A

Create StreetAddress class

The first step was simply to create an address object with the properties I needed:

public class StreetAddress
{
    public string HouseNumber { get; set; }
    public string StreetPrefix { get; set; }
    public string StreetName { get; set; }
    public string StreetType { get; set; }
    public string StreetSuffix { get; set; }
    public string Apt { get; set; }
}

Build regular expression

The next thing I did was get to work on my regular expression. I built my expression with the help of RegExr and did my initial testing. Once I was satisfied, I moved it over to code. Here’s what I came up with:

private static string BuildPattern()
{
    var pattern = "^" +                                                       // beginning of string
                    "(?<HouseNumber>\\d+)" +                                  // 1 or more digits
                    "(?:\\s+(?<StreetPrefix>" + GetStreetPrefixes() + "))?" + // whitespace + valid prefix (optional)
                    "(?:\\s+(?<StreetName>.*?))" +                            // whitespace + anything
                    "(?:" +                                                   // group (optional) {
                    "(?:\\s+(?<StreetType>" + GetStreetTypes() + "))" +       //   whitespace + valid street type
                    "(?:\\s+(?<StreetSuffix>" + GetStreetSuffixes() + "))?" + //   whitespace + valid street suffix (optional)
                    "(?:\\s+(?<Apt>.*))?" +                                   //   whitespace + anything (optional)
                    ")?" +                                                    // }
                    "$";                                                      // end of string

    return pattern;
}

Functions for valid values

Note that there are several functions called while building the regular expression. This is done purely for readability and maintainability. Here are the functions, which each just return a pipe-delimited list of valid values:

private static string GetStreetPrefixes()
{
    return "TE|NW|HW|RD|E|MA|EI|NO|AU|SE|GR|OL|W|MM|OM|SW|ME|HA|JO|OV|S|OH|NE|K|N";
}

private static string GetStreetTypes()
{
    return "TE|STCT|DR|SPGS|PARK|GRV|CRK|XING|BR|PINE|CTS|TRL|VI|RD|PIKE|MA|LO|TER|UN|CIR|WALK|CO|RUN|FRD|LDG|ML|AVE|NO|PA|SQ|BLVD|VLGS|VLY|GR|LN|HOUSE|VLG|OL|STA|CH|ROW|EXT|JC|BLDG|FLD|CT|HTS|MOTEL|PKWY|COOP|ACRES|ESTS|SCH|HL|CORD|ST|CLB|FLDS|PT|STPL|MDWS|APTS|ME|LOOP|SMT|RDG|UNIV|PLZ|MDW|EXPY|WALL|TR|FLS|HBR|TRFY|BCH|CRST|CI|PKY|OV|RNCH|CV|DIV|WA|S|WAY|I|CTR|VIS|PL|ANX|BL|ST TER|DM|STHY|RR|MNR";
}

private static string GetStreetSuffixes()
{
    return "NW|E|SE|W|SW|S|NE|N";
}

Parse the input

At this point, the work is done. All that’s left is to run the regular expression on your address string and deal with the results.

public static StreetAddress Parse(string address)
{
    if (string.IsNullOrEmpty(address))
        return new StreetAddress();
            
    StreetAddress result;
    var input = address.ToUpper();
            
    var re = new Regex(BuildPattern());
    if (re.IsMatch(input))
    {
        var m = re.Match(input);
        result = new StreetAddress
                        {
                            HouseNumber = m.Groups["HouseNumber"].Value,
                            StreetPrefix = m.Groups["StreetPrefix"].Value,
                            StreetName = m.Groups["StreetName"].Value,
                            StreetType = m.Groups["StreetType"].Value,
                            StreetSuffix = m.Groups["StreetSuffix"].Value,
                            Apt = m.Groups["Apt"].Value,
                        };
    }
    else
    {
        result = new StreetAddress
                        {
                            StreetName = input,
                        };
    }
    return result;
}

End product

And, finally, for those of you who love big, gnarly regular expressions, here’s my end product:

^(?<HouseNumber>\\d+)(?:\\s+(?<StreetPrefix>TE|NW|HW|RD|E|MA|EI|NO|AU|SE|GR|OL|W|MM|OM|SW|ME|HA|JO|OV|S|OH|NE|K|N))?(?:\\s+(?<StreetName>.*?))(?:(?:\\s+(?<StreetType>TE|STCT|DR|SPGS|PARK|GRV|CRK|XING|BR|PINE|CTS|TRL|VI|RD|PIKE|MA|LO|TER|UN|CIR|WALK|CO|RUN|FRD|LDG|ML|AVE|NO|PA|SQ|BLVD|VLGS|VLY|GR|LN|HOUSE|VLG|OL|STA|CH|ROW|EXT|JC|BLDG|FLD|CT|HTS|MOTEL|PKWY|COOP|ACRES|ESTS|SCH|HL|CORD|ST|CLB|FLDS|PT|STPL|MDWS|APTS|ME|LOOP|SMT|RDG|UNIV|PLZ|MDW|EXPY|WALL|TR|FLS|HBR|TRFY|BCH|CRST|CI|PKY|OV|RNCH|CV|DIV|WA|S|WAY|I|CTR|VIS|PL|ANX|BL|ST TER|DM|STHY|RR|MNR))(?:\\s+(?<StreetSuffix>NW|E|SE|W|SW|S|NE|N))?(?:\\s+(?<Apt>.*))?)?$

Eight Qualities of Remarkable Emloyees

Inc.com is running a great article by Jeff Haden titled Eight Qualities of Remarkable Employees. The article discusses eight non-tangible behaviors exhibited by the best of the best. These qualities all transcend industry, but there were a few that I felt were particularly true for software development.

They ignore job descriptions

There are many external factors that can influence a software project, and any one of them can roadblock the whole thing. New requirements, unexpected challenges, verification, and deployment issues all have the ability to derail your timeline, and it will often be someone else’s official responsibility to deal with the problem. Waiting for somebody else costs you valuable time and can ultimately lead to missed deadlines or failure. Cut out the middle-men, do what needs to be done, and enjoy success.

(This seems obvious, but I’m going to say it anyway: be aware of the politics of your actions. Preventing a distraction: good; doing someone else’s job: bad.)

They like to prove others wrong

If you’ve got a great idea that others don’t believe in, there are two options: let them go down what you believe to be an incorrect or inferior path, or prove them wrong. When you set out to prove them wrong, you may find that you were actually wrong. (*gasp* I know–not likely, right?) That’s still a win, though, because you (hopefully!) learned from it. If you’re right, you’ll help steer a project toward an optimal solution and gain credibility with your team.

I think healthy competition also falls into this category. If you have individuals competing with each other to find an optimal solution, you’re more likely to find it than if you have a single person trying to accomplish the same thing. Each person is likely to come up with a solution that they feel is the best, and the way to “win” is to prove its the best to their peers.

They’re always fiddling

Tinkering is SO important to software developers. It’s how you practice and hone your craft. It’s how your learn new things. Evolving your skillset and tools allows you to be more creative and innovative with your solutions, which further energizes the team.

Make Your Job Obsolete

A long time ago, I read a book by Chad Fowler titled The Passionate Programmer: Creating a Remarkable Career in Software Development. This is a great book that I’d recommend to anybody getting started in software development. It’s full of great tips and ideas like trying to be the worst on your team (surround yourself by greatness), the importance of practice, and striving to be a little better every single day.

One of the concepts that really resonated with me is making it a goal to make whatever position you’re currently in obsolete. With a larger software company, it’s easy to get your hands into a lot of different projects. It’s also easy to become the person with specialized knowledge on specific topics. There’s a feeling of security that comes along with that–they can’t get rid of me; nobody else knows this–but it also makes it harder for you to move forward. I fell into this trap myself a few years ago. There was nobody on the bench to replace me so that I could move on to new and different challenges, and it took some time to get myself out of that position.

Keeping the goal of obsoleting your job in mind day-to-day helps you accomplish two major things: your tasks get easier and you stay available for whatever’s next. And, one of the amazing things about being a software developer is that you have the power to do this through software! The key is identifying processes that can be automated and then mustering up the motivation to follow through and execute.

So what processes can/should be automated? This will be different for everybody and largely depends on your typical tasks. Here are some examples I’ve encountered:

  • Anything that involves cutting and pasting
  • Things that are run on an interval (e.g., daily/hourly/weekly reports)
  • Complex data entry tasks (i.e., create an application to simplify the process)
  • Abused spreadsheets (spreadsheets that are modified and emailed each day can be replaced with web portals with databases that have entry and reporting)
  • Utility-type or out-of-application SQL scripts

Your imagination is the limit. Dream it, create it, and share it. If you do a great job, your managers and co-workers will thank you!

Adam’s Favorite Things: Logitech K750 Wireless Solar Powered Keyboard

If you’re in the market for a new keyboard, I highly recommend checking out Logitech’s K750 Wireless Solar Powered Keyboard. I bought this keyboard a few months ago, and I absolutely love it!

Logitech K750
(Available at Amazon.com.)

I’d had wireless keyboards in the past and didn’t care for them because I needed to change the batteries so frequently. I definitely wasn’t looking for a wireless keyboard while I was shopping around, but I was intrigued by the idea of solar power when I stumbled upon this. There was some skepticism about how well it would work or what quantity of light would be necessary to keep it going, but I haven’t had a single issue with it. In fact, even on the day I got it, I used it in my dimly lit living room for the entire day without having to charge it.

It’s a very sexy piece of hardware, with its very low profile–similar in thickness to a smartphone–and a shiny black finish. The keys feel more like a laptop keyboard than a “normal” keyboard, so that may turn some people off. There is a light-source button you can press to have the keyboard indicate to you whether it’s getting enough light or not. It’s also important to note that it doesn’t need sunlight to charge; it will charge from any standard lamp. The range on it seems decent, too, though I have not done any sort of testing with that.

Need a keyboard? Check it out!

Console Application Proxy

I’m working on a project where it’s necessary to use a client application provided by a third party to query the third party’s system from within my own system. This can be done very easily in .net by simply redirecting standard input and output.

Here is a sample application that demonstrates how:

var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = @"WorkApp.exe";
p.Start();

string input;
do
{
    // get request from user
    Console.Write("> ");
    input = Console.ReadLine();
    p.StandardInput.WriteLine(input);

    // get response from console
    var output = p.StandardOutput.ReadLine();
    Console.WriteLine(output);
} while (input != "x");

if (!p.HasExited)
{
    p.Kill();
}

TFS SDK: Getting Started

TFS is great, but it simply doesn’t do everything I need it to do. My team has a TFS work-item-driven software development life-cycle that depends on having stories organized with tasks of certain activity types performed in a specific order. It’s a difficult process for new team members to internalize, and it requires discipline for even our veteran team members. One of the things that I’ve decided to do to help my team manage this process successfully is to create a custom tool with built in “queues” that will display their work items as they need attention without relying on the developer to manually run different queries and discover items on their own.

And so that brings us to the TFS SDK. I’m going write a series of short posts detailing how to do some simple tasks that can be combined to do very powerful things. One of the simplest and most powerful things you can do with the TFS SDK is run WIQL queries to query work items using a SQL-like syntax.

The first step you need to do is simply to add the TFS SDK references to your project. These are the three I added to my project:

Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.WorkItemTracking.Client

Once you’ve got that, you can build an execute a query with the following block of code:

var tpc = new TfsTeamProjectCollection(new Uri("http://YourTfsServer:8080/tfs/YourCollection"));
var workItemStore = tpc.GetService(); 
var queryResults = workItemStore.Query(@"
    SELECT [System.Id], [System.WorkItemType], [System.Title], [System.AssignedTo], [System.State] 
    FROM WorkItems 
    WHERE [System.AssignedTo] = @me 
    ORDER BY [System.Id]
    ");
foreach (WorkItem wi in queryResults)
{
    Console.WriteLine("{0} | {1}", wi.Fields["State"].Value, wi.Fields["Title"].Value);
}

Bonus tip: you can construct your WIQL query by building it from Visual Studio’s Team Explorer and saving it to file. For my application, I’m storing the WIQL query in my app.config to allow for quick & easy customization.