Tijmen 09:53, 15 October 2009

One of my machines refused to install updates to the .NET Framework 3.5 sp1, both through auto-update and when installing manually. I finally fixed it by using Aaron Stebner's .NET framework cleanup tool and re-installing .NET. This tool radically removes all versions of the .NET framework, including IIS artefacts, registry entries, the works. I found this tool through a post on raymond.cc.

Note that this tool should probably not be the first thing to try; uninstalling and re-installing the .NET framework versions would probably a safer bet to try first.

Tijmen 07:36, 1 October 2009
Just a quick note: there is an update out for the latest .NET framework version, that addresses issues with ASP.NET dynamic data. Amongst others, the site will not display foreign key fields in a one-to-one relationship. This KB article contains all the download links to the various versions.
Not a new issue by any means (the fix is dated January 2009), but good to know nonetheless.

Tijmen 11:00, 16 September 2009

Nothing much to, just that it took me some time to figure it out today. The code below tests whether DivisionID is actually set in the presenter.

 

public class Presenter
{
    readonly IRepository repository;

    public Presenter(IRepository repository)
    {
        this.repository = repository;
    }

    public IView View { get; set; }



    public void GetDivision()
    {
        View.DivisionID = repository.GetDivisionID();
    }
}

public interface IView
{
    int DivisionID { get; set; }
}

[TestFixture]
public class PresenterTests
{
    Presenter sut;
    IView view;
    IRepository repository;

    [SetUp]
    public void SetUp()
    {
        view = MockRepository.GenerateMock<IView>();
        repository = MockRepository.GenerateMock<IRepository>();
        sut = new Presenter(repository){View = view};
    }

    [Test]
    public void when_on_the_sut_GetDivisionID_is_called_it_should_set_the_divisionID_on_the_view()
    {
        //AAA mocking style
        
        //Arrange
        const int divisionID = 1;
        repository.Stub(s => s.GetDivisionID()).Return(divisionID);
        
        //note: the expectation is set when DivisionID is set to divisionID
        view.Expect(s => s.DivisionID = divisionID);
        
        //Act
        sut.GetDivision();
        
        //Assert
        view.VerifyAllExpectations();    
    }
}
Tijmen 11:16, 12 September 2009

As I will write the translations of the code snippets from the excellent Working Effectively With Legacy Code (WEWLC) book by Michael Feathers I will also assume the following:

  • There is some sort of understanding what mocks are
  • There is some understanding of how Rhino mocks work (if not, you will find out anyway by continue reading this blog)
  • There is some understanding of Dependency injection
  • One knows what TestDriven.net is.
  • One knows why AutoHotKey is used and what you can do with it
  • Some understanding of Reshaper
Tijmen 01:06, 4 September 2009

launch_or_activateOne feature of the new Windows 7 SuperBar that I particularly like is the ability to pin applications. This creates a single button that can be used to both launch the application (when it isn't already running) or to activate it if the app was already active. What I like about this concept, is that it expresses the user's wish much better in this way: a button to run Word can now be used to just "give me Word, I don't care if it's already running".

Since I usually work more keyboard- than mouse-centric, I came up with a way to mimic this behavior in AutoHotkey. I wrote a script that offers the following functionality:

  • either start or activate a particular application (based on a shortcut key obviously, this being an AutoHotkey post)
  • if the application is already running, cycle through the active windows (useful for Firefox or Explorer windows)
  • make it easy to "force-launch": force a new instance/window, regardless of whether it was already up and running.
  • give visual feedback on the launched-or-activated application

It took me a little time to work out the AutoHotkey script syntax, especially for dealing with arrays. In the script you set up an array of shortcut information, which serves as a settings registry. It contains the following parts:

  • display label: text that is shown in the visual feedback
  • a (unique) name: this is used to bind that particular command to a hotkey
  • a groupname: if a groupname is given, the script tries to loop through all the windows that match the window ID that is assigned to this entry
  • windowId: set this to the "ahk_class" of the window. You can use Window Spy (right click on any running AutoHotKey script tray icon) to find out this value for each command you want to add to the registry. It will probably work with Windows titles as well, but I never tried this since that method is a lot less reliable.
  • runcommand: the actual command you want the shortcut to point to if it needs to launch the application (for instance, "c:\windows\system32\calc.exe")

Adding a entry goes like this:

;--1. SETUP
;     enter label, name, groupname, windowId, runcommand
AddShortcut("Windows Explorer", "Explorer", "ExplorerGroup", "ahk_class CabinetWClass", "C:\windows\explorer.exe /select,d:" )

The next step involves hooking up the shortcut keys. This is standard AutoHotkey suff, so please refer to the AHK manual for doing this. An example for Explorer and Firefox:

#E::MyNewActivate("Explorer")
+#E::MyRun("Explorer")
F19::MyNewActivate("FF")
+F19::MyRun("FF")

So, Windows key + E does the launch-or-activate trick, whereas Shift + Win + E forces a new Explorer window.

The rest of the script adds some visual eye candy that is in no way functionally necessary, but it gives a nice, semi-transparent window that fades quickly. The three possible windows are shown at the top of this post.

The entire script is listed below; click expand source to view or copy.

#InstallKeybdHook

;--AUTOEXEC SECTION

GroupArrayCount := 0
SetTitleMatchMode 2

;--DISPLAY SETTINGS
;
INITIAL_TRANSPARENCY := 150
DELTA_TRANSPARENCY := 25
INITIAL_DELAY := 400
DELTA_DELAY := 50

;--1. SETUP
;     enter label, name, groupname, windowId, runcommand
;
AddShortcut("Windows Explorer", "Explorer",   "ExplorerGroup", "ahk_class CabinetWClass", "C:\windows\explorer.exe /select,d:" )
AddShortcut("Outlook", "Outlook", "OutlookGroup", "ahk_class rctrl_renwnd32", "C:\Program Files (x86)\Microsoft Office\Office12\outlook.exe")
AddShortcut("Firefox", "FF", "FireFoxGroup", "ahk_class MozillaUIWindowClass", "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" )
AddShortcut("Calculator", "Calculator", "", "ahk_class CalcFrame", "c:\windows\system32\calc.exe")

;--2. ASSIGN KEYS
; win + E does a "run or activate", shift + win + E forces a new window
#E::MyNewActivate("Explorer")
+#E::MyRun("Explorer")

F14::MyNewActivate("Outlook")
F19::MyNewActivate("FF")
+F19::MyRun("FF")

;--Ctrl + Shift + Esc starts Process Explorer (task manager on steroids)
+^Escape::MyNewActivate("PE")
#C::MyNewActivate("Calculator")
;
;--/AUTOEXEC SECTION


; FUNCTION SECTION
GlobalTrans := INITIAL_TRANSPARENCY

;--CloseWin has to be an AHK subroutine, SetTimer doesn't work with functions
;  also note: subroutines do not require the "global" keyword
;             to manipulate global vars
CloseWin:
  If (GlobalTrans <= 0)
  {
    Gui, Destroy  
  }
  else
  {
    WinSet Transparent, %GlobalTrans%, ahk_class AutoHotkeyGUI
    GlobalTrans := GlobalTrans - DELTA_TRANSPARENCY
    ; negative time means run only once
    SetTimer, CloseWin, -%DELTA_DELAY%
  }
return


ShowText(text, textColor)
{
  global
  GlobalTrans := INITIAL_TRANSPARENCY

  Gui, Destroy
  SetTimer, CloseWin, Off
  Gui +LastFound +AlwaysOnTop -Caption +ToolWindow
  Gui, Color, 404040
  Gui, Font, s32
  Gui, Add, Text, c%textColor%, %text%
  SetTimer, CloseWin, -%INITIAL_DELAY%
  Gui, Show, Center NoActivate
  WinSet Transparent, %GlobalTrans%, ahk_class AutoHotkeyGUI
}

AddShortcut(label, key, groupName, windowId, runCommand)
{
  global
  GroupArrayCount += 1
  Labels%GroupArrayCount% := label
  Keys%GroupArrayCount% := key
  if (groupName != "")
  {
    Groups%GroupArrayCount% := groupName
  }
  Ids%GroupArrayCount% := windowId
  Commands%GroupArrayCount% := runCommand
  if (groupName != "")
  {
    GroupAdd %groupName%,%windowId%
  }
}

MyNewActivate(key)
{
  global
  Loop %GroupArrayCount%
  {
    if (key == Keys%A_Index%)
    {
      local thisId := Ids%A_Index%
      local label := Labels%A_Index%
      if WinExist(thisId)
      {
        ShowText("switching to " . label, "Lime")
        local thisGroup := Groups%A_Index%
        if (thisGroup == "")
        {
          WinActivate %thisId%
        }
        else
        {
          GroupActivate %thisGroup%,r
        }
      }
      else
      {
        ShowText("launching " . label, "FF8800")
        local thisCommand := Commands%A_Index%
        run, %thisCommand%
      }
      break ; terminate the lookup
    }
  }
}

MyRun(key)
{
  global
  Loop %GroupArrayCount%
  {
    if (key == Keys%A_Index%)
    {
      local label := Labels%A_Index%
      ShowText("force new " . label, "FF3300")
      local thisCommand := Commands%A_Index%
      run, %thisCommand%
      break ; terminate the lookup
    }
  }
}

Note that line 46 should read If (GlobalTrans <= 0), but the AHK brush for SyntaxHighlighter gets a bit confused here (since the semicolon ";" is also the AHK comment character). I found this brush here.

Tijmen 10:57, 2 September 2009

Every now and then I want to do a simple authentication scheme in an ASP.NET web application, without calling on various providers or other components that bring too much weight & functionality to the table. Implementing a custom IIdentity and IPrincipal is a straightforward way of achieving this.

The steps involved:

  • create a custom implementation of these two interfaces
  • set the custom principal as the user for HttpContext.Current
  • cache the principal in session state (not actually required, but a simple optimization)

Implementing the interfaces

A simple skeleton for the IIdentity implementation:

public class MyIdentity : IIdentity
{
    private string passedInName; 

    // IIdentity
    public string AuthenticationType { get { return "MyIdentityAuthenticationType"; } }
    public string Name { get { return passedInName; } }

    public bool IsAuthenticated
    {
        get
        {
            // TODO: add whatever logic we need here (for instance, AD group membership)
            throw new NotImplementedException();
        }
    }
    // /IIdentity

    // Hide constructor
    private MyIdentity() { }

    // Static factory method
    internal static IIdentity CreateIdentity(IUserNameProvider provider)
    {
        IIdentity identity = new MyIdentity { passedInName = provider.AccountName } ;
        return identity;
    }
}

And for the IPrincipal-implementing class:

public class MyPrincipal : IPrincipal
{
    private IIdentity identity;

    // IPrincipal
    public IIdentity Identity    { get { return identity; } }
    public bool IsInRole(string role)
    {
        // TODO add logic here
        throw new NotImplementedException();
    }

    // hide Ctor
    private MyPrincipal() { }

    // static factory method
    public static IPrincipal CreatePrincipal(IUserNameProvider provider)
    {
        IIdentity identity = MyIdentity.CreateIdentity(provider);
        IPrincipal principal = new MyPrincipal { identity = identity };
        return principal;
    }
}

A few things to note:

  • IUserNameProvider has only a single string property, name. The injected type is used to determine the current user's name.
  • I used simple static factory methods, that are by no means necessary in this context (regular constructors would work just as well).
  • you could factor out the two "business logic" methods IsAuthenticated and IsInRole to separate concerns using the template method pattern, but this is supposed to be a simple, lean implementation.

Hooking them up

The easiest way I've found to link the custom principal is by implementing the Application_AcquireRequestState event in the global.asax:

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
    IPrincipal principal = null;

    var current = HttpContext.Current;

    // check if session is available; needed because this event can/does fire multiple times per request
    if (current.Session != null)
    {
        // check if we have the principal in session
        if (current.Session["magicstring"] != null)
        {
            principal = current.Session["magicstring"] as IPrincipal;
        }
        // catches both (1) key not in session and (2) cast not succesfull
        if (principal == null)
        {
            // create a new one and store it in the session
            principal = MyPrincipal.CreatePrincipal(new MyWebAccountNameProvider());
            current.Session["magicstring"] = principal;
        }

        // regardless of source (session or freshly created, store in appropriate context)
        current.User = principal;
    }
}

Actually, this event is a bit weird, because it can fire multiple times for a single request. The Session reference is only valid once however, which is why that check is there. So, what happens:

  1. The existence of a session variable is checked, and, if it exists, it is cast to an IPrincipal.
  2. If either the cast failed or the session var was empty, a new specific principal is constructed and stored in session.
  3. The custom principal is linked to the HttpContext.Current.User property, allowing us to use it in the rest of the application.

Wrapup and comments

This is by no means a do-all, end-all solution, but it works well. Depending on the tiering/layering of the solution, you can either check the HttpContext.Current.User property, or you can abstract that into a simple wrapper. I usually either use a static method on my principal that returns the actual active principal, or set up a context registry to hold my principal reference transparently across layers.

Tijmen 02:22, 28 August 2009

I've been working a lot with stored procedures and the Linq to Sql designer. One of the annoyances is that all of a sudden when you drop the nth sproc to the designer it would not allow creating the codebehind anymore. It'll then throw the most usefull message:

"The operation could not be completed"

There's an easy fix however, open a Visual Studio command prompt and hit

"devenv /resetskippkg"

 

Works like a charm.

Tijmen 08:50, 17 August 2009
I am sure I ran into this before, but it took me some time to figure out yet again. Something like that always shouts "blog it" to me, so here goes. I installed a ClickOnce application, that neatly installed itself and placed an appropriate shortcut in my start menu. I then fired up Launchy, rebuilt the catalog and started looking for the new app... which didn't show up.
Searching through the start menu using standard Windows functionality of win-key + start typing (which admittedly got a lot better and snappier in Windows 7, though nowhere near powerful enough for us pro-keystrokers) resulted in the correct shortcut, though.
Long story short: the ClickOnce shortcuts have an extension *.appref-ms. By adding that file type to the various directories that Launchy indexes (right click, options, catalog tab) and rebuilding the catalog, the shortcuts show up in Launchy as well. By the way, on my Windows 7 machine, the start menu shortcuts are in the following folders (I am not sure if Launchy sets those correctly from the start):
  • c:\ProgramData\Microsoft\Windows\Start Menu
  • c:\users\<username>\AppData\Roaming\Microsoft\Windows\Start Menu
Tijmen 03:10, 8 August 2009

At my current project we needed a quick sort of throw away app that was going to be used by a small group of people. Without going into much details the app basically is a planning and analysis module for the allocation of employees to divisions.

Since development speed is crucial we decided to work with Linq2sql and winforms. No need for all sorts of layers; just get it done.

 

We needed to fill a combobox with values. This should be trivial, but was a bit more trouble than expected. I ended up using the excellent description found here. Basically all you need to do is:

var comboBox = new ComboBox();
var choices = new Dictionary<string, string>();
choices["A"] = "Arthur";
choices["F"] = "Ford";
choices["T"] = "Trillian";
choices["Z"] = "Zaphod";
comboBox.DataSource = new BindingSource(choices, null);
comboBox.DisplayMember = "Value";
comboBox.ValueMember = "Key"; 

 

Notice the clever use of new BindingSource(choices, null);

 

Nothing complex here, but this is static and I wanted to get the values from the db. Next to that it would be nice if we could have some sort of generic function that could take a type of TEntity (table) and some hints to which properties in TEntity it needed as Key and Value.

I ended up with this:

public interface IComboBoxHelper
{
    void SetComboBoxContent<TEntity, TKey, TValue>(
            Func<TEntity, TKey> key,
            Func<TEntity, TValue> value, 
            ComboBox comboBox)
        where TEntity : class;
}

Usage becomes pretty straightforward: register the IComboBoxHelper and it's implementation to the Dependency injection container. Add a constructor dependency and use the helper variable:

comboBoxHelper.SetComboBoxContent<Divisie, int, string>(s=> s.Divisie_PK, s=> s.Divisienaam, comboBox);

The implementation of the IComboBoxHelper takes a datacontext and is responsible for looking up the required entity.

Let's have a look at the actual implementation:

public class ComboBoxHelper : IComboBoxHelper
{
    readonly HRDataContext dataContext;

    public ComboBoxHelper(HRDataContext dataContext)
    {
        this.dataContext = dataContext;
    }
   
    public void SetComboBoxContent<TEntity, TKey, TValue>(
            Func<TEntity, TKey> key,
            Func<TEntity, TValue> value, 
            ComboBox comboBox)
        where TEntity : class
    {
        Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();

        IQueryable<TEntity> entities = dataContext.GetTable<TEntity>().Select(s => s);
        entities.ForEach(s => dictionary.Add(key(s), value(s)));
        var source = new BindingSource(dictionary, null);
        comboBox.DataSource = source;
        comboBox.DisplayMember = "Value";
        comboBox.ValueMember = "Key";
    }
}

Nothing too complicated, but the use of Func's to get to the properties in the required Entity is pretty nice.

Technorati Tags: ,,
Tijmen 12:53, 4 July 2009

When I joined Avanade half a year ago they provided me with a very good laptop. It's a Dell 830 with a brilliant 1920x1200 resolution. At first I thought it was a bit small but nowadays I hardly ever use my Dell 24" monitor except for the occasional Hollywood download.

The processor is reasonable fast, it has 4GB of internal memory and they even put the decent IBM 7200rpm hdd in it.

 

For some reason however my machines always feel sluggish after a couple of months. Rather that going for a new install again I decided to take the plunge and get myself the Intel X25 SSD.

Intel x25

 

Ordering was easy and after two days it arrived at work in the afternoon. Obviously my teams productivity dropped to 0 as we had to install the drive first and test how fast it would be.

Initial speed experience was a bit of a disappointment. Copying Windows 7 from DVD took about 8 minutes. Now I know this is due to the limiting speed of the DVD but still.  :)

Installing Windows 7 took about 15 minutes, booting as promised only 25 seconds. Installing Visual Studio 2008 was kind of a surprise. I first copied everything on the hdd, then ran the installer. Took about 4 minutes to complete! SP1 which used to take over 40 minutes now only took about 6. Quite an improvement I must say.


Most important however is day to day speed. Firing up VS2008 is fast, it's still not instantly however. Loading projects is 2-3 times faster, but there still are loading times (also because of Resharper I guess).

 

One of the best improvements however is that the irritation on the noise of the hdd has completely disappeared. The only thing that's audible is the soft spinning of the fan. This means more focus to what I'm doing as opposed to what my machine should be doing. You don't care about the hdd anymore as you can't hear it's activity and the little hdd icon is hardly noticeable.

Building solutions, adding references, working with the file system in general; I never get distracted by a waiting time for some stupid IO anymore and development feels just that much snappier.

 

All in all, bit disappointed in the fact that loading still takes a bit time but very satisfied in the overall user experience my laptop now provides.

 

Technorati Tags: ,,
Tijmen 11:58, 4 July 2009

Jeremy Miller is the author of StructureMap. The first DI container I was exposed to. Nowadays I have to use Unity but that's all fine as a DI container is just a vehicle not the purpose.

Anyways, in this presentation Jeremy talks about setting up your solution in a modularized way and how he did it with his Storyteller project (a fitnesse replacement for .Net). He speaks a bit about injecting view, using Presenters and of course the Event Aggregator.All this is very similar to the PRISM or Caliburn framework.

All was fairly interesting, but I think that without some context on these frameworks you'd be lost soon.

 

Now, I have been working on these concepts for a while now and I fully believe this is the way forward. If you are new to this I would recommend first to have a look at PRISM. There are some very good screencasts available on channel 9.

Next to that you probably also want to have a look at the MVVM geekspeak talk hosted a while ago (june 2009) at MSDN, and read a bit at MSDN.

 

Watch the screencast here

Tijmen 11:41, 4 July 2009

I never heard of Astoria before. I did hear about ADO.NET DataService, but as there's ADO in the name it had to be evil. Luckily Astoria is not about ADO.NET, it's about exposing data using JSON & REST.

 

Basically the idea is very simple. You create a website project, add a class that will act as your data source. This can be anything, be it Linq to Sql, Entity or NHibernate. You can even use a stub to temporarily make some data available. The only important thing to keep in mind is that it needs to implement IQueryable for select operations.

Then add a new item - ADO.NET Data Services item.

 

Data services

 

Go to the newly created cs file and implement the DataServices generic base class.

 

Implement interface


That's all there is to it. You can now reference the WCF Data Service and query it like you would query any IEnumerable<T>.

 

Very cool stuff.

 

Some links for Astoria:

Team blog Astoria
Learning Astoria
MSDN Reference
API Documentation
Help forum and info
Whitepaper on using Astoria

 

Watch the screencast here.

Tijmen 11:25, 4 July 2009

Robert Martin is the author of CleanCode. Great stuff in this presentation. I have read most of his books and this talk felt a bit like a reread.

Some of the notes I took while watching the video:

Write small methods, then write them smaller
In an if statement, call a function
In the predicate, call a function
Extract your logic into small methods and objects. Not only to separate concerns but also to document and name your code.
If you feel troubled coming up with a name for a method; it's probably doing too much (and it's probably also too big)
If there's much data sharing between methods in a class; you're probably better off extracting that logic into another class
Etc etc.

On our current project we have done something similar. First we started by naming our methods in a more expressive manner. We then applied cutting off large chunks of code into smaller methods. One obvious downside to this is that you end up with quite steeps objects graphs and lot's of small methods.

We found that as long as you name them properly and stop caring about the inner details some method deep down you'll be fine. But letting go the habit to examine every bit of code to understand what something is doing is quite a steep learning curve.

 

Watch the screencast here.

Tijmen 11:09, 4 July 2009

Rather than giving a presentation from PowerPoint, Ayende asks the audience what they would like to discuss and then starts rambling off.

He talk is 100% around NHibernate. I increased the playback speed in windows media player (available when you go to full screen). Even though there really wasn't that much coherent info it's still fun to observe someone speaking passionate about something they care for.

Watch the screencast here.

Tijmen 11:02, 4 July 2009

This week the NDC conference made available many of it's talks. In contrast to the typical .Net focussed conventions this one is more or less targeted at the alt.net population.  Uncle Bob is there, Micheal Feathers, Jeremy Miller, Scott Hanselman etc etc.

I have been watching some of the video's available and they are generally speaking very good. I'll post short reviews on them shortly. For an overview of the agenda and screencasts see here.

 

Tijmen 09:18, 16 June 2009

I intend to dedicate several (short) posts on the various tools I use to increase my productivity. At some point I will post a complete list of my must-have tools, but for now I want to focus on a new find (for me): the Everything search engine, by voidtools. Everything is a very silly name for a tool and its functionality is not ground-breaking: it searches for files on your local machine, based on their filename. This is obviously not rocket science, but it has a few distinctive characteristics. The first is performance: it indexes an average system in seconds. Literally. Searching is very snappy as well. Another big advantage is its low footprint. it uses up very little memory and disk space, and since its indexing process is very fast, there is no noticeable background disk churning like you get with default Windows search or other third party tools.

So, after this intro there are a few things worth mentioning: using Everything together with Launchy, and setting up Everything on a fileserver.

 

Everything on a (personal) fileserver

Everything can only index local disks. It does not index network shares or other remote locations (so NAS users are out of luck I suppose). However, you can run Everything as a service on a file server and have your local Everything client connect to this server. As an alternative, you could just run Everything on the desktop at the server, but that requires staying logged in all the time. In any case, you need to install Everything on the server and make it start an ETP server.

To install everything as a service, you need to follow these steps:

  1. Install Everything on the server
  2. Disable "run on system start". Go to the tools menu, click options. On the general tab, uncheck "Start everything on system start up", and click OK
  3. Open up a command prompt, CD into the folder where Everything was installed, and enter everything.exe -install_service
  4. This installs the server, but it does not set the command line option correctly: it only runs Everything as a service for the local computer (i.e., the server), but we want Everything to run as an ETP server. To do this, type the following at the command prompt: sc config everything binPath= "c:\program files (x86)\everything\everything.exe -svc -host" (replacing the path with your install path of choice, obviously).
  5. Stop and start the service (either through control panel or the geeky way, by issuing net stop everything (sounds kind of cool), followed by net start everything).

After this, configuration is done. Fire up Everything on another computer connected to the file server and use the option "Connect to ETP server" on the tools menu. I've had to use the IP number of my server since it did not do a name lookup, but I am not running any local DNS or hosts file, so YMMV.

Side note: Everything defaults to opening networked files on shares named after the local drive letters, so it opens the folder documents on the E-disk of the server as \\server\E\documents\. Not a huge problem, but something to be aware of. I have not found a setting in the INI file (old skool!) to change this.

 

Using Everything from Launchy

This next bit is directly from Lifehacker. Simply add a shortcut in a location that is indexed by Launchy, and use "C:\Program Files (x86)\Everything\Everything.exe" -search as the target. Name it appropriately (for example, "find") and re-index Launchy. Now you can type "find", TAB, and enter your search text. In order to do a search on your fileserver, make another shortcut, but add -connect 192.168.1.1 before the -search  option. I've named this shortcut "dfind", since my servername starts with a D.

 

I first read about Everything on the top 10 tiny & awesome Windows utilities at Lifehacker.

Tijmen 05:23, 1 June 2009

I've finally finished reading the excellent Working effectively with legacy code by Michael Feathers. It has been quite a struggle but that's merely because of the amount of useful information in it.

 

The author declares all code that is not under test to be legacy code. Ayende (author of Rhino mocks) basically based his mocking framework on the concepts in the book. Not surprisingly, he recommends the book as well.

 

I recently worked on an application written by another team that had zero unit tests. It did have a winforms test app included but that was merely for integration testing and required quite a bit of tweaking before anything useful could come out.

I started with isolating large chunks of functionality using Dependency injection with Unity. I then used StructureMap's automocker to bring most of the codebase under test (+80%).

Adding the required features was made much easier when most code was under test. This inspired me to throw a talk on TDD at meet the Masters in Microsoft at Avanade.

 

I´ll be hosting another talk about PEX next week and in preparing I will be diving into the book´s concepts. As most of these are written for either Java or C++, my focus will be around utilizing the same concepts in the beautiful world of .Net.

Tijmen 12:11, 26 May 2009

After Toms intro, I can't stay behind. I've been working in IT for about 10 years now, mainly working as a consultant for various shops, both large and small. Other random facts: I have a degree in Astronomy, a Norwegian forest cat, 2 daughters, I live somewhere between National Park "Utrechtse Heuvelrug" and de Veluwe and sometimes strike people as hyperactive (which I'm not).

My professional background started with developing line-of-business apps with MS Access. In that first year of my career I learned a lot about what problems businesses and business users run into, and the great part of using MS Access was that most projects had limited scope but surprising functional coverage: data modelling and entry, reporting, ETL, etc.

It also planted a seed for the urge to constantly improve as many things as possible about the "developer experience", for lack of a better term. By this I mean everything that influences the quality of code written and the efficiency of writing it: tools, guidelines, frameworks, even the keyboards in use

After this flirting with arguably one of the best RAD tools out there (yes, still talking about MS Access), I got involved on the Microsoft web stack, meaning classic ASP, VB 5/6, COM+, Windows DNA, that whole can of worms. Again, working with these tools, I always tried to come up with ways to reduce the pain and strain of developing software (and we had a lot of that in those days). This was also the time I realized that no, I wasn't that elusive consultant that can do everything perfectly: sure, I can design a user interface, but I'm no user experience expert. Fine, I know something about firewalls, protocols and tunneling, but I'm by no means an infrastructure guy. To cut a long story short: I learned to focus, to concentrate on specific skills to get ahead. I dabbled a bit in DBA roles, but at the heart I am a software developer with a slight tendency for web technologies.

Luckily for all of us, the world moved on since Windows DNA, and .NET has been upon us for quite some time. To accompany this framework, Microsoft has rolled out an impressive stack of server products to support all sorts of scenario's: stuff like BizTalk, SharePoint and SQL Server with all its BI bells and whistles to name a few. These days I often work as a solution  architect, which means I have to know a bit about most of these products, but again, they are mostly outside my focus zone. I continue to focus on the developer experience, trying to share both knowledge and enthusiasm along the way. Design patterns, principles like SOLID and DRY are high on my list of intended topics, but I also expect some less-focused (but equally interesting) ramblings on things I run across.

Tijmen 12:07, 26 May 2009

Both Tom and I were individually toying with the idea to start a blog about programming in the .NET space in general and all things related to patterns, SOLID and effective coding strategies. After finding out we shared initials - both T.J., even though Tom's are actually T.J.T.J. - and shared ideas, combining this with the fact that I already owned this sitename, we decided to join forces and start a shared blog. Our individual introductions will cover What we intend to blog about, but I suppose this will evolve over time anyway.

The blog runs on dasBlog, with a custom theme based on the included "project84grass" theme.

Tijmen 09:07, 25 May 2009

For those of you that don't know me already, I live in Amsterdam near the city market the Dappermarkt and the zoo Artis. I started my career in software development as a SQL programmer at one of those companies where you were allowed to wear short pants and play squash at Squashcity in between doing some actual work.

Besides being able to play squash a lot, the level of the people working there was quite high. Working with them got me addicted to having a creative, elegant solution rather than to have something working but was ugly as hell.

Obviously this also meant spending a great deal of time figuring out why stuff works the way it does. Programming SQL can be fun but has it's limits. Luckily the shop also had quite a large .Net development team and it didn't take me long to make the move to c#. From day 1 I have been in love with Visual Studio and c#. I really, really enjoy programming a lot, even more these days thanks to Resharper and the 3.5 framework.

Nowadays I work for a large global IT consultancy dedicated to using the Microsoft platform to help enterprises achieve profitable growth (shameless copy from the US site). My work focuses around building Brownfield solutions that involve either SharePoint or Web forms (follow the money).

I have a great passion for anything that will improve the process of building quality software. This means constant reading, follow many blogs and share knowledge. Thus far I have been doing this in the teams I worked with but I look forward to share my points of view using this blog.

I will spent most of my time blogging about code, testability, SOLID and anything else that will come on my way.

Tijmen 02:44, 25 May 2009
Well, getting dasBlog up and running on a shared hosting environment takes a bit of time... and a bit of trial and error. At first I published directly from Visual Studio using the "copy" > "only files needed to run this application" setting enabled, which leaves out (a lot of) files that dasBlog depends upon: trivial stuff like the content folder, things like that.
So, after that I wanted to log in to my ISPs control panel to chmod some of the folders (dasBlog needs write permissions to a couple of folders) only to find out that my password was no longer valid. OK, fine, no worries, I'll wait until Monday for proper human intervention. By the way, this post nicely details all the folder permission dasBlog needs.
Having gone through these steps, I was still greeted by a nice, unhelpful security exception, which told me
Request for the permission of type 'System.Security.Permissions.SecurityPermission, 
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

Not very helpful. So, after a bit of Googling I found this post, pointing towards a filelogger for the OpenID activity trace. As is suggested there, I commented out the entire system.diagnostics section from the web.config, since it only deals with this particular trace. After that, the site worked like a charm.