Delete Another User’s Workspace in TFS

I’ve run into this problem several times. A build blows up for some reason and creates an orphaned workspace. Other builds then fail with the message The path […] is already mapped in workspace […].

tfsbuild_alreadymapped

The way that I’ve dealt with this in the past is to simply delete the workspace, which you can do easily enough by using the tf workspace command.

tf workspace /delete someworkspace;somedomain\someuser

When you run the command, you’ll be warned that deleted workspaces cannot be recovered and prompted to confirm.

tfsbuild_reallydeleteworksp

Type “Yes” and the deed is done. Run another build, and you should be good!

 

Get Cute with Predecessors in Microsoft Project

I’ve known about Microsoft Project for a long time, but I’ve never really done anything with it until recently. There are several Project aficionados around the office. I’ve taken a peek here and there at their projects, but I just didn’t see the value. I don’t think I was ready for it. My team recently adopted Project as its primary planning tool, though, and so I’ve been using it more frequently. Little by little, I’m learning and becoming more comfortable with it, and I’m liking it more each day. I’m not a zealot yet, but I may very well be on my way.

The coolest feature I’ve learned about is the Predecessors field for tasks. If you’ve seen project at all, you’ve probably seen this. It allows you to say, “Task A must be finished before Task B, and Task B must be finished before Task C.” That makes sense, but it’s not all that impressive. What’s cool about it, and much less obvious, is that you can specify the dependency type for a predecessor. You can also specify lead time and lag time. These two features allow you to plan for more complex–and realistic–scenarios: “Task A must be finished before Task B, and Task C should start two weeks after Task B is completed.”

Dependency Type Description
FS (Finish-to-Start) Start the day after the predecessor finishes
FF (Finish-to-Finish) Finish the day the predecessor finishes
SS (Start-to-Start) Start the day the predecessor starts
SF (Start-to-Finish) Finish the day the predecessor starts

That’s all good and well, but how is any of this useful? Well, by using these different dependency types, you can pick the task or milestone that’s most important to your project and build a plan around it. Then, if the date of that all-important item changes, the rest of your plan can adjust automatically.

My team is responsible for creating small, custom projects for our customers. We have a backlog of work, and we want to schedule our development work based on a projected deployment date. We enter the deployment task first and build the plan backward from that. In order to deploy, development needs to be done two weeks before. In order for development to begin, we need a completed design. To create a design, a requirements document must be signed by the customer. And so on.

In Project, that plan might look like this. Note that the dates in italics are calculated from the predecessors.

ID Task Duration Date Predecessor
1 Requirements 1 wk 5/6/13 2SF-1 wk
2 Design 1 wk 5/20/13 3SF-1 wks
3 Develop 4 wk 6/3/2013 4SF-2 wks
4 Deploy 1 wk 7/15/2013

To create this plan, I picked my targeted deployment date. The development task’s predecessor says, “The deployment task’s start date should be my finish date with 2 additional weeks of lead time.” Similarly, the design task should start so that it will be finished 1 week before the development task is scheduled to start, and the requirements task should be done 1 week before the design task begins.

Now let’s throw a curveball at the plan. Say that something comes up, and the customer needs an upgrade before I can do my deployment. I can insert a new task, and make it the deployment task’s predecessor. Everything else adjusts automatically.

ID Task Duration Date Predecessor
1 Requirements 1 wk 5/27/13 3SF-1 wk
2 Design 1 wk 6/10/13 4SF-1 wks
3 Develop 4 wk 6/24/2013 5SF-2 wks
4 Customer upgrade 0 days 8/5/13
5 Deploy 1 wk 8/5/2013  4

That’s so awesome! I just shifted the entire project plan to reflect a new milestone that nobody ever saw coming.

Fill-In Field Prompts in Word 2013

I was creating a Word document template for my team to use, and I wanted to include a reference number in the header to make it appear on each page. I initially created a field for the user to click and enter the value. The problem with using a simple entry field and sticking it in the header is that it’s grayed-out and easily forgotten.

So, instead of using a textbox field, I decided to prompt the user for the value by using a fill-in field. It’s an easy thing to do, and users of the template will never forget to enter the value. (Of course, they might choose to ignore the prompt, but that’s a different problem!)

To create a fill-in field in Word 2013, do the following:

  1. Put your cursor in the document where you want the field to appear
  2. In the INSERT bar in the ribbon, choose Quick Parts > Field…

    Word2013_FIllIn_QuickParts

  3. In the Field dialog, choose Fill-In as the field name, enter the prompt text, and click OK

    Word2013_FIllIn_FieldPrompt

  4. Be sure to save your document as a Word Template

    Word2013_FIllIn_SaveAs

That’s all there is to it. When you create a new document from the template, you’ll be prompted, and the value will be filled in.
Word2013_FIllIn_ValuePrompt

Good stuff!

Life-Changing Shortcuts: Windows Key + Arrow

Multiple screens are a must-have these days. I have just two, and I’m constantly throwing windows back and forth. Windows 7 introduced some nice docking features that make this easy and efficient. I can drag a maximized window by the title bar, and it will un-maximize. If I then “push” it to the top of my other screen, it will re-maximize.

Windows 7 also lets you drag windows to the sides of your screen to half-maximize it; the window will use the entire vertical space but only half of the horizontal space, as if it were docked to the side of the screen to which it was dragged. Great. I love it.

But there’s a problem. There are no edges between my screens. Ugh… I guess I’ll just resize the window to make it half-screen sized, and then manually position it along the crack like a caveman. I mean, there’s no better way to do this, right?

That’s what I might’ve said if this were 2012. I know some things now that I didn’t know then. That’s right, I’m talking about the Windows key + arrow shortcut. Use this amazing shortcut to reposition windows by jumping through the different docking options. Here’s the summary:

Shortcut Description
Windows + ↑ Maximize a normal or left/right-docked window
Windows + ← Left-dock a window; cycle through side-dock positions
Windows + → Right-dock a window; cycle through side-dock positions
Windows + ↓ Un-maximize or un-dock a window; minimize a normal window

Toggling maximize and minimize are no big deal, and neither are dock-left and dock-right. What is useful, however, is that dock-left and dock-right respect the boundary between displays. OMG–life changed! This is easily my favorite new shortcut of 2013. So, you probably won’t use this shortcut to maximize or minimize windows, but remember it for the next time you’re trying to look at four things all at the same time. I bet you’ll fall in love.

Pretty Forms with CSS & jQuery

Let’s say you’re making a web form. You want it to look nice, so you’d like the input controls to line up and be consistently sized. You know that you shouldn’t be using tables for formatting, but how else can you avoid creating an ugly mess of labels smushed-up against their controls?

UglyForm

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
    <script type="text/javascript"></script>
    <style type="text/css"></style>
</head>
<body>
    <div>
        <label for="name">Name:</label><input type="text" name="name"/><br/>
        <label for="email">Email:</label><input type="text" name="email"/><br/>
        <label for="password">Password:</label><input type="password" name="password"/><br/>
        <label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/><br/>
        <label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/>
    </div>
</body>
</html>

I found a cool trick to fix the spacing of labels and controls using jQuery. The idea is simple: loop through all labels and set their widths equal to the widest. The logic to do this is a typical CS-101 find-the-max loop, but there’s also a not-so-obvious second step. In order for the widened labels to display, they must be floated to the left.

LessUglyForm

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> 
    <script type="text/javascript">
         $(function() {
             var max = 0;
             $("label").each(function () {
                 if ($(this).width() > max)
                     max = $(this).width();
            });
            $("label").width(max + 5);
        });
    </script>
    <style type="text/css">
        label {
            float: left;
        }
    </style>
</head>
<body>
    <div>
        <label for="name">Name:</label><input type="text" name="name"/><br/>
        <label for="email">Email:</label><input type="text" name="email"/><br/>
        <label for="password">Password:</label><input type="password" name="password"/><br/>
        <label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/><br/>
        <label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/>
    </div>
</body>
</html>

Fixing the label spacing helps, but it’s still pretty ugly. You don’t want the textboxes rubbing shoulders like that, and why are the password boxes slightly shorter than the textboxes? We can fix both of those items with some simple CSS.

OkayForm

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> 
    <script type="text/javascript">
        $(function() {
            var max = 0;
            $("label").each(function () {
                if ($(this).width() > max)
                    max = $(this).width();
            });
            $("label").width(max + 5);
        });
    </script>
    <style type="text/css">
        label {
            float: left;
        }
        input {
            margin: 2px;
        }
        [type=text], [type=password] {
            width: 150px;
        }
    </style>
</head>
<body>
    <div>
        <label for="name">Name:</label><input type="text" name="name"/><br/>
        <label for="email">Email:</label><input type="text" name="email"/><br/>
        <label for="password">Password:</label><input type="password" name="password"/><br/>
        <label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/><br/>
        <label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/>
    </div>
</body>
</html>

Okay, now we’re starting to look like a respectable form! We can make our form a little nicer by adding a fieldset control to house our controls, and we can add a label to controls through the fieldset’s legend. In order to facilitate auto-sizing of the fieldset–it’s 100% width by default–I moved the labels and inputs into a list, and that required another jQuery loop and some CSS. As final step, add more CSS to further improve aesthetics. For this example, I added a custom web font and made the fieldset legend bold and red.

PrettyForm

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> 
    <script type="text/javascript">
        $(function() {
            var max = 0;
            $("label").each(function () {
                if ($(this).width() > max)
                    max = $(this).width();
            });
            $("label").width(max + 5);
            max = 0;
            $("fieldset").each(function() {
                $(this).find("li").each(function () {
                    var w = $(this).find("label").width() + $(this).find("input").width();
                    if (w > max)
                        max = w;
                });
                $(this).width(max + 10);
            });
         });
    </script>
    <link href='http://fonts.googleapis.com/css?family=Unkempt' rel='stylesheet' type='text/css'>
    <style type="text/css">
        body {
            font-family: 'Unkempt', sans-serif;
        }
        fieldset {
            margin: 10px;
            padding: 10px;
        }
            fieldset legend {
                font-weight: bold;
                color: maroon;
            }

            fieldset ul {
                margin: 0;
                padding: 0;
            }

            fieldset li {
                list-style: none;
                padding-bottom: 10px;
            }
        label {
            float: left;
        }
        input {
            margin: 2px;
        }
        [type=text], [type=password] {
            width: 150px;
        }
    </style>
</head>
<body>
    <fieldset>
        <legend>User Info</legend>
            <ul>
                <li><label for="name">Name:</label><input type="text" name="name"/></li>
                <li><label for="email">Email:</label><input type="text" name="email"/></li>
                <li><label for="password">Password:</label><input type="password" name="password"/></li>
                <li><label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/></li>
                <li><label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/></li>
            </ul>
    </fieldset>
</body>
</html>

Create Permanent Custom Styles in Outlook

One of my peeves in Outlook is the formatting of code snippets that I send in email. Nine times out of ten, I’m copying and pasting from Visual Studio. That works pretty well; you get keyword highlights and all that fun stuff. Life is good–unless you happen to have a dark background. I like the dark theme for Visual Studio 2012, but I can’t stand that pasted text comes with a black highlight! It’s not that I mind the black background, but the highlighted text looks like a disaster.

DarkBackgroundCodePasteIntoOutlook

At this point, you’ve got three options: go back to a light-background theme in Visual Studio, deal with it, or adjust the formatting in Outlook. It looks too ugly for me to ignore, so option #2 is out. Until know, I’ve been exercising option #1, living in a default-themed world. I decided to go in a different direction today, though. I created a style that I can use to quickly format my pasted code. (An easy solution that I considered using for a while was to use LINQPad as a formatting buffer. I’d copy/paste code from Visual Studio to LINQPad and then re-copy/paste from LINQPad to Outlook. It works.)

The key to making this as painless as possible is getting the style configured correctly. Here are the steps I used to create my new style in Outlook 2013:

  • Choose “Create a Style” from the Styles gallery (FORMAT TEXT > Styles)
  • Change paragraph spacing options
    • After: 0 pt
    • Line Spacing: Single
  • Modify borders and shading
    • Border Setting: Box
    • Border Color: White
    • Border > Options > From text (all sides): 12 pt
    • Shading Fill: Custom Color (RGB: 30, 30, 30)

To ensure the style sticks around for future emails, do the following:

  1. Change Styles > Style Set > Save as a New Style Set…
  2. Change Styles > Style Set > Set as Default
  3. Restart Outlook for the new default style set to take effect

When I paste code from my dark themed Visual Studio, it still looks ugly. I can make it prettier by simply selecting the text and applying my new style. As a final beautification, I select the text and remove the black highlight from the text. (The removal of highlighting wouldn’t be necessary if I were content to use a black background, but I think 30/30/30 gray looks nicer, and so I will remove the highlight.)

DarkBackgroundCodePasteIntoOutlook_Better

It’s definitely a few extra clicks anytime I’m sending code, but the end product looks good!

Posting Data to an ASP.NET Page Method with Knockout

PostingDataToPageMethodWithKnockoutSample

Last time in my Knockout series of posts, I explored how to retrieve and bind data from an ASP.NET page method. That’s only half the battle, though. How can you take data captured and do interesting things with it? I’ve got an idea! How about passing it to an ASP.NET page method!

I’m going to use my example from last time with a few modifications. I added some entry controls to capture the user’s status, and I modified the GetStatus page method to return the user’s last status. The last status values will be displayed as read-only and will only be visible when a value exists. Here’s the ASPX and code-behind. Note that ASPX contains a button bound to a method in the view model that’s not yet implemented, and the code-behind has a UpdateStatus method.

default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                wasHappy: ko.observable(),
                lastStatusText: ko.observable(),
                isCurrentlyHappy: ko.observable(),
                currentStatusText: ko.observable(),
                updateStatus: updateStatus,
            };
            ko.applyBindings(viewModel);
            getLastStatus();

            function updateStatus() {
                // todo: post data to page method
            }

            function getLastStatus() {
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/GetStatus",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (result) {
                        var data = result.d;
                        if (data == null) {
                            $("#lastTime").hide();
                            return;
                        }
                        $("#lastTime").show();
                        viewModel.wasHappy(data.HappyFlag);
                        viewModel.lastStatusText(data.Text);
                    }
                });
            }
        });
    </script>
</head>
<body>
    <div>
        <strong>How are you feeling?</strong><br/>
        Are you happy? <input data-bind="checked: isCurrentlyHappy" type="checkbox"/><br/>
        Tell me about it: <input data-bind="value: currentStatusText"/><br/>
        <button data-bind="click: updateStatus">Update Status</button>
    </div>
    <div id="lastTime">
        <strong>How you felt last time:</strong><br/>
        Were you happy? <input data-bind="checked: wasHappy" type="checkbox" disabled="true"/><br/>
        What you told me about it: <span data-bind="text: lastStatusText"></span>
    </div>
</body>
</html>

default.aspx.cs:

using System;
using System.Web.Services;

namespace adamprescott.net.Knockout
{
    public class Status
    {
        public bool HappyFlag { get; set; }
        public string Text { get; set; }
    }

    public partial class Default : System.Web.UI.Page
    {
        private static Status lastStatus = null;

        [WebMethod]
        public static Status GetStatus()
        {
            return lastStatus;
        }

        [WebMethod]
        public static void UpdateStatus(Status status)
        {
            lastStatus = status;
        }
    }
}

When the button is pressed, we need to collect values and put them into an object to be passed to our page method. That’s easy–just grab values from the view model:

var data = {};
data.HappyFlag = viewModel.isCurrentlyHappy();
data.Text = viewModel.currentStatusText();

Now that we’ve got our values, we just need to pass them to our page method. Once again, it’s jQuery to the rescue!

$.ajax({
    type: "POST",
    url: "Default.aspx/UpdateStatus",
    data: JSON.stringify({ 'status': data }),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function () {
        // todo: anything?
    }
});

Bam! We just passed data to the page method in the code-behind. Tutorial accomplished. However, I need to go a little further. Now that I just updated the status, I want my UI to update its view to show the latest status. So, when my call to UpdateStatus finishes successfully, I just need to make another call to GetStatus. Super easy!

Here’s the final ASPX.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                wasHappy: ko.observable(),
                lastStatusText: ko.observable(),
                isCurrentlyHappy: ko.observable(),
                currentStatusText: ko.observable(),
                updateStatus: updateStatus, 
            };
            ko.applyBindings(viewModel);
            getLastStatus();

            function updateStatus() {
                // todo: post data to page method
                return;
                var data = {};
                data.HappyFlag = viewModel.isCurrentlyHappy();
                data.Text = viewModel.currentStatusText();
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/UpdateStatus",
                    data: JSON.stringify({ 'status': data }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function () {
                        getLastStatus();
                    }
                });
            }

            function getLastStatus() {
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/GetStatus",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (result) {
                        var data = result.d;
                        if (data == null) {
                            $("#lastTime").hide();
                            return;
                        }
                        $("#lastTime").show();
                        viewModel.wasHappy(data.HappyFlag);
                        viewModel.lastStatusText(data.Text);
                    }
                });
            }
        });
    </script>
</head>
<body>
    <div>
        <strong>How are you feeling?</strong><br/>
        Are you happy? <input data-bind="checked: isCurrentlyHappy" type="checkbox"/><br/>
        Tell me about it: <input data-bind="value: currentStatusText"/><br/>
        <button data-bind="click: updateStatus">Update Status</button>
    </div>
    <div id="lastTime">
        <strong>How you felt last time:</strong><br/>
        Were you happy? <input data-bind="checked: wasHappy" type="checkbox" disabled="true"/><br/>
        What you told me about it: <span data-bind="text: lastStatusText"></span>
    </div>
</body>
</html>