Passing SolutionDir to NAnt For Post-Build Event in TeamCity

I just spent the better part of a day trying to solve this problem, so I’m posting the solution for any who may encounter it in the future. ¬†You’re welcome ūüėČ

For a project I am currently working on, I needed to add a post-build event which invokes a PowerShell script.  The script performs some minor tasks involving a database and is called PostBuild-DbSync.ps1.  At the outset, this was a straightforward proposition.  I created the script file, then referenced it in the Build Events section in Visual Studio.

Powershell.exe -ExecutionPolicy Unrestricted -file “$(SolutionDir)Build\PostBuild-DbSync.ps1”

The Problem

Running the build locally in Visual Studio was successful, and I ran it repeatedly while tweaking the script. ¬†Once the script was perfected, I checked it in to our SVN repo, and that triggered an automated build on our TeamCity server. ¬†That’s when the problems began. ¬†The first build failed with the following error:

Processing -File ‘*Undefined*Build\PostBuild-DbSync.ps1’ failed: Illegal characters in path. Specify a valid path for the -File parameter.

The value for “$(SolutionDir)” was not being passed to the Nant file which was being used to run the build.

Attempt #1

After some research, I learned that you can specify the Solution Directory as a parameter to MSBuild. ¬†However, because TeamCity is running the builds, I don’t have a specific directory to use as the value for that parameter. ¬†It may change from one build to the next. ¬†But TeamCity does expose several predefined build parameters, including the working directory and the checkout directory. ¬†So I decided to use one of these parameters in my NAnt file to set the appropriate solution directory.

<arg value=”/p:SolutionDir=${teamcity.build.checkoutDir}” />

Unfortunately, this approach did not work.  I got a new error:

The argument ‘C:\TeamCity\buildAgent\work\86ef71b243852ab1Build\PostBuild-DbSync.ps1’ to the -File parameter does not exist.

So the path was getting passed into the NAnt process correctly, and to the post-build event. ¬†However, I was missing a slash at the end of the solution directory, so its not finding the PowerShell file. ¬†I’m close, right? ¬†It just needs a little more tweaking…

Attempts #2, #3, #4

This part of the process was the most frustrating of them all.  I went around and around trying to get that missing slash in the right place.  First I tried adding it to the post-build event.

Powershell.exe -ExecutionPolicy Unrestricted -file “$(SolutionDir)\Build\PostBuild-DbSync.ps1″

For some reason, that brought me back to the “*Undefined*” error that I got at first. ¬†Next I tried adding it in the NAnt file.

<arg value=”/p:SolutionDir=${teamcity.build.checkoutDir}\” />

Again,¬†“*Undefined*”. ¬†I even tried a forward slash, but that didn’t resolve the issue. ¬†The next approach was to edit the project file manually and try to specify the solution directory as a relative path there.

<SolutionDir Condition=”‘$(SolutionDir)’==” or ‘$(SolutionDir)’==’*Undefined*'”>..\</SolutionDir>

This attempt also failed, since the PowerShell command requires the full path to the file, not a relative path.

The Solution

For a few other values used by the NAnt file, I had set up environment variables in TeamCity. ¬†So I decided to use that approach to solve this problem. ¬†I set up an environment variable in the build configuration with the name ‘SolutionDir’ and the value ‘%teamcity.build.checkoutDir%\’. ¬†Notice that I’m using the predefined build parameter, and I can easily tack that extra slash on the end.

Now, I can go back to my NAnt file and set the SolutionDir parameter for MSBuild with the following line:

<arg value=”/p:SolutionDir=${environment::get-variable(‘SolutionDir’)}” />

With that, the build succeeds, and the post-build event processes flawlessly as well.

 

The Good Bits ‚Äď September 8

A few interesting articles/posts I have come across recently and wanted to share…

Two Months with a Tesla¬†‚Äď This is an awesome write-up from Andrew Connell about his experience with his new Tesla S 85D. ¬†Like him, I have always been interested in Tesla and the cars they are producing. ¬†They are poised to radically change the automobile industry, in a good and lasting way. ¬†For years though, that change has felt like it is a long way off, as the appetite for electric cars has languished and the infrastructure was sorely lacking. ¬†Now, however, based¬†on Andrew’s account, the future is here and it is exciting!

Code Watch: The first four habits of highly employable developers¬†‚Äď One of the key goals in my professional life¬†is to stay in tune with new technologies and new methods of software development. ¬†That doesn’t always mean¬†using the latest and greatest, but it does mean¬†knowing about them and letting them influence my current projects in the right ways. ¬†This article helps me appreciate that not only is this a balanced way of looking at things, but it will help me be employable if and when I am looking for another opportunity.

API Testing with Telerik Fiddler¬†‚ÄstI’ve been using Fiddler for years to debug websites and external APIs. ¬†But this post opened my eyes to a feature I didn’t know existed: the ability to test my own APIs from within Fiddler itself. ¬†You can load a Test List containing all the pertinent details of each request, and then setup Validators to compare the actual results against expected results. ¬†I look forward to utilizing this feature with my own APIs to improve their reliability and performance.

Open in IE Version 1.5

Today marks the release of an updated version of my Open in IE add-on for Firefox. ¬†This add-on is utilized by over 10,000 people on a daily basis to open certain sites in Internet Explorer that don’t work correctly in Firefox. ¬†I originally developed this to address¬†my own frustrations, but I am thrilled to see that so many other people have benefited from my work.

Looking Back

This update fixes a couple nagging bugs which I had received feedback about. ¬†But it also marks a major change in the architecture of the add-on. ¬†Prior versions were XUL-based, meaning they contained a mix of XML and JavaScript to modify the browser chrome‚ÄĒadding menu items, a toolbar button, and an options window‚ÄĒand handle click events. ¬†With that architecture, the functionality was spread over several different files and folders, some XML, some JavaScript. ¬†Even for me as the lone developer, it was a confusing mess every time I revisited it to make updates. ¬†From the user perspective, the main drawback of this approach was that¬†each install or update required you¬†to restart the browser in order to see the new functionality.

Today

The new version is what Mozilla calls a “bootstrapped” extension. ¬†With the new add-on architecture, the user does not need to restart the browser after installing or updating the add-on. ¬†It is immediately incorporated into the browser’s UI and functionality. ¬†But behind the scenes, in the code, the changes are radical. ¬†Radical, but definitely better! ¬†All the same functionality was accomplished with just two JavaScript files and a handful of icons. ¬†An SDK provided by Mozilla made the transition as painless as possible, with command-line tools for creating the files, loading¬†the add-on for testing in the browser, and packaging everything up for deploying to the add-on site. ¬†A future blog post will detail the steps involved in this transition.

Also, I’m happy to announce that the add-on is officially open source! ¬†While you have always been able to download the xpi file and open it up to see what’s inside, I have now posted the source code to GitHub. ¬†That means you can browse the code yourself and see how it works. ¬†Also,¬†if there is a specific feature that you would like to see in this add-on, you can code it yourself and create a pull request to get it incorporated in the released version. ¬†Enjoy!

Looking Ahead

With the release of Windows 10, Microsoft is retiring Internet Explorer and replacing it with a new browser named ‘Edge’. ¬†The Open in IE add-on can be made¬†to target Edge by changing the path to IE in the options window. ¬†But to make life easier, and to keep the statistics separate, I will be publishing a new add-on that targets Edge by default. ¬†Look for this new release around the time of the Windows 10 release.

 

 

The Good Bits – July 21

The Ultimate Guide For Getting Freelance-Ready When You’re A Self-Taught Coder РThis article caught my attention because I am a self-taught coder, and I hope to one day be a freelancer.  Joyce Akiko tackles the burning questions that many in my situation have asked or will ask if they have freelancing as a goal.  She packs a lot of information into this guide, but distills each key point into a takeaway, 10 in all.  After reading it, I can not only picture myself in the role of a freelancer, but I can start working towards that even now.

Attracting Developers to Your Company¬†– I really like Peter Morlion’s take on the dynamics of the ¬†software development job market. ¬†Presently, I know no out-of-work developers, and that has remained¬†true for¬†the last several years. ¬†As Peter points out, that has put employers and recruiters in the position of having to woo talent away from their present employers. ¬†Potential employees will take into account many other factors beyond what they will be working on, and that also allows them to be picky about the right opportunity for them to take. ¬†I certainly will be.

Visual Studio 2015 launches, with Android, iOS, and even Apple Watch support¬†– There is lots of news this week about the release of the new version of Visual Studio. ¬†As a software developer mainly focused on the Microsoft stack, this interests me a lot. ¬†But this article highlights one of the really exciting aspects of the new version: built-in support for cross-platform development. ¬†Eventually, I would like my mobile apps to be on all the major platforms, and being able to use one IDE¬†—¬†and potentially one language —¬†for that is hugely beneficial.

 

 

The Good Bits – July 6

This is the first in what will be a recurring series of blog posts for me.  As an avid learner in general, and in the field of software development more specifically, I come across a great many articles and blog posts which I find valuable and/or interesting.  Beginning with this post, I will collate the best of that information along with a few of my own thoughts and publish it for you.

Organizational Skills Beat Algorithmic Wizardry¬† –¬†An interesting post from 2013 by James Hague where he discusses the reality of modern software engineering jobs. ¬†The guts and the glory of any software solution, the algorithms or designs that are so highly prized, represent a small fraction of the actual work on any project. ¬†The rest of the¬†effort goes into supporting code such as file I/O, maintaining state, or¬†error handling. ¬†Organizational skills such as¬†refactoring, simplifying, and reducing complexity are put to much more use and therefore should be more highly valued.

Succeeding with Automated Integration Tests РEnd to end integration testing of your software is critical to its stability and success, but it can be a challenge to set up correctly. In this post, Jeremy Miller discusses some of his tips for making your integration testing more effective, efficient and reliable.  I particularly appreciated his emphasis on continuous integration as a key to getting value from automated testing.

5 Tips for Being an Effective Tech Lead – Are you a tech lead, or are you working toward that position in the future? ¬†This helpful post from Patrick Kua will enlighten you about some of the ways to be effective in that role. ¬†His reminder to stay in the code rang true for me. ¬†There’s no worse position than being a tech lead that has lost touch with the codebase. ¬†He also pointed out that this will help you build respect from the rest of the team, which has additional benefits.

 

Using KnockoutJS to Bind to Unknown Dataset

I’m currently working on a web application¬†that retrieves data from a web API and displays it in a web page, using KnockoutJS to provide the view model to bind to. ¬†In some scenarios, the shape of the data that is retrieved will be unknown at design time. ¬†The tables and columns that make up the dataset will be configurable via an admin section of the site. ¬†So when it comes to displaying the data on the page, I won’t know how many tables, rows, or columns are available.

Here is how I retrieve the dataset from the API:

var dataSetsUri = baseApiUri + 'http://localhost:63978/api/datasets/';
vm.getDataSetData = function() {
    var uri = dataSetsUri + datasetId;
    vm.dataTables([]);
    ajaxHelper(uri, 'GET').done(function (data) {
        if (data != '') {
            for (var key in data) {
                var table = data[key];
                vm.dataTables.push(table);
            }
        }
    });
};

Here is a sample of the data returned from that web service call:

{
"Students":
	[
		{"Id":"1","FirstName":"Joe","LastName":"One","AddressLine1":"1234 Main St.","AddressLine2":"","City":"Jacksonville","State":"FL","Zip":"32256","EmailAddress":"joe@one.com","DateOfBirth":null}],
"Awards":
	[
		{"AwardId":"1","StudentId":"1","Amount":"1111","AwardDate":null,"AwardStatus":"1","DeclineReason":null,"AcademicYear":"2014"},
		{"AwardId":"4","StudentId":"1","Amount":"10101","AwardDate":null,"AwardStatus":"1","DeclineReason":null,"AcademicYear":"2014"}
		
	]
}

Using the ‘foreach’ binding, I want to display the data in my HTML page. ¬†So I start with a div to act as a container. ¬†Within the container, I want a table for each data table in my results:

<div class="container" data-bind="foreach: { data: dataTables, as: 'table' }">
   ...
</div>

Now that I have the tables, I want to have a column in the tables for each column in my results. Notice that the column names will be different for each table, so I need to discover them dynamically at run time. To accomplish this, I add a function to my view model which can be called from the HTML:

vm.getColumns = function (row) {
    var columns = [];
    for (var col in row) {
        columns.push(col);
    }
    return columns;
};

Now I can call that function from the Knockout binding.  I use the $root syntax to reference the view model scope.

<thead>
    <tr data-bind="foreach: { data: $root.getColumns(table[0]), as: 'columnName' }">
        <th data-bind="text: columnName"></th>
    </tr>
</thead>

In the table body, I will need a row for each row in the data, so again I use the Knockout foreach binding. I also reuse the getColumns function to create the table cells in each row:

<tbody data-bind="foreach: { data: table, as: 'row' }">
    <tr data-bind="foreach: { data: $root.getColumns(row), as: 'cell' }">
        <td>
            ...
        </td>
    </tr>
</tbody>

The final step is to display the value in each cell. I can use the ‘row’ and ‘cell’ aliases from the foreach bindings to easily access the values. The final result:

<div class="container" data-bind="foreach: { data: dataTables, as: 'table' }">
    <table class="table table-bordered">
        <thead>
            <tr data-bind="foreach: { data: $root.getColumns(table[0]), as: 'columnName' }">
                <th data-bind="text: columnName"></th>
            </tr>
        </thead>
        <tbody data-bind="foreach: { data: table, as: 'row' }">
            <tr data-bind="foreach: { data: $root.getColumns(row), as: 'cell' }">
                <td>
                    <span data-bind="text: row[cell]"></span>
                </td>
            </tr>
        </tbody>
    </table>
</div>

And the finished product:
knockout
Go forth and code!

MinistryMate 2.4 Released

ministrymateToday¬†I released version 2.4 of my popular Windows Phone ministry app, MinistryMate.¬† This is the first update in several months, but¬†I’m certain the wait was worth it.¬† This update brings some very important functionality to the app: the ability to sync data to “the cloud.”¬† This functionality is useful for a¬†couple reasons.

First, it removes the need for manual backups of the app data.¬†Since the app was first released, backing up the data has been a constant concern among users who were fearful of unexpected crashes or phone malfunctions.¬† So I added the ability to backup the app’s data file to dropbox.com, and then¬†restore from that backup.¬† That allowed users to¬†easily reload their data if they had to reset their phone, or load it¬†on a different device if they switched phones.¬† But lately, the backup functionality has been finicky at best, frequently causing the app to crash, or not being able to retrieve the backed up file from dropbox.¬† So now, the data is backed up automatically to¬†a secure database on the WittersWorld.com web host.

Second, adding the cloud storage to the app enables the app to be used from any device on which MinistryMate is installed, without having to worry about losing or overwriting any data.¬† Today, that may not mean much. You most likely aren’t using two phones and need to have your latest ministry data on each one at any given time.¬† But in the near future, I plan on releasing MinistryMate as a Windows Store app!¬† At that time, you will be able to install it on a Windows 8 PC, a Windows 8 or Windows RT tablet, or a Windows Phone 8 device.¬† Then I expect that you will love having access to your MinistryMate data from any of those devices!

Thanks to all who have supported the app and continue to provide kind words and constructive criticism. Because of you, MinistryMate is the best ministry app on Windows Phone, and my hope is that it will soon be the best ministry app on Windows period.

The new version can be found in the Windows Phone store by clicking here.

Watchtower Library on Windows Phone 8?

I recently wrote a post about the fact that the Watchtower Library program is not available on Windows Phone 7, and detailing some possible workarounds.  A reader responded with the following question:

Do you have any news about WTLIB on Windows 8 Phone?

In short, no, I don’t have any information about the availability of Watchtower Library on WP8.¬† However, based on the redesign of the jw.org website, and the inclusion of the Watchtower Online Library, it seems to me that the branch does not intend to build native apps for any mobile platforms. That site is accessible from any internet-connected device with a mobile browser, eliminating the need for a dedicated app.

This is a wise approach for the brothers. Building a native app on each mobile platform currently available would consume a lot of time and resources that would be better spent elsewhere.¬† Even if they chose to only target one or two most commonly used OS’s, considerable effort is required to maintain the apps once they are published.¬† For example, as new literature is released, it would have to be incorporated into the apps.¬† Add to that the fact that the mobile OS landscape is in a constant state of flux, with new updates being released at a breath-taking pace.¬† Publishing the data via a well-designed website is a much more cost-effective choice, without sacrificing any of the convenience that comes from having it on your mobile device.

YAGNI

I recently read a blog post regarding the YAGNI principle of programming.¬† The acronym stands for “You Aren’t Gonna Need It!”.¬† The idea really hit home for me because, while I’ve never heard it before, I have seen its truthfulness play out time and again in my programming career.¬† In hindsight, this approach could have saved me countless hours of coding/testing/debugging/refactoring on features that were not ever used.¬† Putting that time and effort to good use on the parts of my projects that were actually used could have benefited not only me, but my managers and employers.

One example was a project I worked on in the early days of .NET 1.0.  We were porting an ASP web app with a C++ back end to use C# and ASP.NET.  The lead developer/architect insisted on building an overly complicated process to protect the code from any unexpected changes to the underlying data structures.  In theory, it was a useful feature, employing a command-line app to generate strongly-typed datasets, which allowed us to be notified at compile-time of any changes to the structure and modify our code accordingly.  What was missing from that equation, however, was the fact that during the 3-year duration of the project, the number of data structure changes could be counted on one hand.  And each of those changes was thoroughly documented well ahead of time, so the requisite changes on our end could be made at the appropriate time.

In addition to the added time spent building and maintaining the supporting app, this approach forced developers to retrieve data in a rigid and non-performant fashion.  The resulting complexity slowed down development of core pieces of the application and ultimately led to more bugs and less readable and less maintainable code.  The debate raged within the development team about whether or not this was the appropriate way to architect the application, but its clear in looking back that the most efficient use of our time and resources would have been to avoid the added complexity and build only what we needed, only when we needed it.

More recently, a development manager that I worked for was fond of designing elaborate and complex solutions to problems that we had not yet encountered.  Often, this involved some new design pattern he had read about and wanted to find a way to work into our project.  The result was seemingly constant revisions to the product release dates, as well as sometimes tense discussions with upper management trying to rationalize the delays.  Also, we frequently had to deal with performance issues due to unnecessary layers in the architecture.  We finally made the decision to pare down the code base to just the basics, and the resulting simplicity and improved performance was refreshing!

Having lived and learned, I vow never to build in features before I need them.  My time is too valuable to spend on something that may never be used, no matter how brilliant it may seem at the time!

AssemblyMate: Now on Android

AssemblyMate_AndroidA few months ago, I released my latest Windows Phone app, AssemblyMate.¬† It’s a simple app designed for use by Jehovah’s Witnesses to take notes at assemblies and conventions.¬† I have received a lot of positive feedback from users of the app, and I’ve enjoyed using it myself.¬† But being available only on Windows Phone presented some limitations.

First, the relatively small form factor of the phone makes note-taking a little tedious.¬† It’s not terrible, but not ideal either.¬† In the post where I mentioned the initial release of AssemblyMate, I mentioned that I was looking forward to Windows 8 as an opportunity to run the app on a larger tablet device.¬† While those devices are coming soon, they are not yet available.

Second, despite the high level of satisfaction expressed by those who have adopted Windows Phone, the fact remains that the group remains small compared to other mobile OSes.  Again, I expect this to change in the future as the Windows 8/Windows Phone 8 software and devices created by Microsoft and their partners gain traction and popularity among consumers and businesses.  But such widespread adoption is likely six months to a year away, in the best case scenario.

The solution to both of those problems was to port the application to another mobile OS, either Android or iOS.¬† Both platforms run on tablet devices and both have large user bases to which I could market my apps.¬† In the end, I settled on Android as the next platform for AssemblyMate.¬† It was a grueling, months-long process.¬† First, I had to familiarize myself the process and tools involved with writing and publishing Android apps.¬† Then I had to learn how to code in Java.¬† Due to my familiarity with C#, it wasn’t totally foreign, but the difficulty of performing some tasks made it a struggle at times.

The good news is that the process finally came to an end today.  This morning I published AssemblyMate on Google Play.  Download and enjoy!

UPDATE: As of July 15, the app is now also available in the Amazon app store (download here), and will soon be available in the Barnes & Noble Nook app store.

P.S. Since it is my first Android app, and I don’t have a physical device on which to test it, I intended to release the app as a beta version, free to early adopters, and then begin charging for the app after I weed out bugs and any device-specific issues.¬† However, the Google policies would not let me switch from free to paid at a later date, so I had to set the $0.99 price from the start.¬† If anyone wants to get a free copy and help with beta testing, email me and I will hook you up.