Mocking ASP.NET providers

When playing around with ASP.NET membership, I found myself in a situation where I wanted to mock the ASP.NET Providers. This is something the design of providers makes non-trivial. Mark Seemann summarises: “Since a Provider creates instances of interfaces based on XML configuration and Activator.CreateInstance, there’s no way to inject a dynamic mock.”. See Provider is not a pattern.

I had a look around to see what others were doing. I found a post, Mocking membership provider, which proposes adding mocked providers to the provider collection dynamically. It seems like an elegant solution, but I couldn’t get it to work for me after a little playing.

In the end, I came up with a solution that is not the most elegant, but is very easy to use and to understand.

I create an implementation of each provider I want to. The provider contains a mock of that provider type. Each method and property of my provider implementation forwards to the mock the implementation provides. The mock is accessible via a static method of the provider implementation, so that test code can interact with it.

An example implementation:

public class TestRoleProvider : RoleProvider
{
	public static void ResetMock()
	{
		Mock = new Mock<RoleProvider>();
	}

	public static Mock<RoleProvider> Mock { get; private set; }

	#region RoleProvider implementation

	public override void AddUsersToRoles(string[] usernames, string[] roleNames)
	{
		Mock.Object.AddUsersToRoles(usernames, roleNames);
	}

	public override string ApplicationName
	{
		get { throw new NotImplementedException(); }
		set { throw new NotImplementedException(); }
	}

	// Other implementations omitted
}

Note the static methods controlling the mock at the top. Note also that I’ve simply implemented all methods and properties of RoleProvider as not implemented using Visual Studio tooling, and then updated the implementations to forward calls to my mock as I need.

Wiring up the provider framework to use this implementation is easy. Just add the following config to the app.config of your unit test project:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<system.web>
		<roleManager defaultProvider="TestRoleProvider" enabled="true">
			<providers>
				<add name="TestRoleProvider"
					 type="TestProjectAssemblyName.TestRoleProvider, TestProjectAssemblyName" />
			</providers>
		</roleManager>
	</system.web>
</configuration>

Test code utilising this mock looks like the following:

[TestInitialize]
public void TestInitialize() 
{
	TestRoleProvider.ResetMock();
}
		
[TestMethod]
public void ReturnsNothingWhenNoUsersExist()
{
	var roles = new string[] { };
	TestRoleProvider.Mock.
		Setup(m => m.GetAllRoles()).
		Returns(roles);

	var result = new GetAllRolesQuery().Execute();

	Assert.IsTrue(!result.Any());
}

Generating multiple files from one T4 template

In the previous posts about T4 I firstly drove T4 generation from EF entity definitions, then used this to make EF POCO classes with certain properties implement an interface. Please read these posts before reading this one – in particular the code in this post refers to code from the previous one.

In this post, I’ll extend what I’ve already built to handle multiple interfaces, and to generate a single file per interface.

For this example, I’m going to use two interfaces.

public interface IUserNameStamped
{
    string UserName { get; set; }
}

public interface ILookup
{
    string Code { get; set; }

    string Description { get; set; }
}

I want my EF POCOs to implement IUserNameStamped if they have a UserName property, and ILookup if they have a Code and Description property. I want the IUserNameStamped code in a file IUserNameStamped.cs, and ILookup code in a file ILookup.cs.

By default, a T4 template will generate a single file with the same name as the the template, and the extension defined by the <#@ output #> directive. The EntityFrameworkTemplateFileManager, used by EF to generate a file per entity, is the secret to generating multiple files from a single template.

The other change needed to the T4 code we already have is to break it into reusable methods that can be shared for each entity.

The method I’ve defined to generate an file for a given interface is CreateInterfaceFile, shown here with support classes.

<#+
void CreateInterfaceFile(EntityFrameworkTemplateFileManager fileManager,  
	CodeGenerationTools code,
	EdmItemCollection itemCollection,
	string namespaceName, 
	Action interfaceWriter, 
	string interfaceName, 
	params string[] requiredProperties)
{
    fileManager.StartNewFile(interfaceName + ".cs");
	BeginNamespace(namespaceName, code);
	interfaceWriter();
	var entities = GetEntitiesWithPropertyOrRelationship(itemCollection,
		requiredProperties);
	foreach (EntityType entity in entities.OrderBy(e => e.Name))
	{
		WriteInterfaceImplementation(entity.Name, interfaceName);
	}
	EndNamespace(namespaceName);
}
#>
<#+
void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
    CodeRegion region = new CodeRegion(this);
    if (!String.IsNullOrEmpty(namespaceName))
    {
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
        PushIndent(CodeRegion.GetIndent(1));
    }
}


void EndNamespace(string namespaceName)
{
    if (!String.IsNullOrEmpty(namespaceName))
    {
        PopIndent();
#>
}
<#+
    }
}

IEnumerable<EntityType> GetEntitiesWithPropertyOrRelationship(
	EdmItemCollection itemCollection, 
	params string[] requiredProperties)
{
	return itemCollection.GetItems<EntityType>().Where(entity => 
		EntityHasPropertyOrRelationship(entity, requiredProperties));
}

bool EntityHasPropertyOrRelationship
	(EntityType entity, params string[] requiredProperties)
{
	return requiredProperties.All(
		requiredProperty => entity.Properties.Any(property => property.Name == requiredProperty)
		|| entity.NavigationProperties.Any(property => property.Name == requiredProperty));
}

void WriteInterfaceImplementation(string entityName, string interfaceName)
{
#>

public partial class <#=entityName#> : <#=interfaceName#>
{
}
<#+
}

The parameters of CreateInterfaceFile:

  • The first three parameters are T4 and EF classes instantiated at the top of the template and passed in.
  • namespaceName is also provided by T4 – the namespace the interface and classes will belong to.
  • interfaceWriter is a action that writes out the definition of the interface itself.
  • interfaceName is the name of the interface.
  • requiredProperties is an array of all the properties a class must have to be considered to implement the interface.

The logic is very simple

  • The EntityFrameworkTemplateFileManager is used to start a file for the interface – all output now goes to this file until the next time StartNewFile is called.
  • The namespace is written.
  • The declaration of the interface is written.
  • Entities matching this interface are found using GetEntitiesWithPropertyOrRelationship (as explained in the previous blog post.
  • An partial implementation of the class for each matching entity is written, with no content, simply stating that the class implements the interface in question.
  • The namespace is closed.

That’s about all there is to it. Once again, an extension to this code to match entity properties by type as well as name is left as an exercise to the reader.

Here is full source code:

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
 output extension=".cs"#><#

string inputFile = @"OticrsEntities.edmx";
EdmItemCollection itemCollection = new MetadataLoader(this).
	CreateEdmItemCollection(inputFile);

CodeGenerationTools code = new CodeGenerationTools(this);
string namespaceName = code.VsNamespaceSuggestion();

EntityFrameworkTemplateFileManager fileManager = 
	EntityFrameworkTemplateFileManager.Create(this);
WriteHeader(fileManager);

#>
// Default file generated by T4. Generation cannot be prevented. Please ignore.
<#

CreateInterfaceFile(fileManager, 
	code,
	itemCollection, 
	namespaceName,
	WriteILookupInterface,
	"ILookup",
	"ContractorCode", "Description");

CreateInterfaceFile(fileManager, 
	code,
	itemCollection, 
	namespaceName,
	WriteIUserNameStampedInterface,
	"IUserNameStamped",
	"UserName");
	
fileManager.Process(true);

#>
<#+
void CreateInterfaceFile(EntityFrameworkTemplateFileManager fileManager,  
	CodeGenerationTools code,
	EdmItemCollection itemCollection,
	string namespaceName, 
	Action interfaceWriter, 
	string interfaceName, 
	params string[] requiredProperties)
{
    fileManager.StartNewFile(interfaceName + ".cs");
	BeginNamespace(namespaceName, code);
	interfaceWriter();
	var entities = GetEntitiesWithPropertyOrRelationship(itemCollection, 
		requiredProperties);
	foreach (EntityType entity in entities.OrderBy(e => e.Name))
	{
		WriteInterfaceImplementation(entity.Name, interfaceName);
	}
	EndNamespace(namespaceName);
}
#>
<#+
void WriteHeader(EntityFrameworkTemplateFileManager fileManager, 
	params string[] extraUsings)
{
    fileManager.StartHeader();
#>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System.Collections.Generic;

<#=String.Join(String.Empty, extraUsings.
		Select(u => "using " + u + ";" + Environment.NewLine).
		ToArray())#>
<#+
    fileManager.EndBlock();
}

void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
    CodeRegion region = new CodeRegion(this);
    if (!String.IsNullOrEmpty(namespaceName))
    {
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
        PushIndent(CodeRegion.GetIndent(1));
    }
}


void EndNamespace(string namespaceName)
{
    if (!String.IsNullOrEmpty(namespaceName))
    {
        PopIndent();
#>
}
<#+
    }
}

IEnumerable<EntityType> GetEntitiesWithPropertyOrRelationship(
	EdmItemCollection itemCollection, 
	params string[] requiredProperties)
{
	return itemCollection.GetItems<EntityType>().Where(entity => 
		EntityHasPropertyOrRelationship(entity, requiredProperties));
}

bool EntityHasPropertyOrRelationship(EntityType entity, 
	params string[] requiredProperties)
{
	return requiredProperties.All(requiredProperty => 
		entity.Properties.Any(property => property.Name == requiredProperty)
		|| entity.NavigationProperties.Any(property => property.Name == requiredProperty));
}

void WriteInterfaceImplementation(string entityName, string interfaceName)
{
#>

public partial class <#=entityName#> : <#=interfaceName#>
{
}
<#+
}

void WriteILookupInterface()
{
#>
/// <summary>
/// A lookup entity, that can be looked up by a ContractorCode
/// </summary>
public interface ILookup
{
    string ContractorCode { get; set; }
	
	string Description { get; set; }
}
<#+
}

void WriteIUserNameStampedInterface()
{
#>
/// <summary>
/// An entity that is stamped with the Username that created it
/// </summary>
public interface IUserNameStamped
{
    string UserName { get; set; }
}
<#+
}
#>

Duck typing Entity Framework classes using T4 Templates

Duck typing is an interesting concept, and alien to C# generally. But using the techniques of my previous post about T4 and Entity Framework, it is possible to have your entities implement interfaces if they have the required properties, resulting in behaviour similar to duck typing. Please read the previous blog post before reading this one.

The previous blog post gives us code to implement interfaces for each entity in an object model. In order to provide “duck typing”, we will extend this to only implement the interface for an entity if that entity has the properties of the interface.

Fortunately System.Data.Metadata.Edm.EntityType gives us the ability to inspect the properties of an entity. For my purposes, I only check for properties by name, as I control my database and would never have the same column name with two different data types. Extension of this code to check property types as well as names is left as an exercise for the reader.

IEnumerable<EntityType> GetEntitiesWithPropertyOrRelationship(
    EdmItemCollection itemCollection, params string[] requiredProperties)
{
    return itemCollection.GetItems<EntityType>().
        Where(entity => EntityHasPropertyOrRelationship(entity, requiredProperties));
}

bool EntityHasPropertyOrRelationship(
    EntityType entity, params string[] requiredProperties)
{
    return requiredProperties.All(
        requiredProperty => entity.Properties.Any(property => property.Name == requiredProperty)
        || entity.NavigationProperties.Any(property => property.Name == requiredProperty));
}

Pretty simple stuff. EntityHasPropertyOrRelationship checks both the Properties (properties relating to simply database columns), and NavigationProperties (properties relating to foreign key relationships) for properties with the required names. If our entity has all the required properties, it’s a match.

GetEntitiesWithPropertyOrRelationship uses EntityHasPropertyOrRelationship to retrieve all the entities that have the required properies from our itemCollection.

I’ve blogged about further extending the template to handle multiple interfaces, with one file per interface.

Here’s the full code of the example from the last blog post, updated so entities only implement IUserNameStamped if they actually have a column called UserName.

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>
<#
string inputFile = @"Entities.edmx";
EdmItemCollection itemCollection = new MetadataLoader(this).
    CreateEdmItemCollection(inputFile);

CodeGenerationTools code = new CodeGenerationTools(this);
string namespaceName = code.VsNamespaceSuggestion();

WriteHeader();
BeginNamespace(namespaceName, code);
WriteIUserNameStamped();
WriteEntitiesWithInterface(itemCollection);
EndNamespace(namespaceName);
#>
<#+
void WriteHeader(params string[] extraUsings)
{
#>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

<#=String.Join(String.Empty, extraUsings.
    Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#>
<#+
}

void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
    CodeRegion region = new CodeRegion(this);
    if (!String.IsNullOrEmpty(namespaceName))
    {
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
        PushIndent(CodeRegion.GetIndent(1));
    }
}


void EndNamespace(string namespaceName)
{
    if (!String.IsNullOrEmpty(namespaceName))
    {
        PopIndent();
#>
}
<#+
    }
}

void WriteIUserNameStamped()
{
#>
/// <summary>
/// An entity that is stamped with the Username that created it
/// </summary>
/// <remarks>
/// All OTICRS entities should have a username. If any entity fails to implement
/// this interface, it means the table needs the UserName column added to it.
/// </remarks>
public interface IUserNameStamped
{
    string UserName { get; set; }
}

<#+
}

void WriteEntitiesWithInterface(
    EdmItemCollection itemCollection)
{
    foreach (EntityType entity in 
        GetEntitiesWithPropertyOrRelationship(itemCollection, "UserName").
        OrderBy(e => e.Name))
    {
        WriteEntityWithInterface(entity.Name);
    }
}

IEnumerable<EntityType> GetEntitiesWithPropertyOrRelationship(
    EdmItemCollection itemCollection, params string[] requiredProperties)
{
    return itemCollection.GetItems<EntityType>().Where(
        entity => EntityHasPropertyOrRelationship(entity, requiredProperties));
}

bool EntityHasPropertyOrRelationship(
    EntityType entity, params string[] requiredProperties)
{
    return requiredProperties.All(
        requiredProperty => entity.Properties.Any(property => property.Name == requiredProperty)
        || entity.NavigationProperties.All(property => property.Name == requiredProperty));
}

void WriteEntityWithInterface(string entityName)
{
#>
public partial class <#=entityName#> : IUserNameStamped
{
}

<#+
}

#>

Using T4 Templates to extend your Entity Framework classes

A set of entities I’m using with Entity Framework (I’m using EF POCO) have common properties implying commonality between the entities. I didn’t want to use any form of inheritance within my object model to express this commonality, but I did wish to have the entity classes implement common interfaces. It’s easy to do this because entities are partial classes. Say for example all my entities have a string property UserName, I can define an interface to express this, and then have a partial implemention of the class that implements the interface.

public interface IUserNameStamped
{
    string UserName { get; set; }
}
    
public partial class Entity1 : IUserNameStamped
{
}
    
public partial class Entity2 : IUserNameStamped
{
}

So the POCO T4 template generates the “main” class definition for each entity, with all it’s properties, and then these partial classes extend the class, not adding any new properties or methods, just extending with the fact each class implements the IUserNameStamped interface.

I quickly realised that I could use T4 in a similar manner to the EF POCO T4 template, in order to produce these partial classes automatically.

As I explained in my post about UserName stamping entities as they’re saved, all my entities have a UserName column. So all this template has to do is loop through all the entities in my object model, and write an implementation for each.

The main T4 logic is

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>
<#
string inputFile = @"OticrsEntities.edmx";
EdmItemCollection itemCollection = new MetadataLoader(this).
    CreateEdmItemCollection(inputFile);

CodeGenerationTools code = new CodeGenerationTools(this);
string namespaceName = code.VsNamespaceSuggestion();

WriteHeader();
BeginNamespace(namespaceName, code);
WriteIUserNameStamped();
WriteEntitiesWithInterface(itemCollection);
EndNamespace(namespaceName);
#>

Most of this is cribbed unashamedly from the EF POCO T4 template. Firstly we initialise some variables, the most interesting being itemCollection, which is what allows access to the entity metadata. We then write a header indicate the file is a generated file, start the namespace, write the actual declaration of the IUsernameStamped interface, write a partial class for each entity implementing the interface, and then end the namespace. The specifics of each method are:

<#+
void WriteHeader(params string[] extraUsings)
{
#>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

<#=String.Join(String.Empty, 
    extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#>
<#+
}

void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
    CodeRegion region = new CodeRegion(this);
    if (!String.IsNullOrEmpty(namespaceName))
    {
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
        PushIndent(CodeRegion.GetIndent(1));
    }
}


void EndNamespace(string namespaceName)
{
    if (!String.IsNullOrEmpty(namespaceName))
    {
        PopIndent();
#>
}
<#+
    }
}

I think these three methods are fairly self-explanatory, other than the <# syntax that T4 uses to indicate code and text blocks.

void WriteIUserNameStamped()
{
#>
/// <summary>
/// An entity that is stamped with the Username that created it
/// </summary>
public interface IUserNameStamped
{
    string UserName { get; set; }
}

<#+
}

Simply generates the interface definition.

void WriteEntitiesWithInterface(EdmItemCollection itemCollection)
{
	foreach (EntityType entity in itemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
	{
		WriteEntityWithInterface(entity.Name);
	}
}

Iterates through the entities.

void WriteEntityWithInterface(string entityName)
{
#>
public partial class <#=entityName#> : IUserNameStamped
{
}

<#+
}

#>

Writes an implementation of the IUserNameStamped interface for each entity.

So you can see it’s fairly simple to use T4 to generate C# code similar to that at the top of this blog post.

I’ve blogged about how I extended this code to make a certain set of entities with common properties implement a common interface

I’ve also blogged about further extending the template to handle multiple interfaces, with one file per interface.

This is the full code of the T4 template:

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>
<#
string inputFile = @"Entities.edmx";
EdmItemCollection itemCollection = new MetadataLoader(this).CreateEdmItemCollection(inputFile);

CodeGenerationTools code = new CodeGenerationTools(this);
string namespaceName = code.VsNamespaceSuggestion();

WriteHeader();
BeginNamespace(namespaceName, code);
WriteIUserNameStamped();
WriteEntitiesWithInterface(itemCollection);
EndNamespace(namespaceName);
#>
<#+
void WriteHeader(params string[] extraUsings)
{
#>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

<#=String.Join(String.Empty, extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#>
<#+
}

void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
    CodeRegion region = new CodeRegion(this);
    if (!String.IsNullOrEmpty(namespaceName))
    {
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
        PushIndent(CodeRegion.GetIndent(1));
    }
}


void EndNamespace(string namespaceName)
{
    if (!String.IsNullOrEmpty(namespaceName))
    {
        PopIndent();
#>
}
<#+
    }
}

void WriteIUserNameStamped()
{
#>
/// <summary>
/// An entity that is stamped with the Username that created it
/// </summary>
public interface IUserNameStamped
{
    string UserName { get; set; }
}

<#+
}

void WriteEntitiesWithInterface(EdmItemCollection itemCollection)
{
	foreach (EntityType entity in itemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
	{
		WriteEntityWithInterface(entity.Name);
	}
}

void WriteEntityWithInterface(string entityName)
{
#>
public partial class <#=entityName#> : IUserNameStamped
{
}

<#+
}

#>

Updating the registry using .NET and LogParser

I have discovered a need to be able to search and replace registry values. I originally thought about using Powershell but after reading this blog post about Powershell performance with the registry, I decided to use .NET. I quickly encountered the idea of using LogParser to read the registry at high speed, and decided this was a fruitful avenue.

The background to this need is that when you use a custom profile location, you can only use Chrome as your default browser by editing the registry. I did this manually once. Then when I found the keys had reset themselves, I decided coding something to update the registry for me would be interesting.

The first stage was to get the LogParser COM interop built. This was pleasantly easy. As simple as running tlbimp "C:\Program Files (x86)\Log Parser 2.2\LogParser.dll" /out:Interop.MSUtil.dll, adding the DLL as a reference to my project, adding using statements to Program.cs, and then writing some code. I started by getting the search going.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using LogQuery = Interop.MSUtil.LogQueryClass;
using RegistryInputFormat = Interop.MSUtil.COMRegistryInputContextClass;
using RegRecordSet = Interop.MSUtil.ILogRecordset;
using System.Diagnostics;
using Microsoft.Win32;
using System.Collections.Generic;

namespace FreeSpiritSoftware.ChromeRegistryCustomProfile
{
	public class Program
	{
		private const string DefaultChromeCall = @"""C:\Users\sam\AppData\Local\Google\Chrome\Application\chrome.exe"" -- ""%1""";

		public static void Main(string[] args)
		{
			RegRecordSet rs = null;

			Stopwatch stopWatch = new Stopwatch();
			stopWatch.Start(); 
			try
			{
				LogQuery qry = new LogQuery();
				RegistryInputFormat registryFormat = new RegistryInputFormat();
				string query = string.Format(@"SELECT Path, ValueName from \HKCR, \HKCU, \HKLM, \HKCC, \HKU where Value = '{0}'", DefaultChromeCall);
				rs = qry.Execute(query, registryFormat);
				for (; !rs.atEnd(); rs.moveNext())
				{
					string path = rs.getRecord().toNativeString(0);
					string valueName = rs.getRecord().toNativeString(1);
					Console.WriteLine(path);
					Console.WriteLine(valueName);
					Console.WriteLine("--");
				}
			}
			finally
			{
				rs.close();
			}
			stopWatch.Stop();
			Console.WriteLine(stopWatch.Elapsed.TotalSeconds + " seconds");
			Console.ReadKey(false);
		}
	}
}

You’ll see I explicitly reference the five registry keys in the FROM statement of the query I give LogParser, even though I’m searching the whole registry. This is because when I tried FROM /, I got two results per root key of the registry, one using the abbreviated root key name, one using it’s full name (e.g. I’d get HKEY_CLASSES_ROOT\ChromeHTML\shell\open\command and HKCR\ChromeHTML\shell\open\command).

So once I had the code above working, the next step was to actually access and update the keys using Microsoft.Win32.Registry. This proved to be more complex than I had expected as (a) you have to access the root keys as static properties of Registry, and (b) from a particular key, you can only access its immediate subkeys. I’m sure there are libraries that make matters simpler, but working around was easy enough.

To deal with the root keys, I created a dictionary to use to look up root key abbreviations from LogParser, and return the root key objects. I created a recursive function to move through subkeys to finally access the subkey referenced by a path.

private static readonly IDictionary<string, RegistryKey> RegistryLookup = new Dictionary<string, RegistryKey>
{
	{ "HKCR", Registry.ClassesRoot },
	{ "HKCU", Registry.CurrentUser },
	{ "HKLM", Registry.LocalMachine },
	{ "HKCC", Registry.CurrentConfig },
	{ "HKU", Registry.Users },
};

private static RegistryKey GetSubKey(IEnumerable<string> splitPath)
{
	RegistryKey rootKey = RegistryLookup[splitPath.First()];
	return GetSubKey(rootKey, splitPath.Skip(1));
}

private static RegistryKey GetSubKey(RegistryKey key, IEnumerable<string> splitPath)
{
	var theRest = splitPath.Skip(1);
	return theRest.Any()
		? GetSubKey(key.OpenSubKey(splitPath.First()), splitPath.Skip(1))
		: key.OpenSubKey(splitPath.First(), writable: true);
}

So for HKCR\ChromeHTML\shell\open\command and HKCR\ChromeHTML\shell\open\command, it’ll split off HKCR and get the root key, call GetSubKey(Registry.ClassesRoot, { "ChromeHTML", "shell", "open", "command" }) which will get the ChromeHTML subkey within HKCR, and call GetSubKey(ChromeHTML, { "shell", "open", "command" }), and so on, until it calls with GetSubKey(open, { "command" }), and which point recursion ends, and the “command” key is opened writable and returned.

From this point things were easy. The only other complication was that LogParser represents the default key as "(Default)", whereas Microsoft.Win32.Registry represents it as string.Empty.

The final code looks like this. Parameterisation, tidying, etc is left as an exercise for the reader.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using LogQuery = Interop.MSUtil.LogQueryClass;
using RegistryInputFormat = Interop.MSUtil.COMRegistryInputContextClass;
using RegRecordSet = Interop.MSUtil.ILogRecordset;
using System.Diagnostics;
using Microsoft.Win32;
using System.Collections.Generic;

namespace FreeSpiritSoftware.ChromeRegistryCustomProfile
{
	public class Program
	{
		private const string DefaultChromeCall = @"""C:\Users\sam\AppData\Local\Google\Chrome\Application\chrome.exe"" -- ""%1""";
		private const string ReplacementChromeCall = @"""C:\Users\sam\AppData\Local\Google\Chrome\Application\chrome.exe"" --user-data-dir=""E:\settings\chrome-profiles""  -- ""%1""";
		private static readonly char[] PathSeparator = new[] { '\\' };
		private static readonly IDictionary<string, RegistryKey> RegistryLookup = new Dictionary<string, RegistryKey>
        {
            { "HKCR", Registry.ClassesRoot },
            { "HKCU", Registry.CurrentUser },
            { "HKLM", Registry.LocalMachine },
            { "HKCC", Registry.CurrentConfig },
            { "HKU", Registry.Users },
        };

		public static void Main(string[] args)
		{
			RegRecordSet rs = null;

			Stopwatch stopWatch = new Stopwatch();
			stopWatch.Start();
			try
			{
				LogQuery qry = new LogQuery();
				RegistryInputFormat registryFormat = new RegistryInputFormat();
				string query = string.Format(@"SELECT Path, ValueName from \HKCR, \HKCU, \HKLM, \HKCC, \HKU where Value = '{0}'", DefaultChromeCall);
				rs = qry.Execute(query, registryFormat);
				for (; !rs.atEnd(); rs.moveNext())
				{
					string path = rs.getRecord().toNativeString(0);
					string valueName = rs.getRecord().toNativeString(1);
					if (valueName == "(Default)")
						valueName = string.Empty;
					Console.WriteLine(path);
					Console.WriteLine(valueName);
					String[] splitPath = path.Split(PathSeparator);
					RegistryKey key = GetSubKey(splitPath.Take(splitPath.Length));
					Console.WriteLine(key.GetValue(valueName));
					key.SetValue(valueName, ReplacementChromeCall);
					Console.WriteLine(key.GetValue(valueName));
					Console.WriteLine("--");
				}
			}
			finally
			{
				rs.close();
			}
			stopWatch.Stop();
			Console.WriteLine(stopWatch.Elapsed.TotalSeconds + " seconds");
			Console.ReadKey(false);
		}

		private static RegistryKey GetSubKey(IEnumerable<string> splitPath)
		{
			RegistryKey rootKey = RegistryLookup[splitPath.First()];
			return GetSubKey(rootKey, splitPath.Skip(1));
		}

		private static RegistryKey GetSubKey(RegistryKey key, IEnumerable<string> splitPath)
		{
			var theRest = splitPath.Skip(1);
			return theRest.Any()
				? GetSubKey(key.OpenSubKey(splitPath.First()), splitPath.Skip(1))
				: key.OpenSubKey(splitPath.First(), writable: true);
		}
	}
}

(Note: I’m aware that there are aliases within the registry so I’m performing duplicate searches, I was happy to just use a brute-force search).

Tidy IEqualityComparer with GenericEqualityComparer

Whilst looking through a codebase, I saw implementations of IEqualityComparer<>. After thinking to myself that the need to create an entire implementation of IEqualityComparer<> per use creates quite a bit of boilerplate for such a small amount of signal, I realised that creating a generic implementation of IEqualityComparer<> that takes a definition of equality in its constructor would be very simple.

public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
	private readonly Func<T, T, bool> mEqualsFunc;
	private readonly Func<T, int> mGetHashCodeFunc;

	public GenericEqualityComparer(Func<T, T, bool> equalsFunc, 
		Func<T, int> getHashCodeFunc)
	{
		if (equalsFunc == null)
			throw new ArgumentNullException("equalsFunc");
		if (getHashCodeFunc == null)
			throw new ArgumentNullException("getHashCodeFunc");

		mEqualsFunc = equalsFunc;
		mGetHashCodeFunc = getHashCodeFunc;
	}

	public bool Equals(T x, T y)
	{
		return mEqualsFunc(x, y);
	}

	public int GetHashCode(T obj)
	{
		return mGetHashCodeFunc(obj);
	}
}

Creating and using an instance of this class is as simple as

public class TestClass
{
	private static readonly GeneralEqualityComparer<Foo> mFooComparer = 
		new GeneralEqualityComparer<Foo>(
			(x, y) => x.Id == y.Id,
			obj => obj.Id);

	public void GetDistinctFoos(IEnumerable<Foo> foos)
	{
		return foos.Distinct(mFooComparer);
	}
}

However, I was a bit embarrassed when I told my boss, Tony Beveridge, about this great use of generics and Funcs I had thought of, and he told me he had actually implemented exactly the same class some months ago.

Its worth noting that EqualityComparer<T>.Default provides a default implementation using the Equals() and GetHashCode() functions of T.

If you wanted to extend GenericEqualityComparer so you don’t have to provide an implementation for GetHashCode(), you can default mGetHashCodeFunc to always return zero. This will force the Equals function to always be called.

IEnumerable, ReadOnlyCollection, and the missing interface

I’ve been thinking on and off about the appropriate return signature for a method that returns an immutable list of objects, sparked off by reading Eric Lippert’s article, Arrays considered somewhat harmful, and my belief that the value of functional program and growth of parallelism means that immutability is desirable most of the time.

However, once you decide to return an immutable collection, what type do you return?

IEnumerable is not really appropriate. The problem is that an IEnumerable may possibly be only evaluable a single time, or may cost for every evaluation of it you perform. This means that you end up with consumers of your method having to use ToList() or ToArray() to flatten the IEnumerable before consuming it, which is wasteful when your method is returning a bounded collection.

So the only choice you have with .NET is ReadOnlyCollection. Which is okay, but not ideal, I believe.

Firstly this involves specifying a return signature as a concrete type. I prefer my method signatures to be interfaces when primitives are not being used, so they only specify behavour. This also means that you can’t return an object that doesn’t use ReadOnlyCollection as a base class.

The second issue is that ReadOnlyCollection implements ICollection and IList. Whilst the implementation of methods such as Add are explicit, the fact ReadOnlyCollection implements interfaces with methods that are invalid for it creates a class of bugs only findable at run time. Have a look at the following code.

public ReadOnlyCollection<object> GetReadOnly()
{
	ReadOnlyCollection<object> readOnly = new List<object>().AsReadOnly();
}

public void ShowIssue()
{
	ReadOnlyCollection<object> readOnly = GetReadOnly();
	// The next line prevented at compile time
	// readOnly.Add(new object());

	// However this code compiles, unfortunately
	IList<object> iList = GetReadOnly()
	iList.Add(new object()); // Fails with an exception at runtime
}

I think that it would have been sensible for .NET to have had an interface that inherits IEnumerable, that represents a readonly bounded collection, called something like IReadOnlyCollection. It would have a Count and allow read only access to the elements by index. ICollection and IList would both inherit this interface, and ReadOnlyCollection would be the implementation of it.

Update: Firstly, this article doesn’t really cover the differences between immutable and read only. The ReadOnlyCollection doesn’t provide any methods to change the collection membership. However ReadOnlyCollection is only a wrapper around the List, and it does not guarantee that the underlying list is not changed.

Links that may be of interest:

Parsing Event Logs using System.Diagnostics.Eventing.Reader

I’ve just had to analyse a bunch of Event Logs that contain exceptions, produced from a load testing exercise. I needed to turn them into a summary of the counts of each class of exception that occurred.

The exceptions belonging to each class of exception message didn’t generate exactly the same text in the event log data every time. So I decided the simplest way to categorise them was to have each category able to work out if it matches event log data using one of two criteria: either data contains a substring; or data matches a Regex. Flexible enough for the fairly simple requirements of this scenario.

After a little research, I found out about the existence of the System.Diagnostics.Eventing.Reader class, which will parse event logs from either the local or a remote computer, or from an EVTX file. The event logs I was parsing already needed to be saved into a file and archived after each run, so I made the parser use the archived files. I’m still keen to play with parsing logs directly off remote computers at some point.

Here’s some code. I haven’t included all the boring declaration of constants and the like in these code snippets, just the interesting bits. Some of it’s a wee bit hack-ish and not properly structured or parameterised; as this is a small utility for occasional use, the effort to make it really nice isn’t currently justified.

The EventLogMatcher class itself:

public class EventLogMatcher
{
  public EventLogMatcher(string dataContains, string dataRegex, string description)
  {
    if (!(string.IsNullOrEmpty(dataContains) ^ 
        string.IsNullOrEmpty(dataRegex)))
      throw new ArgumentException
        ("One and only one of dataContains and dataRegex must be specified");
    DataContains = string.IsNullOrEmpty(dataContains) 
      ? null
      : dataContains;
    DataRegex = string.IsNullOrEmpty(dataRegex) 
      ? null 
      : new Regex(dataRegex, RegexOptions.Singleline);
    Description = description;
  }

  public string DataContains { get; private set; }

  public Regex DataRegex { get; private set; }

  public string Description { get; private set; }

  public bool IsDataMatch(string data)
  {
    return (DataContains != null && data.Contains(DataContains)) || 
      (DataRegex != null && DataRegex.IsMatch(data));
  }
}

The main loop of the program itself – it processes all the EVTX files in the SourcePath directory:

foreach (string sourceFile in Directory.EnumerateFiles(SourcePath, SourcePattern))
{
  string outputFile = DeriveOutputFilename(sourceFile);
  IDictionary<EventLogMatcher, int>; logMatchCounts = GetInitialisedLogTypeCounts();
  List<UnmatchedEventLog> unmatchedLogs = new List<UnmatchedEventLog>();

  EventLogReader logReader = new EventLogReader(new EventLogQuery(sourceFile, PathType.FilePath));
  for (EventRecord eventInstance = logReader.ReadEvent(); eventInstance != null; 
    eventInstance = logReader.ReadEvent())
  {
    EventLogMatcher matcher = logMatchCounts.Keys.
	  SingleOrDefault(key => key.IsDataMatch(GetData(eventInstance)));
    if (matcher == null)
      unmatchedLogs.Add(ToUnmatchedLog(eventInstance));
    else
      logMatchCounts[matcher]++;
  }
  WriteMatchedResults(outputFile, logMatchCounts, unmatchedLogs);
};

I love using System.Xml.Linq. It makes parsing XML files really simple, and quite readable. Especially for a utility like this where proper error handling isn’t important.

The code for getting the dictionary of EventLogMatchers and counts:

private static IDictionary<EventLogMatcher, int> GetInitialisedLogTypeCounts()
  {
    return LogTypes.ToDictionary(type => type, type => 0);
  } 

  private static IEnumerable<EventLogMatcher> GetParsedLogTypes()
  {
    XDocument source = XDocument.Load(KnownEventLogTypesFileName);
    return source.Elements(EventLogsTypesXName).
      Elements(EventLogsTypeXName).
      Select(ParseAsLogMatcher);
  }

  private static EventLogMatcher ParseAsLogMatcher(XElement element)
  {
    string dataContains = element.GetValueOfOptionalAttribute(DataContainsXName);
    string dataRegex = element.GetValueOfOptionalAttribute(DataRegexXName);
    string description = element.Attribute(DescriptionXName).Value; 
    return new EventLogMatcher(dataContains, dataRegex, description, ignored, defaultReason);
  }

internal static class XElementExtensions
{
  public static string GetValueOfOptionalAttribute(this XElement element, XName attributeName)
  {
    XAttribute attribute = element.Attribute(attributeName);
    return attribute == null ? null : attribute.Value;
  }
}

The actual XML for KnownEventLogTypes.xml is structured like this

<?xml version="1.0" encoding="utf-8" ?>
<EventLogsTypes>
  <EventLogsType 
     dataContains="System.Net.WebException: The operation has timed out" 
     description="The operation has timed out" />
  <EventLogsType
     dataRegex="Internal failure Sorry, there was an error\. Please try again later.*AnAgent\.GetSomethingInteresting"
     description="Internal failure in AnAgent. GetSomethingInteresting" />
</EventLogsTypes>

Not rocket science, but simple and effective.

Next time around I’d look at Powershell to do this: Get-EventLog also looks like a simple way to deal with event logs. But I’m glad to have had the opportunity to learn about System.Diagnostics.Eventing.Reader.