Today we started running our Coded-UI Tests in the TFS Lab Environment, or at least tried to... unfortunately, we were greeted with this popup error message while attempting to run tests...

As it turns out, we have written several of our own automation objects, and expanded some of the automation peers to be able to test for some of the extended features that we have within our user interfaces. The Offending assemblies are:
Microsoft.VisualStudio.TestTools.UITesting
Microsoft.VisualStudio.TestTools.UITest.Extension
These are referenced by our "automation" assemblies. We do not want to include the Microsoft TestTools files in our internal build/test because we want to test what matches the deliverables supplied to our customers. I had some difficulty tracking down an idea solution to this, I had thought about updating our deployment scripts to copy the needed files into the appropriate directories, but discarded that idea because I want to maintain an environment as close to what the end users would have as possible.
I came across a post in the MSDN news groups talking about adding a probing path to the configuration, but decided against that because I did not want to include specific paths in the application's config file that could change from environment to environment; not to mention would deviates from what we deliver to the customer. Instead I decided to include an assembly resolver that could determine where the requested assemblies were and resolve them when encountered. It just seemed much cleaner that way.
I updated our WPF application to include the resolver as follows
//-- Connect an assembly resolver to allow the Code to run within a Test Environment
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolverForTestEnvironment);
I had previously come across a post by Vinoth Sathappan (Microsoft), he is a Software Design Engineer in the Visual Studio 2010 Coded UI Test Team that had posted a snippet of code that could be used to resolve the assembly. I adapted his code to work on both 32-bit and 64-bit systems, as well as in an environment where visual studio, itself is not installed.
private static Assembly CurrentDomain_AssemblyResolverForTestEnvironment(object sender, ResolveEventArgs args)
{
AssemblyName assemblyName = new AssemblyName(args.Name);
if (assemblyName.Name.StartsWith("Microsoft.VisualStudio", StringComparison.Ordinal))
{
string path = string.Empty;
//-- Lets try to get the installation location of the public/private assemblies from the Visual Studio key...
if (Environment.Is64BitOperatingSystem)
{
path = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\", "InstallDir", null);
}
else
{
path = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\", "InstallDir", null);
}
//-- Did we get it?
if(string.IsNullOrEmpty(path))
{
//-- No, perhaps the Quality Tools Agent is installed instead...
if (Environment.Is64BitOperatingSystem)
{
path = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\EnterpriseTools\\QualityTools\\Agent\\", "InstallationPath", null);
}
else
{
path = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\EnterpriseTools\\QualityTools\\Agent\\", "InstallationPath", null);
}
}
//-- Do we have an installation directory?
if (!string.IsNullOrWhiteSpace(path))
{
//-- Yes, lets get to see if the assembly exists in either the public or private assemblies directories...
string assemblyPath = Path.Combine(path, "PublicAssemblies", string.Format(CultureInfo.InvariantCulture, "{0}.dll", assemblyName.Name));
if (!File.Exists(assemblyPath))
{
assemblyPath = Path.Combine(path, "PrivateAssemblies", string.Format(CultureInfo.InvariantCulture, "{0}.dll", assemblyName.Name));
if (!File.Exists(assemblyPath))
{
string commonFiles = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86);
if (string.IsNullOrWhiteSpace(commonFiles))
{
commonFiles = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles);
}
assemblyPath = Path.Combine(commonFiles, "Microsoft Shared", "VSTT", "10.0", string.Format(CultureInfo.InvariantCulture, "{0}.dll", assemblyName.Name));
}
}
//-- If we have the full path of the assembly, lets load and return it...
if (File.Exists(assemblyPath))
{
return Assembly.LoadFrom(assemblyPath);
}
}
}
return null;
}
The code above works in my Isolated Lab Environment when I have only installed the Lab, Build and Test Agents. This is because it first checks the Visual Studio registry key, and if that is not found, it checks the quality tools registry key.