nunit-console-x86 can't access the Windows Registry correctly

Asked by Patrick Walker

NUnit version: 2.5.9.10348
Windows Version: Windows 7 x64 SP1
CLR version: 2.0.50727.5420 (Net 2.0)

I have written a helper library that (amongst others) reads some registry values. When I'm loading the Test.dll directly into NUnit GUI (not the x86 version), all tests pass. When I load it into the x86 version, some tests (those testing the registry values) fail. The libraries are created using VisualStudio 2008 and compiled as "Any CPU".

My problem is that I need to use the x86 versions because I'm profiling the tests with PartCover to track my test coverage. When I use the non-x86 versions, PartCover doesn't produce any output.

So my question is now: Is this an issue of NUnit-x86 or is there a way to get PartCover to work with the non-x64 version?

Any help or hint in the right direction would be much aprechiated.

Question information

Language:
English Edit question
Status:
Solved
For:
NUnit V2 Edit question
Assignee:
No assignee Edit question
Solved by:
Simone Busoli
Solved:
Last query:
Last reply:
Revision history for this message
Simone Busoli (simone.busoli) said :
#1

Without any additional information I would guess that the registry keys you are reading are varying according to the bitness of the executing process which tries to read them. What kind of registry keys are you trying to read? Do you specify a full path or are you relying on placeholders or wildcards?

Also, can you post a code snippet which reproduces the problem?

Revision history for this message
Patrick Walker (homesen) said :
#2

Hi Simone,

thank you for your quick reply. I feared it could be an issue with the x86/x64 mix. Anyways, here is one method that fails under nunit-console-x86:

[code]
private const string REGISTRY_LOCATIONS = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\Locations";

[...]

public static string GetUserAreaCode()
{
    RegistryKey hklmLocations = Registry.LocalMachine.OpenSubKey(REGISTRY_LOCATIONS);
    try
    {
        object currentID = hklmLocations.GetValue("CurrentID");
        if (currentID == null)
            return String.Empty;
        RegistryKey currentLocation = hklmLocations.OpenSubKey("Location" + currentID);
        object areaCode = currentLocation.GetValue("AreaCode");
        if (areaCode == null)
            return String.Empty;

        return areaCode.ToString();
    }
    catch { return String.Empty; }
}
[/code]

This method is used to get the user's default location's area code, as it is normally set within "Control Panel"->"Telephony"->"Locations".

Revision history for this message
Simone Busoli (simone.busoli) said :
#3

I cannot see anything blatantly wrong with the code. What are the failures you're getting when running on the x86 version of nunit's console?

Revision history for this message
Patrick Walker (homesen) said :
#4

When I started the test to copy the exact failure message, the test for the above method now somehow works correctly. But other methods still fail. One example is the following:

[code]
private const string REGISTRY_COUNTRYLIST_LEGACY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\CountryList";
        private const string REGISTRY_COUNTRYLIST_MODERN = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\Country List";

[...]

public static string GetCountryNameFromRegistry(int countryID)
{
    string result = "";

    RegistryKey hklmCountry = Registry.LocalMachine.OpenSubKey(REGISTRY_COUNTRYLIST_LEGACY);
    if (hklmCountry == null)
        hklmCountry = Registry.LocalMachine.OpenSubKey(REGISTRY_COUNTRYLIST_MODERN);
    if (hklmCountry == null)
        return String.Empty;

    try
    {
        hklmCountry = hklmCountry.OpenSubKey(countryID.ToString());
        result = hklmCountry.GetValue("Name").ToString();
    }
    catch { }

    return result;
}
[/code]

I need to check both locations because Microsoft change the name of the specific Registry key when they introduced Windows Vista.

The failing test is as follows:
[code]
[Test]
public void GetCountryNameFromRegistry_GermanCountryID_ReturnsGermany()
{
    int countryID = 49;
    // TODO: The registry contains the localized names of the countries,
    // thus the expected result needs to be translated to the correct language.
    //string expected = "Germany";
    string expected = "Deutschland";
    string actual = PhoneNumberData.GetCountryNameFromRegistry(countryID);

    Assert.AreEqual(expected, actual);
}
[/code]

The failure message is:
1) Test Failure : HomeSen.Helpers.Conversion.Tests.PhoneNumberDataTests.GetCountryNameFromRegistry_GermanCountryID_ReturnsGermany
     Expected string length 11 but was 0. Strings differ at index 0.
  Expected: "Deutschland"
  But was: <string.Empty>
  -----------^

Currently I'm evaluating the NCover Trial version which works as expected. So maybe I just have to invest the money for a more recent (and working) code coverage solution.

Revision history for this message
Best Simone Busoli (simone.busoli) said :
#5

I think it's a bug in the .NET framework. Try this code in a console app:

   class Program
    {
        static void Main()
        {
            Console.WriteLine(string.Join(Environment.NewLine,
                                          Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony").GetSubKeyNames()));
        }
    }

I tried running that code on a W7 x64 machine, compiling it as x86 and x64. Here the results.

x86:

Providers
TAPI3
Terminal Manager
Locations

x64:

Country List
Locations
Providers
TAPI3
Terminal Manager

As you can see Country List is not shown when compiling for x86, but I can't guess why. For sure it doesn't have anything to do with NUnit.

Revision history for this message
Patrick Walker (homesen) said :
#6

Thank you very much for your help.

On my machine it even misses some other SubKeys, too. I'll have a look if this is .NET2 specific, or if it also happens with other versions. I would never have come to conclusion that it might be a NETFX issue.

Here are the results from my machine:

x86:
Providers
TAPI3
Terminal Manager
Locations

x64/AnyCPU:
Country List
EllSoft/Auerswald LAN-TAPI
Locations
Providers
TAPI3
Terminal Manager

Once again, thank you for your assistence.

Revision history for this message
Simone Busoli (simone.busoli) said :
#7

You're welcome. BTW, on a x64 machine compiling for Any CPU is the same as compiling for x64.

I tried running the same code under the fx 4.0 and I get the same results.