Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows Registry Issue

I'm trying to modify some values in the registry using D, but it keeps giving me the following error:

Value cannot be set

However if I write the exact same code in C# then it works. Is it an issue with the registry module in D or is it an issue with the way I'm using it?

D

module main;

import std.windows.registry;
import std.stdio;

import core.thread;

void main() {
    string languageName = "English";
    string languageCode = "en_uk";
    const uint languageValue = 0x00000001;
    writefln("Name '%s' Code '%s' Value '%s'", languageName, languageCode, languageValue);
    writeln("Press ENTER to change language.");
    readln();
    writefln("Changing language of Sims 2 to '%s' ...", languageName);
    Thread.sleep(dur!("msecs")(2000));
    string keyName;
    try {
        enum versions = [
            "",
            "Apartment Life",
            "Bon Voyage",
            "Celebration Stuff",
            "Family Fun Stuff",
            "Free Time",
            "Fun with Pets Collection",
            "Glamour Life Stuff",
            "H M Fashion Stuff",
            "IKEA Home Stuff",
            "Kitchen & Bath Interior Design Stuff",
            "Mansion and Garden Stuff",
            "Nightlife",
            "Open For Business",
            "Pets",
            "Seasons",
            "Teen Style Stuff",
            "University"
        ];
        foreach (simsVersion; versions) {
            keyName = "SOFTWARE\\Wow6432Node\\EA GAMES\\The Sims 2";
            if (simsVersion && simsVersion.length)
                keyName ~= " " ~ simsVersion;
            // main
            {
                scope auto key = Registry.localMachine.getKey(keyName);
                key.setValue("Language", languageName);
                key.setValue("Locale", languageCode);
                key.flush();
            }
            // sub
            {
                keyName ~= "\\1.0";
                scope auto key = Registry.localMachine.getKey(keyName);
                key.setValue("Language", languageValue);
                key.setValue("LanguageName", languageName);
                key.flush();
            }
            writefln("Changed language of '%s' ...", simsVersion);
        }
        writeln("Success...");
        Thread.sleep(dur!("msecs")(2000));
    }
    catch (Throwable t) {
        writefln("Key Entry: '%s'", keyName);
        writeln(t);
        readln();
    }
}

C#

class Program
{
    public static void Main(string[] args)
    {
        const string languageName = "English";
        const string languageCode = "en_uk";
        const uint languageValue = 0x00000001;
        string[] versions = new string[]
        {
            "",
            "Apartment Life",
            "Bon Voyage",
            "Celebration Stuff",
            "Family Fun Stuff",
            "FreeTime",
            "Fun with Pets Collection",
            "Glamour Life Stuff",
            "H M Fashion Stuff",
            "IKEA Home Stuff",
            "Kitchen & Bath Interior Design Stuff",
            "Mansion and Garden Stuff",
            "Nightlife",
            "Open For Business",
            "Pets",
            "Seasons",
            "Teen Style Stuff",
            "University"
        };
        const string mainKey = @"SOFTWARE\Wow6432Node\EA GAMES\The Sims 2";
        string keyName = "";
        try
        {
            Console.WriteLine("Name '{0}' Code '{1}' Value '{2}'", languageName, languageCode, languageValue);
            Console.WriteLine("Press ENTER to change language.");
            Console.ReadLine();
            Console.WriteLine("Changing language of Sims 2 to '{0}' ...", languageName);
            Thread.Sleep(2000);

            foreach (var simsVersion in versions)
            {
                if (!string.IsNullOrWhiteSpace(simsVersion))
                    keyName = mainKey + " " + simsVersion;
                else
                    keyName = mainKey;
                // main
                {
                    var key = Registry.LocalMachine.OpenSubKey(keyName, true);
                    key.SetValue("Language", languageName);
                    key.SetValue("Locale", languageCode);
                    key.Close();
                }
                // sub
                {
                    keyName += "\\1.0";
                    var key = Registry.LocalMachine.OpenSubKey(keyName, true);
                    key.SetValue("Language", languageValue);
                    key.SetValue("LanguageName", languageName);
                    key.Close();
                }
                Console.WriteLine("Changed language of '{0}' ...", simsVersion);
            }
            Console.WriteLine("Success...");
            Thread.Sleep(2000);
        }
        catch (Exception e)
        {
            Console.WriteLine("Key: '{0}'", keyName);
            Console.WriteLine(e);
            Console.ReadLine();
        }
    }
}
like image 627
Bauss Avatar asked May 07 '15 17:05

Bauss


1 Answers

As you have SOFTWARE\WOW6432Node registry entry your system is 64-bit. By default C# compiler (see /platform:anycpu, it is also used by default in VS) produces an assembly which runs as 64-bit process on 64-bit system and as 32-bit process on 32-bit system.

Also by default registry queries of a 32-bit process on 64-bit system are redirected to special WOW6432Node subkey (e.g. request to open HKLM\Software will actually open HKLM\Software\WOW6432Node, see MSND article "32-bit and 64-bit Application Data in the Registry"). As a result your 32-bit D application (just like your C# application will do if run as 32-bit process) actually tries to open SOFTWARE\Wow6432Node\Wow6432Node\EA GAMES\The Sims 2 key which doesn't exist.

To fix the issue either compile D application in 64-bit mode (-m64 switch) or use REGSAM.KEY_WOW64_64KEY to disable default redirection:

Registry.localMachine.getKey(keyName, REGSAM.KEY_READ | REGSAM.KEY_WOW64_64KEY);

Note: RegistryView.Registry64 can be used to disable default redirection in C# if it runs as 32-bit process on 64-bit system.

like image 111
Denis Avatar answered Oct 04 '22 04:10

Denis