Installing Microsoft Team Foundation Server is a ridiculously arduous and difficult process. I'll spare you my own complaints and simply list the checklist for installing this beast. This assumes you're installing TFS in a domain-enabled environment and in single-server mode; this is the typical configuration for a small-to-medium-size organization:
- Designate a machine to host your Team Foundation Server repository. This machine must not double as a domain controller as this configuration is not supported by TFS.
- Set up at two regular user accounts (not administrators, and if you have any group policies you may - according to your configuration - want to keep these users out of the relevant OUs) in your Active Directory. I used the trivial TFSService and TFSReports accounts. Also you'll need a user with administrative privileges on the target server; I personally prefer to avoid the associated headaches, so I simply used a domain administrator user for installation purposes (but used the aforementioned two users to set the beast up).
- If necessary, install Windows 2003 Server (whatever flavor) on the machine; don't forget the necessary service packs and updates. If your pipe is fat enough, just let Windows Update do its magic.
- Add an Application Server role, make sure you enable ASP.NET 2.0 during the installation process
- Install SQL Server 2005. Make sure you read the installation guide first though, as you'll need to set it up to "Use the built-in System account," enable all services except Notification and finally select Windows authentication as the preferred authentication mechanism. You'll also need to let the SQL Server installer install a bunch of prerequisites before actual installation begins.
- Install SQL Server 2005 Service Pack 2.
- From the TFS installation media, install hot-fix 913393 for .NET Framework.
- Install Windows SharePoint Services 2.0 with Service Pack 2.0. Make sure you select server farm mode when installing, or you'll just have to redo the installation.
- Install Team Foundation Server itself.
- Back up the reporting services encryption key (you can find a description of the procedure here).
- Install hot-fix 919156, a.k.a the Quiescence GDR (no, I have no idea what GDR stands for).
- Install Team Foundation Server Service Pack 1.
- Make sure TCP port 8090 is open in your firewall software if you want web access to your Team Foundation Server (to be honest, I haven't found any use for it yet.)
- Install Team Explorer from the installation media (required for many add-ons, including eScrum).
- Install Visual Studio 2005 Team Suite Service Pack 1. This can, and will, take forever.
If at this point you're not thoroughly exhausted, you might want to set yourself up a with a project. We're currently evaluating the Microsoft eScrum template for our purposes; my colleague Oren Ellenbogen, in his capacity as Scrum Master, will probably be posting his thoughts on eScrum as a platform. In the meantime here's a quick list of solutions to problems we've encountered while configuring the beast:
- Make sure you install the various prerequisites; in this case, .NET Framework 2.0, IIS, TFS and Team Explorer, AJAX Extensions 1.0 and the Anti-Cross Site Scripting Library
- At this point you're liable to get a strange SharePoint-related error if you try and create an eScrum-based project; if that's the case (or as a preemptive measure), just run iisreset on the TFS server.
- If you can't seem to access the eScrum website (nominally at http://yourserver/eScrum) you may have to reconfigure the eScrumAppPool identity from the IIS manager (right click the application pool, chose Properties, go to the Identity tab and enter the right information under Configurable)
- You may also get 404 errors from the eScrum website even though it's very obviously configured. We've found that the solution described here works as well:
- From the command prompt, type cd "%ProgramFiles%\Common Files\Microsoft Shared\Web Server Extensions\60\BIN"
- Run STSADM.EXE -o addpath -url http://localhost/eScrum -type exclusion
- Run iisreset again
- eScrum reports only update once every 1 hour. If this bothers you, follow the instructions here to reduce the lag.
Hope this saves someone out there a lot of time and headache (and if so, a comment or e-mail is always appreciated...)
A new organization and a new office require a new IT infrastructure. I'll spare you the gritty details and just mention several installation issues we've encountered and how to resolve them.
| ||Problem: ||Windows Server 2003 installed on a RAID array via NVidia RAID controller; drivers are not available on the regular installation CD-ROM.|
| ||Solution: ||Use a USB floppy drive (most servers and workstations don't come with floppy drives nowadays, and with good reason). In the case of the Tyan server we use, booting off of the driver CD allowed me to create a driver floppy which I then used when installing Windows.|
| || || |
| ||Problem: ||Windows can't locate file "nvraid.cat" when using the NVidia RAID controller drivers.|
| ||Solution: ||Hit the escape button to ignore the missing files (apparently that .CAT files are used for cryptographic purposes and are not provided by NVidia, see here).|
| || || |
| ||Problem: ||Nero refuses to install without installing DirectX 9.0c first on Windows Vista.|
| ||Solution: ||Although Vista comes with DirectX 10, you can safely agree to this and skip the DirectX installation later. Why a CD/DVD burning package requires DirectX (even though I didn't install any of the additional crap provided by Nero) is beyond me.|
| || || |
| ||Problem: ||Not strictly an installation issue, but there isn't any immediately apparent way to echo an empty line from the Windows command processor.|
| ||Solution: ||While "echo /?" won't tell you this, the MSDN documentation for the same command clearly mentions "echo." (written exactly so). Contrived.|
| || || |
| ||Problem: ||Setting up a DNS canonical name (alias) entry for a file server results in "Duplicate name exists on the network." errors when attempting to use the network resource.|
| ||Solution: ||Find registry key "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters" and set the value of "DisableStrictNameChecking" to 1. (More information)|
| || || |
| ||Problem: ||Newly configured DHCP server doesn't respond to "ipconfig /renew" requests.|
| ||Solution: ||Although I can't explain this, the problem was not the DHCP server; right-clicking the network connection icon and then selecting Repair did actually manage to obtain a lease. If this happens to you, don't get upset (as I did), try this technique first and see if it works for you.|
I'll add a separate post on TFS and eScrum later today or tomorrow (hopefully).
I didn't want to post this before all formalities were complete, and now that they are I can finally announce my new workplace: a shiny new Israeli startup called Semingo.
I can't currently say much about what it is we're doing, but it's a huge challenge and it's quite a change of pace from my previous job. It's also a nice plus working alongside fellow bloggers Oren Ellenbogen and Pasha Bitz, and trying out New and Improved™ methodologies such as Scrum.
As an aside, here's a couple of videos of the last project I worked on running on the eMobile EM-ONE device (the second video appears to be a leaked beta version. Curious!) If you can read Japanese, there's more about it here. There's absolutely no way to demonstrate this without one of these devices, so while I regret the poor video quality, it's definitely better than nothing...
Update: Now that we've enjoyed a bit of spotlight in Israeli publication The Marker (Hebrew only, sorry) I'll be able to progressively discuss more about what we do at Semingo. Heads up!
Can you see the problem?
Didn't think so. I'll clue you in: the last one in that list has one distinct difference with the first four. Look around you. Have you found what we're looking for?
That is correct. The answer is: the semicolon. A lightweight, generally meaningless way to end a statement in most common languages. Arguably useless to users, arguably beneficial to parsers, and the cause of almost half an hour of continuous head-scratching by both programmer and DBA. How so?
C:\Temp>mysql -C -usomeuser -phispassword thedatabase;
ERROR 1044 (42000): Access denied for user 'someuser'@'%' to database 'thedatabase;'
I'll let you draw your own conclusions.
Let's start off with Hot Fuzz. This movie, from the creators of Shaun of the Dead, is an action-comedy about an overachieving London cop who, in order not to make his contemporaries in the police force look bad, is sent to a backwater little English village. While the worst crime in the village appears to be serving alcohol to minors, a series of "accidents" lead Sgt. Angel to dig deeper into the unlikely inhabitants of the village until he finds out what really goes on. Combining hilarious action and outrageous comedy (not to mention goofy references to classic action films), this is going to be one of my favorites for a long time yet.
After an amusing but unspectacular sequel, Shrek returns in what I expected would be a "the quest for more money" kind of movie. Despite (or maybe because of) my ridiculously low expectations I actually enjoyed Shrek the Third quite a bit. It's not a brilliant movie by any means, but it has a much better signal-to-noise ratio than the second one in my opinion, and my companions and I laughed our asses off throughout the production. Bottom line? If you're looking for a fun way to spend a couple of hours, it works very well.
It's hard to explain just how low my expectations of Transformers were. To me, it's a classic "well how can it not suck?" kind of movie, along with Resident Evil and Bloodrayne (both of which sucked, in case you were wondering). And I'm not even a fan of the TV series, so I had every reason to expect a terrible movie.
Well, it actually wasn't. The first half is surprisingly funny (not "ha-ha" kind-of funny, I mean "laugh out loud" funny), and the second half is non-stop, kick-ass action. This movie is definitely going to become high-definition reference material when it comes out on Blu-Ray or whatever, and the intentionally simpleminded plot works very well indeed. Biggest surprise of the year - recommended!
And they're getting better at it:
I mean, what the hell? That looks like a goddamned phi (φ) in italics! I couldn't even figure it out, it took a coworker to figure out that it's supposed to be "cp"...
I've been working with Rhino Mocks for a couple of days now and I'm duly impressed. Aside from being generally useful, the Rhino Mocks syntax is mostly natural and some very clever design hacks are used to make it work the way you'd expect it to. (In case you don't know what mocking frameworks are, the subject has been tackled ad nauseam. Just take your pick.)
There is one caveat that is not immediately visible in the Record-Playback syntax, though:
internal interface IFoo
[ExpectedException( typeof( InvalidOperationException ),
"Type 'System.Object' doesn't match the return type " +
"'System.Int32' for method 'IFoo.Bar();'" )]
public void TestRecordSyntax_ReturnTypeMismatchBehavior()
MockRepository mocks = new MockRepository();
IFoo mock = mocks.CreateMock<IFoo>();
using ( mocks.Record() )
Expect.Call( mock.Bar() ).Return( new object() );
This simple test merely returns an incorrectly typed return value for the IFoo.Bar method, so with the ExpectedException in place you'd expect it to succeed, but you're in for a surprise:
failed: Exception of type 'MbUnit.Core.Exceptions.ExceptionExpectedMessageMismatchException' was thrown. Expected exception message: "Type 'System.Object' doesn't match the return type 'System.Int32' for method 'IFoo.Bar();'", got "Previous method 'IFoo.Bar();' require a return value or an exception to throw.".
To understand this, consider the following flow:
- A method call expectation is set (by calling mock.Bar())
- Attempting to set a wrong return type results in the expected exception being thrown from Rhino Mocks. This happens before the Return constraint is set
- Because using calls IDisposable.Dispose in the finally block, the mocks.Record object calls mocks.ReplayAll()
- ReplayAll asserts because a required expectation (return value) is not yet set, masking the expected exception!
This is in fact how I first encountered this behavior, however there are several scenarios where this can happen. One example: setting up a return value that throws an exception on construction, possibly due to invalid arguments, causes the same behavior thereby masking the true cause of the error.
An alternative syntax suggested by Ayende (author of Rhino Mocks) is:
Expect.Call( mock.Bar() ).Return( new object() );
Aside from the esthetical aspect (i.e. butt-ugly), this syntax introduces a minor issue: you cannot Edit-and-Continue methods with anonymous delegates. This may not be a big deal for test code but it's worth noting.
All in all I don't consider this a big issue, but it can bite and should therefore be understood and documented. This post will be reflected in the Rhino Mocks wiki shortly and will hopefully save someone a little grief in the future...
Quick download link (v1.2)
I wanted to simple way to download an entire PicasaWeb album. Right-click and save simply will not do, installing the Picasa application is completely out of the question (I use FastStone, in case you were wondering) and I couldn't find any easy way of doing this, so I whipped up a quick and dirty application. It's pretty self-explanatory, really:
Download the application (source included) here.
I also used the chance to give #Develop a serious whirl, and I can honestly say that it's damn impressive; in several hours of use the only real qualms I've had with it are the non-configurable keyboard bindings (at least I couldn't find any configuration menu for this; it wouldn't be an issue if the default bindings weren't slightly different from what I'm used to) and the lack of immediate/watch debug windows. The dialog editor is full-featured and the environment seems to be quite responsive and robust. I really am impressed.
Update (20-Aug-2007): Version 1.1 is now downloadable. I've added support for AuthKeys (as per skolima's request) so you should now be able to download private albums as well (assuming you have the appropriate key). Also added a compiled binary to the archive, doh!
Update (11-Sep-2008): Version 1.2 is available for download, and includes the following improvements:
- The tool now works for PicasaWeb albums from any valid top-level domain (this means that albums hosted at www.picasaweb.ru will be properly handled.
- Existing files will not be overwritten; instead I've taken a cue from common browsers and am now adding a counter suffix to the filename. If an album has two pictures with the name example.jpg, you can now expect to find two files named example.jpg and example (2).jpg in your directory. This behavior is also applied if you already have such a file in your directory prior to running the tool - any feedback as to whether or not this is desirable will be appreciated!
- Authentication keys may now include dashes (thanks, Jakob).
It's official: I'm leaving Monfort Software Engineering, my workplace and second home for the last two years. I'm leaving with mixed feeling because I consider Monfort to be one of the finest places I'll ever find on both a technical and personal level, but it's time for me to move on.
I have several promising alternatives and will be settling on a new job by the end of the month; until that time I'm still open to offers (and will consider relocation if the offer is enticing). You can find up-to-date CV and contact information here or through the navigation menu on the right.
My brother was going on and on about a coding challenge he found as part of the "Lisp as an Alternative to Java" study (the challenge instructions are outlined here, and you can find the sample dictionary and input data by following the study link); eventually I agreed to give it a try.
Spoiler alert: Do not read on if you want to take on this challenge!
Although I had to stop in the middle because I had company, the initial (hacked-together, very inefficient and completely uncommented C# 2.0 code) version took me 1 hour and 20 minutes. While technically correct this version performed abysmally, but it served as a good basis for further optimizations; a second, optimized version took another 30 minutes and with another 20 or so minutes to clean it up, the final version took a grand total of 2 hours and 20 minutes. Total length is 193 lines of code (including comments and white-space), which you can find here.
The crux of the solution is a very simple tree structure to hold the word dictionary. Each node has a 10-entry branch table, each entry representing a phone digit; a node can have an arbitrary number of leaves, each leaf representing a dictionary word. This allows for a very simple (and hopefully efficient) inner search loop:
- Use successive digits as indices for traversal into the tree;
- When a node with leaves is encountered, the leaves (dictionary words) are added to the potential result set. The rest of the input is then recursively encoded;
- If no leaves are encountered for the entire input set, a digit is added to the encoded string and the rest of the input is again encoded. A boolean flag is passed along with the recursion to make sure two consecutive digits are never encoded.
This is basically a prefix tree (or trie). With the provided dictionary and input sets, runtime on my 1.7GHz Pentium M-equipped laptop is approximately three seconds. I haven't properly profiled the application for CPU and memory utilization because, frankly, it's good enough. There's also a lot of leeway for optimizations: the current tree implementation is woefully inefficient, as tree traversal can result in additional memory pressure.