Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There is still native support for registry access under 64 bit Windows using <strong>.NET Framework 4.x</strong>. The following code is tested with &nbsp;<em>Windows 7, 64 bit</em>&nbsp; and also with &nbsp;<em>Windows 10, 64 bit</em>. To access the <strong>64 bit registry</strong>, you can use:</p> <pre><code>string value64 = string.Empty; RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); if (localKey != null) { value64 = localKey.GetValue("RegisteredOrganization").ToString(); } Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64)); </code></pre> <p>If you want to access the <strong>32bit registry</strong>, use:</p> <pre><code>string value32 = string.Empty; RegistryKey localKey32 = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32); localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); if (localKey32 != null) { value32 = localKey32.GetValue("RegisteredOrganization").ToString(); } Console.WriteLine(String.Format("RegisteredOrganization [value32]: {0}",value32)); </code></pre> <p>Don't be confused, both versions are using <code>Microsoft.Win32.RegistryHive.LocalMachine</code> as first parameter, you make the distinction whether to use <strong>64 bit</strong> or <strong>32 bit</strong> by the <strong>2nd parameter</strong> (<code>RegistryView.Registry64</code> versus <code>RegistryView.Registry32</code>).</p> <p><strong>Note</strong> that </p> <ul> <li><p>On a 64bit Windows, <code>HKEY_LOCAL_MACHINE\Software\Wow6432Node</code> contains values used by 32 bit applications running on the 64 bit system. Only true 64 bit applications store their values in <code>HKEY_LOCAL_MACHINE\Software</code> directly. The subtree <code>Wow6432Node</code> is entirely transparent for 32 bit applications, 32 bit applications still see <code>HKEY_LOCAL_MACHINE\Software</code> as they expect it (it is a kind of redirection). In older versions of Windows as well as 32 bit Windows 7 (and Vista 32 bit) the subtree <code>Wow6432Node</code> obviously does <strong>not</strong> exist.</p></li> <li><p>Due to a bug in Windows 7 (64 bit), the 32 bit source code version always returns "Microsoft" regardless which organization you have registered while the 64 bit source code version returns the right organization.</p></li> </ul> <p>Coming back to the example you've provided, do it the following way to access the 64 bit branch:</p> <pre><code>RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); RegistryKey sqlServerKey = localKey.OpenSubKey( @"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL"); string sqlExpressKeyName = (string) sqlServerKey.GetValue("SQLEXPRESS"); </code></pre> <hr> <p><strong>Update:</strong></p> <p>I'd like to add an interesting approach <a href="https://stackoverflow.com/users/222134/johny-skovdal">Johny Skovdal</a> has suggested in the comments, which I've picked up to develop some useful functions by using his approach: In some situations you want to get back all keys regardless whether it is 32 bit or 64 bit. The SQL instance names are such an example. You can use a union query in that case as follows (C#6 or higher):</p> <pre><code>// using Microsoft.Win32; public static IEnumerable&lt;string&gt; GetRegValueNames(RegistryView view, string regPath, RegistryHive hive = RegistryHive.LocalMachine) { return RegistryKey.OpenBaseKey(hive, view) ?.OpenSubKey(regPath)?.G‌​etValueNames(); } public static IEnumerable&lt;string&gt; GetAllRegValueNames(string RegPath, RegistryHive hive = RegistryHive.LocalMachine) { var reg64 = GetRegValueNames(RegistryView.Registry64, RegPath, hive); var reg32 = GetRegValueNames(RegistryView.Re‌​gistry32, RegPath, hive); var result = (reg64 != null &amp;&amp; reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32); return (result ?? new List&lt;string&gt;().AsEnumerable()).OrderBy(x =&gt; x); } public static object GetRegValue(RegistryView view, string regPath, string ValueName="", RegistryHive hive = RegistryHive.LocalMachine) { return RegistryKey.OpenBaseKey(hive, view) ?.OpenSubKey(regPath)?.G‌​etValue(ValueName); } public static object GetRegValue(string RegPath, string ValueName="", RegistryHive hive = RegistryHive.LocalMachine) { return GetRegValue(RegistryView.Registry64, RegPath, ValueName, hive) ?? GetRegValue(RegistryView.Re‌​gistry32, RegPath, ValueName, hive); } public static IEnumerable&lt;string&gt; GetRegKeyNames(RegistryView view, string regPath, RegistryHive hive = RegistryHive.LocalMachine) { return RegistryKey.OpenBaseKey(hive, view) ?.OpenSubKey(regPath)?.GetSubKeyNames(); } public static IEnumerable&lt;string&gt; GetAllRegKeyNames(string RegPath, RegistryHive hive = RegistryHive.LocalMachine) { var reg64 = GetRegKeyNames(RegistryView.Registry64, RegPath, hive); var reg32 = GetRegKeyNames(RegistryView.Re‌​gistry32, RegPath, hive); var result = (reg64 != null &amp;&amp; reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32); return (result ?? new List&lt;string&gt;().AsEnumerable()).OrderBy(x =&gt; x); } </code></pre> <p>Now you can simply use the functions above as follows:</p> <pre><code>var sqlRegPath=@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL"; foreach (var valueName in GetAllRegValueNames(sqlRegPath)) { var value=GetRegValue(sqlRegPath, valueName); Console.WriteLine($"{valueName}={value}"); } </code></pre> <p>which will give you a list of the value names and values in sqlRegPath.</p> <p><strong>Note:</strong> You can access the <strong>default</strong> value of a key (displayed by the commandline tool <code>REGEDT32.EXE</code> as <code>(Default)</code>) if you omit the <code>ValueName</code> parameter in the corresponding functions above.</p> <p>To get a list of <strong>SubKeys</strong> within a registry key, use the function <code>GetRegKeyNames</code>or <code>GetAllRegKeyNames</code>. You can use this list to traverse further keys in the registry.</p> <p>For example</p> <pre><code>var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion"; var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall"; var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath); </code></pre> <p>will get all 32 bit and 64 bit uninstall keys.</p> <p><strong>Notice the null handling</strong> required in the functions because SQL server can be installed as 32 bit or as 64 bit. The functions are overloaded so you can still pass the 32 bit or 64 bit parameter if required - however, if you omit it then it will try to read 64 bit, if that fails (null value), it reads the 32 bit values. </p> <p>There is one speciality here: Because <strong><code>GetAllRegValueNames</code></strong> is usually used in a loop context (see example above), it returns an empty enumerable rather than <code>null</code> to simplify <code>foreach</code> loops: if it wouldn't be handled that way, the loop would have to be prefixed by an <code>if</code> statement checking for <code>null</code> which would be cumbersome having to do that - so that is dealt with once in the function.</p> <p><strong>Why bothering about null?</strong> Because if you don't care, you'll have a lot more headaches finding out why that null reference exception was thrown in your code - you'd spend a lot of time finding out where and why it happened. And if it happened in production you'll be very busy studying log files or event logs (I hope you have logging implemented) ... better avoid null issues where you can in a defensive way. The operators <code>?.</code>, <code>?[</code>...<code>]</code> and <code>??</code> can help you a lot (see the code provided above). There is a nice related article discussing the new <a href="https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/" rel="nofollow noreferrer">nullable reference types in C#</a>, which I recommend to read and also <a href="https://blogs.msdn.microsoft.com/jerrynixon/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator/" rel="nofollow noreferrer">this one</a> about the Elvis operator.</p> <hr> <p><strong>Hint:</strong> You can use the free edition of <strong><a href="https://www.linqpad.net/" rel="nofollow noreferrer">Linqpad</a></strong> to test all examples under Windows. It doesn't require an installation. Don't forget to press <kbd>F4</kbd> and enter <code>Microsoft.Win32</code> in the Namespace import tab. In Visual Studio, you require <code>using Microsoft.Win32;</code> at the top of your code.</p> <p><strong>Tip:</strong> To familiarize yourself with the new <strong><a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators" rel="nofollow noreferrer">null handling operators</a>,</strong> try out (and debug) the following code in LinqPad:</p> <pre><code>string[] test { get { return null;} } // property used to return null void Main() { test.Dump(); // output: null // "elvis" operator: test?.Dump(); // output: // "elvis" operator for arrays test?[0].Dump(); // output: (test?[0]).Dump(); // output: null // combined with null coalescing operator (brackets required): (test?[0]??"&lt;null&gt;").Dump(); // output: "&lt;null&gt;" } </code></pre> <p>If you're interested, <strong><a href="https://stackoverflow.com/questions/3555317/linqpad-extension-methods/12006038#12006038">here</a></strong> are some examples I put together showing what else you can do with the tool.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload