Adjustment of testing environment via Registry

Sometimes  you have to adjust parameters of your testing environment before running your tests. It may be some security settings, turning on or off some plug-ins, settings of browsers or other applications. As an example let’s look at the settings of Internet Explorer browser. Using this browser many automation testers often face with the following error: “Unexpected error launching Internet Explorer. Protected Mode settings are not the same for all zones. Enable Protected Mode must be set to the same value (enabled or disabled) for all zones. (NoSuchDriver)” 12.1

This error occurs when Protected  Mode for different zones are not the same. This is old and known issue which is easy to handle off. To solve the issue you just have to turn on Protected Mode for all zones or turn it off. 12.2

You can do it manually or programmatically using InternetExplorerOptions class from OpenQA.Selenium.IE namespace. Here I took this issue as an example to show you how you can adjust IE setting and many other things changing values of your system registry. Default setting of Internet Explorer browser are not the same for all zones and every time you have set the IE to its default (this is recommended to do before running tests) you have to adjust Protected Mode again. And if you have to do it on remote machine and especially on many machines it becomes boring. Fortunately there is an elegant solution. All these settings (and many other) may be set programmatically. Before starting working Internet Explorer reads its settings from system registry. So, if you put correct values to the registry the browser will be parametrized just as you need. Now a couple of words how to work with system registry. С# has special class named Registry for that, this class is located in  Microsoft.Win32 namespace. There are a lot of examples of using this class in the Internet, so I do not see any sense to describe it here one more time. I just want to show you my own solution. You have to create additional application for working with registry. Create new solution in Visual Studio with a project of Console Application type. 12.3

Give a name for your namespace and class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Win32;

namespace Assign_Environment_Settings
{
    class Program
    {
        static void Main()
        {
        }
    }
}

Add enumerator RegistryBranch to class Programm. It will be used for switching between branches of system registry

internal enum Branches
{
    HKLM,
    HKCU
}

Add struct KeyValueDescr, it will be representing one value for the registry

internal struct KeyValueDescr
{
    internal string key;
    internal string value;
    internal string message;
}

Add struct RegistryEntry, this is one registry entry

internal struct RegistryEntry
{
    internal string path;
    internal KeyValueDescr[] values;
}

And now add a method for setting in a value to the registry

internal static void SetRegistryValue(Branches branch, RegistryEntry[] settings, int delay)
{
    //declaration of an instance of registry key
    RegistryKey key = null;

    //block using is utilized for closing the registry after work and releasing used resources as RegistryKey implements interface IDisposable. Details are here : (http://msdn.microsoft.com/en-us/library/system.idisposable.aspx)
    using (key)
    {
        //looking over all setting that should be set
        foreach (var setting in settings)
        {
            //switching between registry branches.
            switch (branch)
            {
                case Branches.HKLM:
                    key = Registry.LocalMachine;
                    break;
                case Branches.HKCU:
                    key = Registry.CurrentUser;
                    break;
            }
            try
            {
               if (key != null)
               {
                   key = key.OpenSubKey(setting.Path, true);
                   foreach (var v in setting.values)
                   {
                       if (key != null)
                       {
                            try
                            {
                                key.SetValue(v.key, v.value);
                                Console.WriteLine(v.message);
                            }
                            catch (Exception ex)
                           {
                               Console.WriteLine(ex.Message);
                           }
                       }
                      else
                          throw new Exception("Registry branch " + setting.Path + " does not exist or is not available for editing!");
                  }
              }
          }
          catch (Exception ex)
          {
              Console.WriteLine(ex.Message);
           }
           Thread.Sleep(delay);
        }
    }
    Console.WriteLine("Done!");
}

Now before the method will be invoked you should describe necessary settings (in our case this is Protected Mode in IE). Inside Main() method let’s declare and initialize the settings:

RegistryEntry[] ie_settings =
 {
     new RegistryEntry
     {
         path = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1",
         values = new [] 
         {
             new KeyValueDescr
             {
                 key = "2500",
                 value = "0",
                 message = "Protected Mode for Local Intranet zone: enabled"
             }
         }
     },
     new RegistryEntry
     {
         path = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2",
         values = new [] 
         {
             new KeyValueDescr
             {
                 key = "2500",
                 value = "0",
                 message = "Protected Mode for Trusted Sites zone: enabled"
            }
        }
    },
    new RegistryEntry
    {
        path = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3",
        values = new [] 
        {
            new KeyValueDescr
            {
                key = "2500",
                value = "0",
                message = "Protected Mode for Internet zone: enabled"
            }
        }
    },
    new RegistryEntry
    {
        path = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\4",
        values = new [] 
        {
            new KeyValueDescr
            {
                key = "2500",
                value = "0",
                message = "Protected Mode for Restricted Sites: enabled"
            }
        }
    }
};

Now the method SetRegistryValues may be invoked:

const int delay = 1000;
Console.WriteLine("ENVIRONMENT SETTINGS\r\n");
Console.WriteLine("Starting to assign Internet Explorer settings...");
Console.WriteLine("------------------------------------------------");

SetRegistryValues(Branches.HKCU, ie_settings, delay);

Console.WriteLine("\r\nAll changes done!");
Thread.Sleep(delay * 10);

Now I will explain where the values used above are taken from. To know what values to use you should know what is changing in the registry when you do some actions in the system. The program RegFromApp can help. There are 64 and 32-bit versions of the program. Located here. There are good documentation of the program on the site. You can read it for some details. Here I describe only necessary for current project features. Open the application which you are going to watch for (in my case it is Internet Explorer browser). Select Tools -> Internet Options

12.4

Then Security tab

12.5

Adjust all settings you are about to change in wrong position. For example turn off Protected Mode for all zones. Now launch appropriate version of RegFromApp. In ‘select process to inspect’ window select process of the Internet Explorer – IEXPLORE.EXE.

12.6

Return back to IE and turn on Protected Mode for all zones, click Apply. In RegFromApp window you can see the following values:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\4] “2500”=dword:00000000

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\2] “2500”=dword:00000000

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1] “2500”=dword:00000000

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3] “2500”=dword:00000000 12.7

That’s it. You’ve got the path, key and value for all changed settings of Protected Mode. Later when you start the IE this values will be read by the browser from system registry. Now you can put this values in your RegistrySettings application, recompile the code and to launch it from your automated tests or manually. To run the program automatically invoke the code below right before running your tests. For example:

const int timeoutSec = 20;
var regSettings = new ProcessStartInfo
{
    FileName = "C:\\pathToTheProgram\\RegistrySettings.exe"
};
Process proc = Process.Start(regSettings);
int ticker = 0;
while (proc != null && (!proc.HasExited || ticker < timeoutSec))
{
    Thread.Sleep(1000);
    ticker++;
}

You can do it in a method with attribute [TestFixtureSetUp] or in a parent class of your test classes or via separate script. Playing with RegFromApp you can get a lot of additional information about system registry and create automated adjustments for other programs and applications that use the registry for storing their settings. Note that if current user of your operating system may have limited permissions for editing the registry settings. An attempt to change such values will throw an exception with error message like “Registry branch Softaware\Microsoft\Internet Explorer\Main does not exist or is not available for editing!”. To avoid it your current user should have system administrator permissions. Also sometimes the system firewall or antivirus program may deny you to change the registry or may require additional confirmation. It may be adjusted in settings of appropriate program.

One Reply to “Adjustment of testing environment via Registry”

  1. Nice Presentation and very clear step by step process. I had a good understanding.
    Thanks
    J Synder.

Leave a Reply