Forum Discussion

howie_'s avatar
howie_
Contributor
11 years ago

Reading the registry from ScriptExtensions

Does anyone happen to know if there's an easy way to read the registry from a script extension? I'd normally use Storages.Registry(), but that doesn't seem to be on the list of approved objects, (as per this article). I've been sifting through the source material, but I haven't had any luck so far. 



I figure it doesn't hurt to ask before I to try to cook up some convoluted powershell/console-app/who-knows-what workaround. 



Thanks, 

Howie 
  • I wrote a quick wrapper for the Registry class; it's attached if you're interested. I designed it so that you could call Registry.CurrentUser.GetValue() and whatnot. The file needs to be broken into 8 pieces: 



    - description.xml

    - ClassesRoot.sj

    - CurrentConfig.sj

    - CurrentUser.sj

    - DynData.sj

    - LocalMachine.sj

    - PerformanceData.sj

    - Users.sj



    I'm not guaraneeing that it's perfect, but it's yours if you want it. 
  • Philip_Baird's avatar
    Philip_Baird
    Community Expert

    Hi Howie, I think it's a pretty safe bet to think the Registry Class will function as you require.


     


    I use some .Net Classes of a similar vintage with no issues, in fact I am considering using the Registry Class in a Script Extension myself.


     


    Regards,


    Phil Baird


  • Thank you both for your responses. I have a couple follow up questions for each of you, I'll list them below including my current implementation in case anyone else is curious. 


     


     


     


    Phil, 


    I managed to get the CLR Bridge to work; is it safe to assume that this technique will contine to work on any target machine as long as it has .Net 2.0 or greater installed? I don't want to assume that it will work only to have it betray me at the last minute when I run it in TestExecute. 


     


     


    CLR BRidge Code (working): 


    -----------------------------------------


    function GetLanguageCode()


    {


    var keyPath =  "HKEY_CURRENT_USER\\Control Panel\\International";


    var value = "Locale";


    var default = 0x00000409;


     


    return dotNET.Microsoft_Win32.Registry.GetValue(keyPath, value, default).OleValue;


    }




     



    ==================================



    ==================================


     




    Helen, 


     


    I couldn't actually get the WMI method to work for me. Maybe you can see what I'm doing wrong. I managed to ge it to return a value, but the value always comes back as '2', instead of "0x00000409". Additionally, is it also safe to assume that the WMI service will be intstalled and running on any Window machine with .Net installed? 


     


     


     


    CLR BRidge Code (broken): 


    ----------------------------------------


    function GetLanguageCode()


    {


    var HKEY_CURRENT_USER = 0x80000001;


    var keyPath = "Control Panel\International";


    var value = "Locale";


     


    var reg = GetObject("WinMgmts:{impersonationLevel=impersonate}!/root/default:StdRegProv");


    return reg.GetStringValue(HKEY_CURRENT_USER, keyPath, value);


     


    }

  • Hi Howie,



    One note about the .NET method: by default, it accesses only the 32-bit or only 64-bit registry - as specified by the Preferred architecture of the assembly hosting process option in the CLR Bridge options of the current project. If you need to access both 32-bit and 64-bit registries at the same time (e.g. in HKLM\SOFTWARE\ and HKLM \SOFTWARE\Wow6432Node), use something like this:

    (Note: This requires .NET Framework 4+.)



    function Test()

    {

      var HKLM = -2147483646;

      var key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion";

      var value = "ProgramFilesDir";



      var str = GetRegistryValue(HKLM, key, value /* , 32 */);

      Log.Message(str); // C:\Program Files (x86) - value from Wow6432Node



      str = GetRegistryValue(HKLM, key, value, 64);

      Log.Message(str); // C:\Program Files

    }



    function GetRegistryValue(RootKey, KeyName, ValueName, Bitness)

    {

      var oRegView = (Bitness == 64

        ? dotNET.Microsoft_Win32.RegistryView.Registry64

        : dotNET.Microsoft_Win32.RegistryView.Registry32);



      var oRoot = dotNET.Microsoft_Win32.RegistryKey.OpenBaseKey(RootKey, oRegView);

      var oKey = oRoot.OpenSubKey(KeyName);

      return oKey.GetValue(ValueName);

    }


  • Additionally, is it also safe to assume that the WMI service will be intstalled and running on any Window machine with .NET installed?


    WMI is a built-in Windows component - it works even if .NET isn't installed.



    I couldn't actually get the WMI method to work for me. Maybe you can see what I'm doing wrong. I managed to ge it to return a value, but the value always comes back as '2', instead of "0x00000409".


    That's because GetStringValue returns the error code, not the value itself. The value is returned through the last out parameter.

    Also, you forgot to double the backslash in the key name - "Control Panel\\International".



    Here's the working example. It's a bit longer than the .NET method. :) I see you're already using the .NET method, but I thought I'd post it anyway.



    function Test()

    {

      var HKCU = 0x80000001;

      var key = "Control Panel\\International";

      var value = "Locale";



      var str = ReadRegStr(HKCU, strKey, strValue);

      Log.Message(str);

    }



    // ----------------------------------------------------------------------------------------

    // Returns a string value (REG_SZ) from the registry.

    // Parameters:

    //   RootKey - one of the following values:

    //       HKEY_CLASSES_ROOT: 0x80000000

    //       HKEY_CURRENT_USER: 0x80000001

    //       HKEY_LOCAL_MACHINE: 0x80000002

    //       HKEY_USERS: 0x80000003

    //       HKEY_CURRENT_CONFIG: 0x80000005

    //   KeyName - the key name

    //   ValueName - the value name

    //   Architecture - the number 32 or 64 that indicates the registry bitness. Default is 32.

    // ----------------------------------------------------------------------------------------

    function ReadRegStr(RootKey, KeyName, ValueName, Architecture)

    {

      var oCtx = new ActiveXObject("WbemScripting.SWbemNamedValueSet");

      if (typeof Architecture === 'undefined') Architecture = 32;

      oCtx.Add("__ProviderArchitecture", Architecture);



      var oLocator = new ActiveXObject("WbemScripting.SWbemLocator");

      var oWMI = oLocator.ConnectServer("", "root\\default", "", "", "", "", 0, oCtx);

      var oReg = oWMI.Get("StdRegProv");



      var oInParams = oReg.Methods_("GetStringValue").Inparameters;

      oInParams.Hdefkey = RootKey;

      oInParams.Ssubkeyname = KeyName;

      oInParams.Svaluename = ValueName;



      var oOutParams = oReg.ExecMethod_("GetStringValue", oInParams, 0, oCtx);

      return oOutParams.SValue;

    }