A Dutch software developer living in Chile
| | Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|
| 30 | 31 | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 | 11 | 12 | | 13 | 14 | 15 | 16 | 17 | 18 | 19 | | 20 | 21 | 22 | 23 | 24 | 25 | 26 | | 27 | 28 | 29 | 30 | 1 | 2 | 3 | | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Search
Navigation
Categories
Blogroll
|

Thursday, September 17, 2009
Moving TFS Historic builds to a new location
If you have a bunch of TFS builds that get a new home, it is always nice to let TFS know those files have been moved. But sadly, in the documentation there’s not much to find about this, nor is there any UI interface that lets you make this kind of change.
So I asked a question on the build forums, and Hongye Sun of Microsoft told me the best way to go at this, is use the Team Build APIs.
I’ve created a simple MoveBuild command line tool that allows you to move all the known builds from an old drop location to a new one, across all TFS projects.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
namespace MoveBuild
{
class Program
{
static void Main(string[] args)
{
if (args.Length < 3)
{
ShowUsage();
return;
}
try
{
string tfsServer = args[0];
string sourceDir = args[1];
string targetDir = args[2];
bool commit = args.Length == 4 && String.Equals(args[3], "/Commit", StringComparison.InvariantCultureIgnoreCase);
TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(tfsServer);
ICommonStructureService css = (ICommonStructureService)tfs.GetService(typeof(ICommonStructureService));
foreach (ProjectInfo item in css.ListAllProjects())
{
MoveBuilds(tfs, item.Name, sourceDir, targetDir, commit);
}
}
catch (Exception ex)
{
if (!Debugger.IsAttached)
Console.WriteLine(ex.ToString());
else
throw;
}
}
private static void MoveBuilds(TeamFoundationServer server, string teamProject, string sourceDir, string targetDir, bool commit)
{
int recordCount = 0;
IBuildServer buildServer = (IBuildServer)server.GetService(typeof(IBuildServer));
foreach (IBuildDetail item in buildServer.QueryBuilds(teamProject))
{
bool isMatch = item.DropLocation.StartsWith(sourceDir, StringComparison.InvariantCultureIgnoreCase);
if (!isMatch)
continue;
recordCount++;
//Console.ForegroundColor = isMatch ? ConsoleColor.Green: ConsoleColor.Red;
//if (!isMatch)
// Console.Write("SKIPPED: ");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(item.BuildNumber);
Console.ForegroundColor = ConsoleColor.Gray;
StringBuilder newDropLocation = new StringBuilder();
newDropLocation.Append(targetDir);
if (item.DropLocation.Length > sourceDir.Length)
newDropLocation.Append(item.DropLocation.Substring(sourceDir.Length));
StringBuilder newLogLocation = new StringBuilder();
newLogLocation.Append(targetDir);
if (item.LogLocation.Length > sourceDir.Length)
newLogLocation.Append(item.LogLocation.Substring(sourceDir.Length));
Console.WriteLine("Old location: {0}", item.DropLocation);
Console.WriteLine("New Location: {0}", newDropLocation);
Console.WriteLine("Old log location: {0}", item.LogLocation);
Console.WriteLine("New log location: {0}", newLogLocation);
if (commit)
{
item.LogLocation = newLogLocation.ToString();
item.DropLocation = newDropLocation.ToString();
item.Save();
}
}
Console.ForegroundColor = ConsoleColor.Gray;
}
private static void ShowUsage()
{
Console.WriteLine("MoveBuild - Usage");
Console.WriteLine("MoveBuild <TFS URL> <SourceFolderPattern> <DestinationFolder> [/Commit]");
Console.WriteLine();
Console.WriteLine(@"Example: MoveBuild http://mytfsserver:port \\OldServer\OldShare \\NewServer\NewShare");
Console.WriteLine(@"This will move all builds which have a drop location starting with \\OldServer\OldShare to \\NewServer\NewShare");
Console.WriteLine();
Console.WriteLine("If you specify /Commit the changes will be made to the database, if not, you only see a list of builds that would have been changed by this program");
}
}
}
To get this to build you need to:
- Add a refference to the following Microsoft.TeamFoundation libraries (which are in %ProgramFiles%\Microsoft Visual Studio 9.0\Common\IDE\PrivateAssemblies
- Microsoft.TeamFoundation.dll
- Microsoft.TeamFoundation.Build.dll
- Microsoft.TeamFoundation.Build.Common.dll
- Microsoft.TeamFoundation.Build.Client.dll
- Microsoft.TeamFoundation.Client.dll
- Microsoft.TeamFoundation.Common.dll
- Set your project’s properties to build for platform x86 if you’re developing on a x64 platform, otherwise you get a BadImageFormatException when loading these references.
Thursday, September 17, 2009 4:44:49 PM (Pacific SA Standard Time, UTC-04:00)
Some cool hidden feature in IIS7
If you need to configure a site to only allow SSL connections, that’s easy. But if you want to redirect URLs to the SSL url when they are entering with a normal URL typed in the browser, or linked to, that’s not an option you’ll find in the management tools… or is it?
As posted here: http://tech.mikeal.com/blog1.php?blog=1&title=ssl-redirects-in-iis7-using-403-4-error--302&disp=single&more=1&c=1&tb=1&pb=1 it is possible to redirect those requests to a specific URL, using the “error pages” feature. The status code to redirect is “403.4” and the rest is easy.
Thursday, September 17, 2009 1:28:30 PM (Pacific SA Standard Time, UTC-04:00)

Sunday, August 09, 2009
New MoBo installed
Because some things went wrong here in the household, like TL tubes blowing out and other electrical problems, I didn’t have much time to do some real work on my PC. But, this weekend that was different, because now everything is working like usual again. I replaced 3 TL lamps in it’s entirely (not just the tube), and the electrical problems are solved.
So, it was time to get to work on my nice PC. I have a quad core AMD Black Edition 3 Ghz processor, 8 GB memory, a 1000W PSU and 2 nice video cards (ATI Radeon HD 4870), but I could only install one of these cards because the SATA cables were in the way. The ECS board therefore didn’t fulfill my requirements and needed to be replaced. Since this is all still an AM2 Chipset, I needed to be quick. AM3 comes out and before you know it, you can’t get it anywhere anymore.
So here we are: One DFI LanParty board
As you can see on the picture, this board has the advantage that the SATA cables can be plugged into the side, so that does not conflict with large video cards, like this one:
Now you may ask: why 2 of these beasts? I got 3 big 26” HD monitors here on my desk. (Each having a resolution of 1920 * 1200) This alone is very cool to work with.
Putting it all together
The task was a hefty one. Each video card needed 2 PCI-E Power connectors attached, so those were 4 cables. Then came the motherboard, with the standard power connector (the big one), and 3 aux connectors. (2 via the good’ol FDD connectors.) The audio connector for the front part is a bit in a strange place, that’s between the 2 PCE-slots where the gap is. Now came a nasty one, I had to get the proc out of the motherboard. Once I carefully lifted up the heat sink, which didn’t go really easy, I noticed the processor was attached to it. That stuff of AMD that they use on their heat sinks is way to adhesive! I got the processor loose using the hairdryer trick. You warm up the heatsink with a hairdryer, once this is warm you can slowly but surely move the processor off.
The rest was all simple, and once the box was closed, it was time to put it back in place.
Let’s run again
This was the first time I used the 2 video cards together, and I must say: "I’m impressed, big time!” Video performance is funtastic, the motherboard does also a very good job. Since this is an overclocker’s board, the BIOS is not something for the faint hearted. Do your homework or don’t fiddle with it too much.
All together this is now a rig that will almost do anything you throw at it. The only thing I’m missing is water cooling
If you want to build something like this, make sure you get a good PSU. For 2 of these video cards, a 1000W Modular PSU is highly recommended.
Sunday, August 09, 2009 10:00:10 PM (Pacific SA Standard Time, UTC-04:00)

Monday, August 03, 2009
How to get a SHA1 hash from a file in C#.Net
A simple way to get a hash code from a file:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace Sha1
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("Usage: SHA1 <filename>");
return;
}
string fileName = args[0];
if (!File.Exists(fileName))
{
Console.WriteLine("File not found: {0}", fileName);
return;
}
using (Stream s = File.OpenRead(fileName))
{
SHA1Managed sha = new SHA1Managed();
byte[] result = sha.ComputeHash(s);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
sb.AppendFormat("{0:x2}", result[i]);
}
Console.WriteLine("SHA1 Hash: {0}", sb);
}
}
}
}
Monday, August 03, 2009 9:22:14 AM (Pacific SA Standard Time, UTC-04:00)

Monday, July 27, 2009
A very simple GZip command line tool
During some testing, I needed a tool that could simply compress a file to GZip format and back again. I decided that other people might have a similar need, so here’s the code to make it work.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Compression;
using System.IO;
namespace GZip
{
class Program
{
static void Main(string[] args)
{
CompressionMode mode = CompressionMode.Compress;
if (args.Length != 3)
{
ShowUsage();
return;
}
string command = args[0].ToLower();
switch (command)
{
case "compress":
mode = CompressionMode.Compress;
break;
case "decompress":
mode = CompressionMode.Decompress;
break;
default:
ShowUsage();
return;
}
Stream sourceStream = File.OpenRead(args[1]);
Stream targetStream = File.OpenWrite(args[2]);
switch (mode)
{
case CompressionMode.Compress:
using (GZipStream gZip = new GZipStream(targetStream, CompressionMode.Compress))
{
Pump(sourceStream, gZip);
}
break;
case CompressionMode.Decompress:
using (GZipStream gZip = new GZipStream(sourceStream, CompressionMode.Decompress))
{
Pump(gZip, targetStream);
}
break;
}
sourceStream.Close();
targetStream.Close();
}
private static void Pump(Stream source, Stream target)
{
byte[] buffer = new byte[65536];
int count;
while ((count = source.Read(buffer, 0, buffer.Length)) > 0)
{
target.Write(buffer, 0, count);
}
}
private static void ShowUsage()
{
Console.WriteLine("Usage: GZip compress | decompress sourceFileName targetFileName");
}
}
}
Monday, July 27, 2009 3:02:34 PM (Pacific SA Standard Time, UTC-04:00)
Programming
World’s smallest web server
It’s always fun to play with .Net, the HTTP Listener class in .Net 2.0 makes it really easy. With this little block of code you can setup a very simple (multithreaded) web server…
private static System.Threading.AutoResetEvent listenForNextRequest = new System.Threading.AutoResetEvent(false);
protected Server()
{
_httpListener = new HttpListener();
}
private HttpListener _httpListener;
public string Prefix { get; set; }
public void Start()
{
if (String.IsNullOrEmpty(Prefix))
throw new InvalidOperationException("No prefix has been specified");
_httpListener.Prefixes.Clear();
_httpListener.Prefixes.Add(Prefix);
_httpListener.Start();
System.Threading.ThreadPool.QueueUserWorkItem(Listen);
}
internal void Stop()
{
_httpListener.Stop();
IsRunning = false;
}
public bool IsRunning { get; private set; }
private void ListenerCallback(IAsyncResult result)
{
HttpListener listener = result.AsyncState as HttpListener;
HttpListenerContext context = null;
if (listener == null)
// Nevermind
return;
try
{
context = listener.EndGetContext(result);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
return;
}
finally
{
listenForNextRequest.Set();
}
if (context == null)
return;
ProcessRequest(context);
}
// Loop here to begin processing of new requests.
private void Listen(object state)
{
while (_httpListener.IsListening)
{
_httpListener.BeginGetContext(new AsyncCallback(ListenerCallback), _httpListener);
listenForNextRequest.WaitOne();
}
}
protected abstract void ProcessRequest(HttpListenerContext context);
Always nice to have ;)
Monday, July 27, 2009 1:21:45 PM (Pacific SA Standard Time, UTC-04:00)
Programming

Wednesday, July 22, 2009
Windows 7 & Windows Server 2008 R2 RTM
Today is the day, Windows 7 and it’s big brother (Server 2008 R2) has both been released to manufacturing. (Which means: Let’s copy a few million DVDs)
See the following links for more info:
My congrats to the Windows team, they really did an outstanding job!
Hurray :)
Wednesday, July 22, 2009 5:46:59 PM (Pacific SA Standard Time, UTC-04:00)
That’s a ‘stinky’ newsletter ;)
When I read this I really had a good laugh…
Code Deodorants for Code Smells
Code Smells have become an established way of talking about indications that things may be wrong with your code. Nick Harrison extends the idea with the concept of 'code deodorants' and shows how the code smell of 'inappropriate intimacy' can be cured by means of the code deodorant, called 'separation by interface'.
- Snif – No, I don’t smell anything here… Or as my lovely would wife put it:
“That newsletter stinks” :o)
LOL :)
Wednesday, July 22, 2009 1:39:27 AM (Pacific SA Standard Time, UTC-04:00)

Monday, July 20, 2009

Monday, July 13, 2009
Windows 7 – RTMed or not RTMed? That’s the question
It’s that time again. Is the 7600 Build the official RTM build, or isn’t it? We won’t be able to tell until Microsoft will officially declare the build: “RTM.”
When Vista was released, there were several “6000” builds before the official one was released, starting with 16384 (the 16*1024 number) and moving up to 17015 all which were “claimed” RTM, but none of them were.
A Microsoft spokesman denied today that Windows 7 has gone RTM. Is this because of the fact that there will be an announcement tomorrow at the Worldwide Partner Conference by Steve Ballmer, or is it simply the truth, maybe they need their time to test the build.
Think of it, testing software takes time. The build number 090710-1945 indicates this build is 3 days old, with a weekend in the middle… How can they test it this fast? It takes almost a full day to build the beast! (Build numbers are assigned before the build starts) A whole lot of tests are automated and are taking place during or after the build of software, but still I think there will be a lot of things that needs to be done by hand.
To add to the confusion, several screenshots have been seen on websites, some stating the obvious (the 7600 number in WinVer) and some stating the full build string. Some news reporters say “Yes, it is RTM”, some say “It’s too early to know for sure”, it’s all pure speculation.
So if you ask me, if 7600 might be the final build number, sure it could be. Is it 16384? It would be nice, but I don’t think so. I think it is the first build in a series of test builds, just as we saw when Vista was created.
I am surprised to see how quickly this build made it onto the torrent sites. This must really be a matter of hours between build completion and online availability. That’s kind of stunning, and I think Microsoft has a big problem on her hands when software makes it out of the build lab so quickly.
It would be nice if I am wrong, in that case you can be sure tomorrow morning because if 16384 is really the RTM version, I’m betting that Steve Ballmer will announce RTM during his keynote speech.
And for those of you who want to know if I’m downloading Windows 7? No I’m not. I’ll grab the build of MSDN as soon as it is there.
UPDATE: It seems that I was right. There’s already a newer build in the wild, that’s number 16385. Friday July 24th there is an announcement expected, so it’s “wait and see”
UPDATE 2: The RTM Prediction Advisory of Long Zeng is here: http://islongwrongaboutwindows7rtm.com/
Monday, July 13, 2009 7:11:05 PM (Pacific SA Standard Time, UTC-04:00)

Saturday, July 11, 2009

Monday, June 29, 2009
Power failure and no Internet
Sometimes the <censored> hits the fan, and guess what happens? The whole city was blacked-out. For about an hour we sat in the dark, without any electricity. But the real fun began when the power came back…
I got my server and VMs back up and running but no Internet. Try to call my ISP (TelSur) and once I selected “Apollo technico para Internet” (Internet Helpdesk) nobody answer. So I called a friend of mine, Guido, who told me he has the same issue.
I guess they have their hands full. It would be nice if they inform the people that call with a simple message like: “There’s a service disruption in Valdivia…”
Of course, now you read this message, Internet is back up again, else I couldn’t post it on my blog :)
Monday, June 29, 2009 12:23:38 AM (Pacific SA Standard Time, UTC-04:00)

Friday, June 26, 2009
Using DNS as an authentication mechanism
Sometimes you need a construct for verifying a domain name ownership before you allow specific actions to be done to that domain. An example could be to send a bunch of mail to a specific domain. This will never be considered spam when you’re the owner of that domain, but it will be considered spam if that isn’t the case.
To validate domain ownership, you can check WhoIs records, ask for some proof of ownership, etc. But all these methods require human intervention. IRIS (Internet Registry Information System) isn’t done yet and won’t be globally available for the next few years, and we all probably have seen once the output of a WhoIs server. Try to parse that with a generic RegEx, no way in hell. So how do you automatically check if someone is really an owner of a domain?
Let’s just assume an owner has the power to change DNS records, anyone else hasn’t. SPF works that way, and I don’t think any sysadmin is going to give up those passwords easily. (It could compromise a lot!) So how about if you simply put a TXT record in DNS which has some custom format, like: “myapp:accountIdOfTheCustomer”. Guess what? This can be checked with a simple DNS query :)
The customer must logon to “myapp” and once it has done so, domain names can be checked against the account ID of that customer, so once you’ve got that in place, there’s no need to do any handwork. Requirement here is that the customer is in charge of their own DNS, but that should be the case most of the time. Since the customer doesn’t want to give anyone else access, they won’t put anyone else’s account number there… And you can put some salt in there if it’s needed…
Friday, June 26, 2009 7:18:24 PM (Pacific SA Standard Time, UTC-04:00)
Problems with EFS and developing software
EFS (Encrypting File System) is a great Microsoft solution to keep a secret a real secret, and to safeguard source files from (accidental) leaking when for example a notebook is stolen. The problem with writing software is that during testing, most of the stuff you create need to be accessed by processes that do not have access to your EFS key. Let me clarify…
Let’s say you are building a web site which you host in IIS. IIS runs in is own account and does not have access to your EFS key. You build your project, this creates a bin folder and a few DLLs within that folder. But guess what? The BIN folder is encrypted, and so are the DLL outputs. When running with a service in your local account, that’s not a problem. But when IIS tries to access those files, it will get a access denied exception because it can’t decrypt the DLL file. (Or any ASPX files for that matter.) This generally means that encrypting content files which need to be accessed by other services (running in their own process with their own account) is a bad idea. EFS will block access to these services. It becomes even more fun when COM+ DLLs are in play, etc.
The only solution is to do full hard drive encryption using BitLocker, it is not possible to do this any other way. Sure you can try to configure every account with keys, etc, or try to prevent the output binaries from being encrypted, but all this will become rather a management nightmare at the end. The reason that full hard drive encryption works, is that the main difference is that every account that is active on your system will have access to the files, in stead of your own account as the only account.
Friday, June 26, 2009 7:08:23 PM (Pacific SA Standard Time, UTC-04:00)
The Windows 7 madness has begun
Windows 7 is now available for pre-order…
I’ve been running Windows 7 RC for a while and I must say, it’s the best version of Windows I’ve seen, and I’ve seen them all. (All the way from 1.0)
If you’re living in one of the countries that the upgrade offer is valid for, you should consider getting your copy. If you haven’t switched to Vista yet, you might as well get Vista and a free upgrade to Windows 7 will be available once it is released. For the European community: Wait for the “E” edition, and sorry, no upgrade from Vista to Windows 7 E, only “Wipe & Load” migration is available. You may thank the European Union for that.
Partners will get Windows 7 at the end of July (at RTM date), and this means that I’ll be running Windows 7 RTM probably within a month… and since I’m in Chile, I don’t need the “E” version… You may get jealous now
What I like about Windows 7?
- Windows Virtual PC with XP Mode,
- Seamless integration of apps within Virtual PC
- Windows Virtual PC using hardware virtualization
- OK, besides Virtual PC:
- Document libraries (which is a huge benefit for me)
- The new superbar
- And a lot more…
At the moment I have Windows 2008 on my workstation because I use Hyper-V as a virtualization platform and I have some features in IIS which aren’t available in Windows Vista. (Like the BITS server extensions.)
Windows Server 2008 R2 will also be released within the same timeframe. There’s a lot of improvements in this version of Windows Server, actually so much I’m surprised they simply call it an R2 version. What I like most is .Net for Server Core, which allows .Net to be run on a Core installation and allows you to create Windows Services or ASP.Net websites which now can run on Core.
Friday, June 26, 2009 10:14:16 AM (Pacific SA Standard Time, UTC-04:00)