Mike's profileFreeToDevBlogLists Tools Help

Blog


    March 24

    Regular Expression Scratchpad v1

    UPDATE: 14 Jan 08 --- Version 2 has been posted here.

    Small modifications to the beta. v1 is available here.

    March 13

    .net Regular Expression Scratchpad Beta 1

    I'm a massive fan of regular expressions. The only problem I have with them is that I don't use them often enough and forget how to use them most efficiently!

    The best free tool I have used is Eric Gunnerson's Regular Expression Workbench V2.0. I tried installing it on a Vista machine the other day and it wouldn't install because the machine didn't have .net 1.1. I didn't want to install this, so the only other option was to convert it to a .net 2.0 app. Conversion is not very pretty exercise for winform apps and I decided to write an app from the ground up to mimic the parts of REW2 that I most use...

    ...and here is the result: [UPDATE: V1 is available. See this post.]

    Please feel free to try it out and send me any bugs that you may find...FTD

    March 06

    TFS Team Build DropLocation

    I'm running multiple build servers and want drops to go to the relevant build server rather than a central drop folder. The TFSBuild.proj file has a property called DropLocation that specifies where to drop build output. I decided to add a property to the value of DropLocation to make the build drop locally:

        <DropLocation>\\$(COMPUTERNAME)\drops\CI---ProductXYZ</DropLocation>

    Easy enough, but running a build resulted in:

    TF42042: Failed to connect to drop location \\$(COMPUTERNAME)\drops please ensure that is is a valid share.

    It’s not the $, using %24 gives the ‘same’ message. It looks like the build process is using EvaluatedProperties.Value rather than FinalValue.

    Luckily there is a way to get around this small bug. I overrode BeforeEndToEndIteration and set DropLocation in there:

    <Target Name="BeforeEndToEndIteration" Condition="'$(IsDesktopBuild)'!='true'">
    <ShowBuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildURI="$(BuildUri)" BuildStep="TARGET OVERRIDE: BeforeEndToEndIteration"/>
    <CreateProperty Value="\\$(COMPUTERNAME)\drops\CI---ProductXYZ">
    <Output TaskParameter="Value" PropertyName="DropLocation" />
    </CreateProperty>
    </Target>

    If you are wondering what ShowBuildStep is, take a look at this post...FTD

    March 03

    MSBuild Task: Detokenise File

    This task can be used to find and replace tokens in a file or set of files.

    [25 May 07: - Download the update with samples from here.]

    There are two distinct ways of using this task.

    1. The first way is to pass in a ReplacementValues collection. Easy, the task simply matches on the collection and substitutes the token with the Replacement value.
    2. The second way is to pass in no ReplacementValues. If this is done, then the task will use the evaluated properties of the calling project. This is handy if you have a bunch of imports and don’t want to maintain a specific ReplacementValues collection. This is how I mostly use the task, but there are two things that should be noted when using the task in this way.
      • The properties that are evaluated are the 'FinalValues’ of properties as if the project file were instantiated with no parameters. This means that if you have made any changes to a property before calling the task or overridden the property from the command line, the changes will not be seen, the original ‘FinalValue’ is what is substituted. This is a limit of MSBuild, not the task.
      • Because the task must load the calling project, there will be a minor performance hit. This should be insignificant, but I’m guessing that if you have a project file loading several meg’s of imports or you call the task many (thousands) of times, then you may have problems.

    Required Input Parameters

    TargetFiles: an ItemGroup of files to be detokenised. An optional encoding may be specified for each file, e.g.

    <ItemGroup>
    <FileCollection Include="C:\web.config">
    <Encoding>UTF8</Encoding>
    </FileCollection>
    <FileCollection Include="C:\web1.config"/>
    </ItemGroup>

    --- or ---

    TargetPath: detokenise any files in the given path. A * can be used to search all sub directories.

    Optional Input Parameters

    DisplayFiles: the task will log the processing of each file to the console. The default is true.

    Encoding: the file encoding to use when re-writing the file. If no encoding is passed, then the task will attempt to maintain the current file encoding. This encoding will be overridden by any individual encodings passed in the TargetFiles collection.

    ForceWrite: the task will re-write any file it processes, even if no tokens have been replaced. This may be handy if you want to ensure all processed files have the same encoding. The default is false.

    ReplacementValues: an ItemGroup of values to use for de-tokenising files (the default is to use the calling projects evaluated properties), e.g.

    <ItemGroup>
    <Parameters Include="Token1">
    <Replacement>value1</Replacement>
    </Parameters>
    <Parameters Include="Token2">
    <Replacement>value2</Replacement>
    </Parameters>
    </ItemGroup>

    TokenPattern: this is the regular expression to use to identify a token. The default token format to replace is $(token)

    Output Parameters

    FilesProcessed: the count of files the task has processed.

    FilesDetokenised: the count of files which have had tokens replaced.For performance reasons, it is best that these two output parameters are equal; otherwise the task is processing unnecessary files.

    Using the Task

    1. Download it from here
    2. Add an Import in your .proj file
      <Import Project="FreeToDev.MSBuildTasks.tasks"/>
    3. The imported file (FreeToDev.MSBuildTasks.tasks) should have
      <?xml version="1.0" encoding="utf-8"?>
      <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <UsingTask AssemblyFile="FreeToDev.MSBuild.SystemTasks.dll" TaskName="FreeToDev.MSBuild.SystemTasks.DetokeniseFile" />
      </Project>

    Samples

    TestFile.txt contains the following text:

    Hello my name is $(MyName) and my blog can be found at $(MyBlog).

    Let's use the .proj file below

    <Project DefaultTargets="Execute" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="FreeToDev.MSBuildTasks.tasks"/>
    <PropertyGroup>
    <MyName>FreeToDev!!!</MyName>
    <MyBlog>http://freetodev.spaces.live.com</MyBlog>
    <PathToDetokenise>C:\Atest\*</PathToDetokenise>
    </PropertyGroup>
    <ItemGroup>
    <FileCollection Include="C:\TestFile.txt"> <!--This file will be written with UTF8 encoding -->
    <Encoding>UTF8</Encoding>
    </FileCollection>
    <FileCollection Include="C:\TestFile2.txt"/> <!—This file will be written with its current encoding or the encoding specified in the Encoding parameter -->
    </ItemGroup>
    <ItemGroup>
    <TokenValues Include="MyName">
    <Replacement>FreeToDev</Replacement>
    </TokenValues >
    <TokenValues Include="MyBlog">
    <Replacement>www.freetodev.com</Replacement>
    </TokenValues >
    </ItemGroup>
    <Target Name="Execute">
    <!-- 1 -->
    <DetokeniseFile TargetFiles="@(FileCollection)" ReplacementValues="@(TokenValues)"/>
    <!-- 2 -->
    <DetokeniseFile Encoding="ASCII" TargetFiles="@(FileCollection)"/>
    <!-- 3 -->
    <DetokeniseFile TargetPath="$(PathToDetokenise)"/>
    <!-- 4 -->
    <DetokeniseFile TargetPath="$(PathToDetokenise)" DisplayFiles="false" ForceWrite="true"/>
    <!-- 5 -->
    <DetokeniseFile TargetPath="$(PathToDetokenise)" DisplayFiles="false">
    <Output TaskParameter="FilesProcessed" ItemName="FilesProcessed"/>
    <Output TaskParameter="FilesDetokenised" ItemName="FilesDetokenised"/>
    </DetokeniseFile>
    <Message Text="FilesDetokenised = @(FilesDetokenised), FilesProcessed = @(FilesProcessed)"/>
    </Target>
    </Project>

    1. Detokenise the files defined in FileCollection and use the TokenValues collection for substitution. TestFile.txt will read
      • Hello my name is FreeToDev and my blog can be found at www.freetodev.com [Encoding = UTF8]
    2. Detokenise the files defined in FileCollection and use the tokens defined by the .proj properties. TestFile.txt will read
    3. Detokenise the files at the given TargetPath and perform a recursive search. Assuming TestFile.txt is in the path, it will read
    4. This will produce the same result as #3, but no file processing will be logged to the console. Because ForceWrite has been specified, all files will be re-written.
    5. This will produce the same result as 4, though ForceWrite is false by default so the difference can be displayed using the output parameters.

    Hope it's of use....FTD

    March 01

    It's time to start looking at Orcas...

    The March CTP is here and I'm looking forward to working with the new bits. Also, check out the great Code Metrics that are included in VS. The Orcas Forums are a great place to request, provide and review feedback...FTD