Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,640
|
Comments: 51,264
Privacy Policy · Terms
filter by tags archive
time to read 4 min | 742 words

I was recently at the Israeli ALT.Net tools night, and I had a very interesting discussion on installers. Installers are usually a very painful part of the release procedure. The installer format for Windows is MSI, which is… strange. It takes time to understand how MSI work, and even after you got that, it is still painful to work with. Wix is a great improvement when it comes to building MSI installations, but that doesn’t make it good. Other installer builders, such as InstallSheild and NSIS are just as awkward.

The discussion that I had related to the complexity of building an installer on those technologies.

My argument was that it simply made no sense to try to overcome the hurdles of the installer technologies, instead, we can write our own installer more easily than fussing about the existing ones. The installer already assumes the presence of the .NET framework, so that make things even easier.

This is an application of a principle that I strongly believes in: Single purpose, specially built tools & components can be advantageous over more generic ones, for your specific scenarios.

Case in point, the installer. Installers are complicated beasts because they must support a lot of complex scenarios (upgrading from 5.3.2 to 6.2.1, for example), be transactional, support installation, etc. But for the installer in question, upgrade is always an uninstall of the previous version & install of the new one, and the only tasks it requires is copying files and modifying registry entries.

Given that set of requirements, we can design the following installer framework:

public interface IInstallerTask
{
     void Install();
     void Uninstall();
}

public class FileCopyTask : IInstallerTask
{
    public string Source { get;set; }
    public string Destination { get;set; }
    
    public void Install()
    {
        File.Copy(Source, Destination,overwrite:true);
    }
    
    public void Uninstall()
    {
        File.Delete(Destination);
    }
}

And building a particular installer would be:

ExecuteInstaller(
    Directory.GetFiles(extractedTempLocation)
        .Select( file =>
            new FileCopyTask
            {
                Source = file,
                Destination = Path.Combine(destinationPath, file)
            }        
        ),
    new RegistryKeyTask
    {
        Key = "HKLM/Windows/CurrentVersion...",
        Value = 9
    }
);

This gives the ExecuteInstaller method a list of tasks to be executed, which can then be used to installer or uninstall everything.

Yes, it is extremely simple, and yes, it wouldn’t fit many scenarios. But, it is quick to do, match the current and projected requirements, doesn’t introduce any new technology to the mix and it works.

Contrast that with having someone on the team that is the Installer expert (bad) or having to educate the entire team about installer (expensive).

time to read 1 min | 103 words

It has been a while since we had a new major feature for the profiler, but here it is:

image

The expensive queries report will look at all your queries and surface the most expensive ones across all the sessions. This can give you a good indication on where you need to optimize things.

Naturally, this feature is available across all the profiler profiles (NHibernate Profiler, Entity Framework Profiler, Linq to SQL Profiler and Hibernate Profiler).

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. API Design (10):
    29 Jan 2026 - Don't try to guess
  2. Recording (20):
    05 Dec 2025 - Build AI that understands your business
  3. Webinar (8):
    16 Sep 2025 - Building AI Agents in RavenDB
  4. RavenDB 7.1 (7):
    11 Jul 2025 - The Gen AI release
  5. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
View all series

Syndication

Main feed ... ...
Comments feed   ... ...