Tuesday, December 6, 2016

Reading Windows Registry values in c#

An example I wrote for retrieving any windows registry value, and return its string representation (some values are stored as byte arrays, some as 4-byte or 8-byte numbers, etc)


private static bool GetRegistryKeyValue(string keyFullPathWithoutRoot, string subKey, out string valueAsStr, RegistryHive rootNode = RegistryHive.LocalMachine, RegistryView registryView = RegistryView.Registry64, bool getNumericValuesInHexaNotation = truebool displayMessageBoxUponErrors = false)
{
    //search a registry key for a given subkey, if found return its value in a textual representation

    /*
     * Note:
     * The Wow6432 registry entry indicates that you're running a 64-bit version of Windows.
     * The OS uses this key to present a separate view of HKEY_LOCAL_MACHINE\SOFTWARE for 32-bit applications that run on a 64-bit version of Windows.
     */


    RegistryKey root = RegistryKey.OpenBaseKey(rootNode, registryView);
    RegistryKey registryKey = null;
    object subKeyValue = null;
    valueAsStr = null;

    try
    {
        //read key
        registryKey = root.OpenSubKey(keyFullPathWithoutRoot);

        if (registryKey != null)
        {
            //get subKey value type (binary, dword, etc)
            RegistryValueKind subKeyValueKind = registryKey.GetValueKind(subKey);
            subKeyValue = registryKey.GetValue(subKey);
            switch (subKeyValueKind)
            {
                case RegistryValueKind.Binary:
                    byte[] byteArray = (byte[])subKeyValue;
                    valueAsStr = string.Join(" ", byteArray.Select(b => b.ToString()));
                    break;

                case RegistryValueKind.DWord:
                    int dword = (int)subKeyValue;
                    valueAsStr = getNumericValuesInHexaNotation ? Convert.ToString(dword, 16).ToUpper() : dword.ToString();
                    break;

                case RegistryValueKind.QWord:
                    long qword = (long)subKeyValue;
                    valueAsStr = getNumericValuesInHexaNotation ? Convert.ToString(qword, 16).ToUpper() : qword.ToString();
                    break;

                case RegistryValueKind.String:
                    valueAsStr = (subKeyValue ?? string.Empty).ToString();
                    break;
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Failed to read {keyFullPathWithoutRoot}\\{subKey} key from registry. {ex.Message}");
        return false;
    }

    return true;
}
private static void TestRegistryReads()
{
    List<Tuple<stringstring, RegistryView>> keys = new List<Tuple<stringstring, RegistryView>>
    {
        new Tuple<stringstring, RegistryView>(@"SOFTWARE\Khronos\OpenCL\Vendors""IntelOpenCL32.dll", RegistryView.Registry32),
        new Tuple<stringstring, RegistryView>(@"HARDWARE\ACPI\FACS""00000000", RegistryView.Registry64)
    };

    foreach (var key in keys)
    {
        string value;
        if (GetRegistryKeyValue(key.Item1, key.Item2, out value, RegistryHive.LocalMachine, key.Item3, displayMessageBoxUponErrors: true))
        {
            Console.WriteLine("---------------------");
            Console.WriteLine($"Key: [{key.Item1}]  SubKey: [{key.Item2}], SubKeyValue: [{value}], Architecture: [{key.Item3.ToString()}]");
        }
    }
}

Sunday, November 27, 2016

Editing windows registry to Force WebBrowser control use the latest IE version installed in local machine

Here's the C# code I used for this task:

private void EditRegistryToFixIEWebBrowserCompatibility()
       {
           string installedIEVersion = string.Empty;
           int hostAppKeyValue = 0;
           //name of the application that hosts the WebBrowser object being invoked
           var hostAppKeyName = Assembly.GetExecutingAssembly().GetName().Name + ".exe";

           //registry key for Feature Browser Emulation
           RegistryKey regKeyFBE = null, regKeyInstalledIEVersion = null, regKeyHostApp = null;

           try
           {
               //search for Feature Browser Emulation key in relevant windows architecture
               if (Environment.Is64BitOperatingSystem)
               {
                   regKeyFBE = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\\Wow6432Node\\Microsoft\\Internet Explorer\\MAIN\\FeatureControl\\FEATURE_BROWSER_EMULATION"true);
                   regKeyInstalledIEVersion = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\\Wow6432Node\\Microsoft\\Internet Explorer"true);
               }
               else
               {
                   //For 32 bit machine
                   regKeyFBE = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION"true);
                   regKeyInstalledIEVersion = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\\Microsoft\\Internet Explorer\\"true);
               }

               //get current IE installed version
               installedIEVersion = Convert.ToString(regKeyInstalledIEVersion.GetValue("svcVersion"))?.Split('.').FirstOrDefault();
               int.TryParse(installedIEVersion, out hostAppKeyValue);
               hostAppKeyValue *= 1000;
           }
           catch (Exception ex)
           {
               MessageBox.Show("Registry creation of Feature Browser Emulation key failed for Internet Explorer failed. {0}", ex.Message);
               return;
           }

           #region Search for registry key

           try
           {
               //search for a dword with a key named like our app's exe (if its value is lower than the current installed IE version, discard
               hostAppKeyValue = Math.Max(hostAppKeyValue, Convert.ToInt32(regKeyFBE.GetValue(hostAppKeyName)));
           }
           catch (Exception)
           {
               MessageBox.Show($"{hostAppKeyName} key does not exist. Creating...");
               regKeyHostApp = regKeyFBE.CreateSubKey(hostAppKeyName);
               int.TryParse(installedIEVersion, out hostAppKeyValue);
               hostAppKeyValue *= 1000;
           }

           #endregion

           // Need to set the minimum IE version currently supported by Google Maps's api - multiplied by 1000
           regKeyFBE.SetValue(hostAppKeyName, unchecked(hostAppKeyValue), RegistryValueKind.DWord);

           try
           {
               //Check for the key after adding
               hostAppKeyValue = Convert.ToInt32(regKeyFBE.GetValue(hostAppKeyName));
           }
           catch (Exception ex)
           {
               MessageBox.Show("Registry creation of Feature Browser Emulation key failed for Internet Explorer failed. {0}", ex.Message);
               return;
           }
       }

Thursday, November 24, 2016

C# WebBrowser facing errors when navigating into a page that makes use of (the new 3.25) google maps api

Problem:

I have a win forms application that makes use of a System.Forms.WebBrowser object, which in turn navigates to a given html that contains several javascript files that makes an api for drawing areas/polygons / adding text labels, among other things, on top of google maps. The problem is that google recently upgraded their api to v3.25, in which they do not support anymore IE versions lower than 10. My WebBrowser object was always emulating an IE 7 browser (not clear why, because after creating a blank winforms project and adding a single WebBrowser into it, to navigate into a page like the mentioned above - but this time hosted locally - the user agent string displayed (after adding alert(this.navigator.userAgent); into the onload event of the body html element) contained no "compatible; MSIE 7;" or alike, rather a rv.11 (referring to IE 11)).
Having the WebBrowser running an emulation of IE 7 was causing javascript errors (Google's api stopped supporting IE versions prior to 10).

Solution:

The solution that finally worked was this one.

Summary:

  1. Make sure you have IE 10 or higher installed on the machine serving the uri WebBrowser is to navigate to.
  2. Add the registry values as indicated in the link above - do not forget, when adding the DWORD, to use a key with the exact .exe file where the WebBrowser instance is invoked.

I added another post containing the C# code for fixing this issue (another post because I wanted a post that would catch a closer-to-the-exact-issue title).

Tuesday, November 22, 2016

Find in Visual Studio Find Results (further search)

I was wondering if it was possible to further search the results of a Find Results window in Visual Studio. I googled it but did not arrive to any relevant answer.

I then played a bit with it and ended up figuring out that it is possible - it is built in, and it's quite simple: just click CTRL + F inside the Find Results window.



Thursday, October 13, 2016

Xamarin Forms Real Time Designer / Previewer

I have been trying what is available out there, at the moment, with regards to a real time UI designer for Xamarin forms.

The outcome of my research is:
  1.  Tried Xamarin's Previewer - am stuck with the designer showing a gray box containing  "XFPageRendererView". You can find other users facing the same issue. I tried to follow what they did to overcome it, but without success. Actually none of the solutions presented is really clear. It's worth mentioning a major drawback of this option: you must have a Mac running (at least in the current state of things, this seems to be a bug, not yet fixed) , to which you will connect to as the Mac Agent in Visual Studio, otherwise the previewer does not seem to respond. Like Gorilla Player, requires you to code your UI using XAML.
  2. Xamarin Forms Player - there is a nuget package, it is a headache to install, because it will (may) conflict with several of your other nuget packages - my workaround here was to manually install all the depencencies/missing ones, one by one, in the Droid project. Still, after being all set and ready to go, I could not go passed the Window with the Connect button. No idea how to proceed from there, what am I supposed to do, how do I finally see the preview. No suceess, followed the docs/the site, to no avail.
  3. Last and only working option - Gorilla Player. Setup consists of installing a program both in the desktop and in the device. But that's all. Just follow the instructions from the site, and things move smoothly. Drawback: you are forced to code your UI using XAML.

Sunday, October 9, 2016

Silverlight NumericUpDown and BusyIndicator dlls missing

If you are facing the messages

The type or namespace name 'NumericUpDown' could not be found (are you missing a using directive or an assembly reference?)

or

The type or namespace name 'BusyIndicator' could not be found (are you missing a using directive or an assembly reference?)

You are likely missing the installation of Silverlight's toolkit. Install the one that matches the silverlight version you are using.

Thursday, October 6, 2016

Find out which mySql version you are using without using the command line

Most posts will tell you to run something in the mysql command line, but in case you do not have it installed, like me (I have only an sql editor installed), function VERSION can give you that from the Sql Editor you are using:

Simply run  a SELECT VERSION()