Twelve Days of .NET: Day 9: Git and TFS

This post is part of my 12 Days of .NET series. This is a (not terribly ambitious) series of posts on .NET topics that came up while I was working on a recent C# Web API project.

At work, we have a TFS 2012 server for version control. We’re pretty much stuck with that, because the TFS integration in AX 2012 can be a little finicky, and we don’t have a really compelling reason to upgrade anyway. I know that recent versions of TFS (starting with 2013 maybe?) support hosting Git repos, but I think I’d be stuck with TFVC anyway, for a variety of reasons.

For my current .NET project, for which I’m using VS 2017, I started out with a local Git repo, intending to kill it and switch to TFVC when it was ready to go into test. I’m liking Git enough, though, that I’ve stuck with it, and have come up with a somewhat kludgey workflow, where I use Beyond Compare to periodically copy changed code files from my “work” project to a copy of the project that’s bound to TFS. So I code and test locally in the Git version of the project, committing often. Then, when I’m ready to deploy to my test server I follow a workflow where I copy to the TFS project, check my changes into TFS, then deploy to our test IIS server. As I said, it’s a bit of a kludge, but it works for me.

I thought about trying to use git-tfs, but I didn’t want to go down any rabbit holes so I stuck with the simple (but ugly) solution. And I’d love it if we could just switch to VSTS, but I don’t think that’s going to happen either.

TFS query PowerShell script

It’s been a while since I posted any PowerShell code here, so here’s a quickie script that I’m using to help with my workflow for checking in Dynamics AX changes.

First, a little background: We have a slightly odd workflow set up in TFS for tracking the projects we do in Dynamics AX. For each project, we open a TFS work item. We then check in all changes for that project under that work item. So far, so good. But we also routinely close out a work item after the first deployment that contains a check-in for that work item. So bug fixes and enhancements after the initial deployment are technically being checked in against a closed work item.

The problem here is that the check-in dialog within AX shows a list of open work items assigned to the current user, and doesn’t provide a mechanism for searching for other work items. It does allow you to manually add a work item to the list, but it can only do that by ID. But we have our own project number, which is stored as part of the work item title, and we generally don’t use the TFS work item ID for anything, so I generally don’t know it off the top of my head. So I often have to go into Team Explorer in Visual Studio to look up the work item ID for a project before I can check it in. That’s not a huge inconvenience, but I thought it would be nice to have a little PowerShell script that could look up the work item ID for me, given an AX project number.

The script shown below isn’t terribly complicated, but it shows off a few interesting little things. I started with an example script taken from Julian Kay’s blog.

First, we’re using the TFPT command-line query capability. This is part of TFS Power Tools, and uses a query syntax called WIQL.

Second, we’re doing a little rudimentary parsing of the data returned from TFPT to pull out the first work item ID. Then, we’re copying it to the clipboard with the clip command. (Looking at this script, I’m pretty such there’s a better way for me to pull out the work item ID, but the way I’m doing it now works fine.)

And finally, we’re displaying the results to the screen, so if by chance more than one result is returned, I can see the list and decide which work item is the right one.

If I wanted to go a few steps further with this, I could probably integrate this into AX completely. The check-in dialog in AX is a regular AX form named “SysVersionControlCheckIn”, and there’s no reason I couldn’t customize it. (But that’s a problem for another rainy day.)


# Given AX project #, return ID.
param (
[string]$projno = $( Read-Host "Enter project # (e.g. 123.4)" )
)
[string]$tfpt = "C:\Program Files (x86)\Microsoft Team Foundation Server 2012 Power Tools\TFPT.EXE"
[string]$svr = "http://myTfsServer:8080/tfs/defaultcollection"
[string]$projname = "myProjName"
[string]$query = "SELECT [System.Id], [System.Title] FROM WorkItems " +
"WHERE [System.TeamProject] = '$projname' " +
"AND [System.Title] CONTAINS '$projno' " +
"ORDER BY [System.Id] asc"
$data = & $tfpt query /collection:$svr /wiql:$query /include:data
if ($data -ne $null) {
$line = ($data | select -first 1)
$taskid = $line.split("`t")[0]
$taskid | clip
}
$data
Write-Host "Press any key to continue …"
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

view raw

tfpt_ex1.ps1

hosted with ❤ by GitHub

 

TFS Scripts

I’m definitely not a TFS genius, but I’ve written a few scripts that have proven helpful in dealing with some of the issues that come up with version control.
First, here’s a simple one. This just automates a simple TF.EXE command to show the last 50 check-ins in our project. This particular command opens a GUI window to show the output.

# https://gist.github.com/andyhuey/5471064
[string]$tf = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe"
pushd
cd c:\ax2012tfs
& $tf history /r /stopafter:50 *
popd

Second, here’s one to show the TFS status. This command, unlike the previous, sends output to the console, so I’m piping it to Notepad++, so I can see it there.

# https://gist.github.com/andyhuey/5471072
[string]$tf = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe"
[string]$npp = "C:\Program Files (x86)\Notepad++\notepad++.exe"
# [string]$tempFile = [System.IO.Path]::GetTempFileName()
[string]$tempFile = "$env:temp\tfStatus.txt"
pushd
cd c:\ax2012tfs
& $tf status > $tempFile
popd
& $npp $tempFile

And third, here’s a somewhat more complicated one. This one allows you to diff two changesets, and pipes the output to Notepad++. But, if there’s an error, it instead shows a “press any key” message, so you can see the error in the console window. Notepad++ has syntax highlighting for diff files, so the output is reasonably nice-looking.

# https://gist.github.com/andyhuey/5471084
param (
     [string]$cs1 = $( Read-Host "Enter changeset 1 (as c9999)" ),
     [string]$cs2 = $( Read-Host "Enter changeset 2 (as c9999)" )
)
[string]$tf = "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe"
[string]$npp = "C:\Program Files (x86)\Notepad++\notepad++.exe"
[string]$tempFile = "$env:temp\tfDiff.diff"
pushd
cd c:\ax2012tfs
& $tf diff cus /v:$cs1~$cs2 /r /f:unified > $tempFile
if ($LastExitCode -eq 0)
{
     & $npp $tempFile
}
else
{
     Write-Host "Press any key to continue ..."
     $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
popd

This pretty much concludes the overview of my utility scripts that I started a few days ago. I hope it was helpful to someone. If not, at least I’ve got them documented now, so if I lose them again, I know where to look!

My new job, Dynamics AX, and X++

I started a new job (at SHI) back in January. I’ve been wanting to post something about it for awhile now, but I’ve been pretty busy. Also, I kind of wanted to keep quiet about it for a bit, just in case it didn’t work out. Well, I’ve been there for about two months now, and it seems to be going well.

Right now, I’m doing development for our Dynamics AX system, using AX’s proprietary programming language, X++. It’s a reasonably decent and relatively modern language, very similar to C# and/or Java. I do miss the more chaotic environment I’d previously been working in, where I was using a mix of ASP.NET / C#, JavaScript, and PHP / Drupal, depending on the project. SHI does have a fairly mixed environment, but there are enough programmers working here that they’re not likely to need me on anything other than X++ any time soon, so I guess I’ll have to get used to a bit less variety than I’ve had in the past.

The development environment built into AX is called MorphX. (This is also the name of a mediocre XBox 360 game, which kind of skews Google results for MorphX, but that’s OK.) Microsoft has obviously made some effort to add some nice features to MorphX since they acquired AX, but it’s not quite up to the standard set by Visual Studio. They’ve also tried to standardize some of the keyboard shortcuts between VS and MorphX, but there are still a few annoying inconsistencies there.

I recently found a project on CodePlex called Microsoft Dynamics AX 2012 X++ Editor Extensions, which adds a few missing features to the X++ code editor. I tend to worry about add-ins like this slowing things down or introducing instability, but these three extensions all seem to work well. (It’s funny how you don’t really think of, for instance, brace matching as being a big deal, until you don’t have it…)

I haven’t really blogged much about programming recently, so I’d really like to get back into the habit. I have a few possible topics in mind for AX-related posts, so hopefully I can find the time to write those up soon.