Regular expressions with ASCII values

I was writing some unit tests today to test a format out. The format that I was testing used ASCII characters for FS, GS, RS, and US.

A sample format might look like this:

1.03:1[us]00[rs]2[us]01[rs]10[us]01[gs]

So, in my test, I wanted to verify that my string started with “1.03:” and ended with “[rs]10[us]someValue[gs]” However, I didn’t know how to check for those pesky ASCII characters, though! After a bit of Googling, I found the answer, and it’s actually pretty simple. You can use an escaped u in a regular expression to specify a four-digit Unicode character. After a quick ASCII-to-Unicode lookup (here) I came up with the perfect regular expression:

Regex.IsMatch(contents, @"1.03:.*?\u001E10\u001F0*" + expected + @"\u001D")

Thanks for being so awesome, regular expressions!

Advertisements

WPF Combo Box validation

I’ve been working on a small WPF project that requires some business rule validation. I thought this would be relatively simple but proved to be slightly more complicated than expected. At the end of the day, I found two relatively simple ways to perform the validation.

The first is to simply bind ComboBox.Selected item to a property and do the validation in the set block.

    private MyDataObject _someData;
    public MyDataObject SomeData
    {
        get
        {
            return _ someData;
        }
        set
        {
            _ someData = value;
            if (value == null || string.IsNullOrEmpty(value.MyProperty))
                throw new ApplicationException("SomeData is required");
        }
    }

Then, in the XAML, you just need to hook it up to treat exceptions as validation errors.

    <ComboBox.SelectedItem>
        <Binding Path="SomeData" ElementName="Window">
            <Binding.ValidationRules>
                <ExceptionValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </ComboBox.SelectedItem>

The second method gives more flexibility but requires the creation of a custom ValidationRule class.

    public class MyCustomValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            if (value is MyDataObject)
            {
                var myDataObj = (MyDataObject)value;
                if (myDataObj.CheckCustomBusinessRules())
                    return new ValidationResult(true, null);
            }
 
            return new ValidationResult(false, "Invalid selection!");
        }
    }

And then you hook up the validation rules to use the new custom class.

    <ComboBox.SelectedItem>
        <Binding Path="SomeData" ElementName="Window">
            <Binding.ValidationRules>
                <local:PersonValidation />
            </Binding.ValidationRules>
        </Binding>
    </ComboBox.SelectedItem>

(Note that the “local” prefix requires an additional namespace at the top of your XAML file, xmlns:local=”clr-namespace:MyNamespace”)

One last tip that threw me off for a bit is that I was missing x:Name=”Window” in my Window tag at the top of my XAML; this caused the ComboBox’s SelectedItem to not bind properly and the validation rules consequently didn’t work.

Mass find & replace in TFS using Powershell

One of the problems that seems to come up semi-frequently is, “We need to update all x files to have y!” The old solution to this was manually going through all x files and updating them to have y. However, this can be accomplished quickly and easily using Powershell.
Here’s an example. We had a number of VB6 project files whose BCO paths were set to use a mapped “O:” drive that no longer existed. Instead, these projects should be using a relative path. There were 100 or so of these projects that needed to be updated, and I was able to check them out from TFS and make the change to all of them in a matter of seconds by using the following script (sorry for the formatting!):

Get-ChildItem "C:\Code" -recurse | 
    Where-Object {$_.Extension -eq ".vbp"} | 
    ForEach-Object {Write-Host "  "$_.FullName; &amp; "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe" checkout "$($_.FullName)" | Out-Null; (Get-Content $_.FullName) | 
        ForEach-Object {$_ -replace "O:\\.*?\\BCO\\", "..\..\BCO\"} | 
            Set-Content $_.FullName -Force}

And another example. I needed to update the revision numbers of all projects in a sub-directory to be automatic. Here’s the same script modified to accomplish that. I’ve made this more re-usable by accepting parameter values from the command line.

# example usage: .\UpdateVersion.ps1 -path "C:\Code" -build "1.0.0.*"

# get param values
param(
  [int] $build, 
  [string] $path, 
  [string] $root)


if ($build -eq $null)
{
    $build = Read-Host "Build number:"
}
if ($path -eq $null)
{
    $path = ".\"
}

# $root will be trimmed from start of directory string
# when checking for exceptions
if ($root -eq $null)
{
    $root = "c:\"
}


# $exceptionDirs will not have their versions updated
$exceptionDirs = "test"

Write-Host "Updated the following files:"

# recursively search $path for AssemblyInfo.cs
# if found, update version number &amp; save
Get-ChildItem $path -recurse | 
    Where-Object {$_.Name -eq "AssemblyInfo.cs"} | 
    Where-Object {$exceptionDirs -notcontains $_.Directory.ToString().ToUpper().TrimStart($root.ToUpper())} |
    ForEach-Object {Write-Host "  "$_.FullName; &amp; "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe" checkout "$($_.FullName)"; (Get-Content $_.FullName) | 
        ForEach-Object {$_ -replace "(?(\d+\.){3})\d+", "`${ver}$build"} | 
            Set-Content $_.FullName -Force}

❤ Powershell!