C# Registry key assignement is null - c#

I'm busy creating a little application for my self and others but I'm kinda stuck here.
I want to get a value of the register 'regedit' with an path. but the value 'RegistryKey' is always null even when I copy the path from the regedit is..
private bool HasKey
{
get
{
try
{
string path = #"Computer\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\0002";
using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(path, false))
{
if(key != null)
{
return true;
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
return false;
}
return false;
}
}
I only want to write a bool function that he has found the key.. but the variable 'key' is always null.

Try this
string path = #"\SYSTEM\ControlSet001\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\0002";
using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
using (var subKey = key.OpenSubKey(path, false))
{
if (subKey != null)
{
return true;
}
}
}

Related

Reading Registry DWORD

This code below checking if MySQL is installed works perfectly.
public bool MySql()
{
try
{
using (var key = Registry.CurrentUser.OpenSubKey("Software\\MySQL AB\\MySQL Server 5.6"))
{
var keyObject = key?.GetValue("installed");
var keyToString = keyObject?.ToString();
if (keyToString == "1")
return true;
}
return false;
}
catch (Exception)
{
return false;
}
}
However using the exact same code I try to see if OpenSSL is installed.
public bool OpenSsl()
{
try
{
using (var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1"))
{
var keyObject = key?.GetValue("NoModify");
var keyToString = keyObject?.ToString();
if (keyToString == "1")
return true;
}
return false;
}
catch (Exception)
{
return false;
}
}
Setting breakpoints in the code revealed that key is returning null. I'm not sure why. Yes the path is correct.
A 32-bit application on a 64-bit OS is routed to HKLM\Software\Wow6432Node. To read the 64-bit version of the key, we need to use the RegistryView
C# 4.0 code sample
public static RegistryKey GetRegistryKey(string keyPath)
{
RegistryKey localMachineRegistry
= RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
Environment.Is64BitOperatingSystem
? RegistryView.Registry64
: RegistryView.Registry32);
return string.IsNullOrEmpty(keyPath)
? localMachineRegistry
: localMachineRegistry.OpenSubKey(keyPath);
}
If your using .NET 3.5 or below p/invoke is the only solution.
http://www.rhyous.com/2011/01/24/how-read-the-64-bit-registry-from-a-32-bit-application-or-vice-versa/

C# code to change the default program attached with an extension using a custom progid with hash in windows 8

Purpose: Associate a new progid to an extension so that file will open with new associated program.
Programming Language: C#
Description:
I want to create a program to associate another program with an extension from my recommended program list. My program is working in windows-xp and windows-7 but it is not working in windows-8. when i searched for the issue, i found that in Windows-8 there is an additional key called "Hash".
I am not able to find the hash for my new progid.
Steps Being Followed:
Created a class say "MyTest.txt" in HKEY_CLASSES_ROOT eg: HKEY_CLASSES_ROOT MyTest.txt Shell Open Command (Default) "[PATH TO NOTEPAD] "%1""
I noticed that same key is also created in LOCAL_MACHINE folder
Now I want to assign this "MyTest.txt" ProgID to
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts.txt\UserChoice]
"Hash"="????"
"ProgId"="MyTest.txt"
But I am unable to find the Hash for my newly created ProgId "MyTest.txt" in C#.
Code Using C#:
public void changeExtensionDefaultProgram(string fileext,string operationmode, string oldkeyname, string fileopenerpath)
{
try
{
if (!string.IsNullOrEmpty(fileext))
{
//Global declaration for new custom key
string sCustomkeyName = string.Format("MYTest.{0}", fileext);
RegistryKey OurKey = Registry.LocalMachine;
RegistryKey ParentKey = Registry.LocalMachine;
RegistryKey GlobalLocalMachineKey = Registry.LocalMachine;
RegistryKey GlobalRootKey = Registry.ClassesRoot;
string keyToCopy = #"SOFTWARE\Classes";
ParentKey = ParentKey.OpenSubKey(keyToCopy, true);
string programopencommand = string.Format(#"SOFTWARE\Classes\{0}\Shell\{1}\Command", oldkeyname, operationmode);
OurKey = OurKey.OpenSubKey(programopencommand, true);
if (OurKey != null)
{
//check if backup exists then do not take backup, along with source key
string backupkeyName = string.Format("MyBKP{0}", fileext);
RegistryKey rBackupKeyName = GlobalRootKey.OpenSubKey(backupkeyName, true);
if (rBackupKeyName==null)
{
//backup the keys with a new name MyBKP{ext}
FileAssoc.CopyKey(GlobalRootKey, oldkeyname, backupkeyName);
MessageBox.Show(string.Format("Backup Done -- GlobalRootKey=> oldkeyname:{0} as newbackupname:{1}", oldkeyname, backupkeyName));
}
//check if MyTest.{ext} Custom Class for extension exists
RegistryKey rCustomkeyName = GlobalRootKey.OpenSubKey(sCustomkeyName, true);
if (rCustomkeyName == null)
{
//copy the keys with a new name MyTest.{ext}
FileAssoc.CopyKey(GlobalRootKey, oldkeyname, sCustomkeyName);
}
if (rBackupKeyName != null)
{
rBackupKeyName.Close();
}
if (rCustomkeyName != null)
{
rCustomkeyName.Close();
}
//Perform in localmachine
bool isFlagSet = setMicrosoftDefaultProgID(fileext, sCustomkeyName, fileopenerpath);
if (isFlagSet)
{
string newopencommand = string.Format(#"SOFTWARE\Classes\{0}\Shell\{1}\Command", sCustomkeyName, operationmode);
rCustomkeyName = GlobalLocalMachineKey.OpenSubKey(newopencommand, true);
if (rCustomkeyName != null)
{
rCustomkeyName.SetValue("", "\"" + fileopenerpath + "\"" + " \"%1\"");
MessageBox.Show(string.Format("going to set GlobalRootKey\\{0} with fileopenerpath:{1}", programopencommand, fileopenerpath));
rCustomkeyName.Close();
}
else
{
MessageBox.Show(string.Format("Failed to modify GlobalRootKey\\{0} with fileopenerpath:{1}", programopencommand, fileopenerpath));
}
}
}
};
}
catch (Exception ex)
{
MessageBox.Show("changeExtensionDefaultProgram()::Exception raised" + ex.ToString());
}
}
public bool setMicrosoftDefaultProgID(string fileextension, string keyname, string fileopenerpath)
{
try
{
RegistryKey OurKey = Registry.CurrentUser;
//HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice = MyTest.txt
string programopencommand = string.Format(#"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\{0}\UserChoice", fileextension);
try
{
cSecurityOwnerShip sec = new cSecurityOwnerShip();
string name = sec.UserName(cSecurity.EXTENDED_NAME_FORMAT.NameSamCompatible);
if (name == null)
{
name = sec.UserName();
}
string sKey = OurKey.ToString()+#"\" + programopencommand;
try
{
sec.ChangeMYKeyOwnership(sKey, cSecurityOwnerShip.SE_OBJECT_TYPE.SE_REGISTRY_KEY);
}
catch (Exception ex)
{
sec.ChangeMyKeyPermissions(cSecurityOwnerShip.ROOT_KEY.HKEY_CURRENT_USER, programopencommand, name, cSecurityOwnerShip.eRegAccess.Full_Control, cSecurityOwnerShip.eAccsType.Access_Allowed, cSecurityOwnerShip.eFlags.Inherit_Child);
}
RegistryKey NewSubKey = OurKey.CreateSubKey(programopencommand);
if (NewSubKey != null)
{
try
{
if (NewSubKey != null)
{
NewSubKey.SetValue("ProgID", keyname);
//NewSubKey.SetValue("Hash", "v8gh4ng+Pro=");
return true;
}
else
return false;
}
catch (Exception ex)
{
MessageBox.Show("setMicrosoftDefaultProgID()::SetValue() Exception raised" + ex.ToString());
return false;
}
}
else
{
MessageBox.Show(string.Format("setMicrosoftDefaultProgID()::programopencommand:{0} not exist", programopencommand));
return false;
}
}
catch (Exception ex)
{
MessageBox.Show(string.Format("setMicrosoftDefaultProgID()::Exception raised :{0}", ex.ToString()));
return false;
}
}
catch (Exception ex)
{
MessageBox.Show("setMicrosoftDefaultProgID()::Exception raised" + ex.ToString());
return false;
}
finally
{
}
}
Issue i am facing is in this commented line to find and change "Hash"
//NewSubKey.SetValue("Hash", "v8gh4ng+Pro=");
Windows 8 does not want random apps tampering with default application associations. Users and only users get to decide what application they choose for a file extension.
Don't do this. Let the user choose default application by opening "Default Programs" dialog from Control Panel.
If you're in a corporate environment and want to copy settings, you can export associations using group policies. See Windows 8: Associate a file Type or protocol with a specific app using GPO.

How do I retrieve the default icon for any given file type in Windows?

How do I get the icon that Windows uses by default for a specified file type?
Default icons for a file type irrespective of whether you happen to have one of these types of files handy, are defined in the Window's Registry under
HKEY_CLASSES_ROOT\ type \DefaultIcon(Default)
...but why tinker with that when there is a nice c# code sample here by VirtualBlackFox in his answer to How do I get common file type icons in C#?
Try this
public static Hashtable GetTypeAndIcon()
{
try
{
RegistryKey icoRoot = Registry.ClassesRoot;
string[] keyNames = icoRoot.GetSubKeyNames();
Hashtable iconsInfo = new Hashtable();
foreach (string keyName in keyNames)
{
if (String.IsNullOrEmpty(keyName)) continue;
int indexOfPoint = keyName.IndexOf(".");
if (indexOfPoint != 0) continue;
RegistryKey icoFileType = icoRoot.OpenSubKey(keyName);
if (icoFileType == null) continue;
object defaultValue = icoFileType.GetValue("");
if (defaultValue == null) continue;
string defaultIcon = defaultValue.ToString() + "\\DefaultIcon";
RegistryKey icoFileIcon = icoRoot.OpenSubKey(defaultIcon);
if (icoFileIcon != null)
{
object value = icoFileIcon.GetValue("");
if (value != null)
{
string fileParam = value.ToString().Replace("\"", "");
iconsInfo.Add(keyName, fileParam);
}
icoFileIcon.Close();
}
icoFileType.Close();
}
icoRoot.Close();
return iconsInfo;
}
catch (Exception exc)
{
throw exc;
}
}

Getting Registry Key Delete Permission

I am trying to have my program determine if it has permission to delete a registry key in C#. I have been trying this code which is returning true when in fact I don't have the right permissions for the registry key.
public static bool CanDeleteKey(RegistryKey key)
{
try
{
if (key.SubKeyCount > 0)
{
bool ret = false;
foreach (string subKey in key.GetSubKeyNames())
{
ret = CanDeleteKey(key.OpenSubKey(subKey));
if (!ret)
break;
}
return ret;
}
else
{
RegistryPermission r = new
RegistryPermission(RegistryPermissionAccess.AllAccess, key.ToString());
r.Demand();
return true;
}
}
catch (SecurityException)
{
return false;
}
}
The registry key that I am passing to this function is HKEY_CLASSES_ROOT\eHomeSchedulerService.TVThumbnailCache. It should be re-cursing to the sub key CLSID and returning false because the Full Control permission is only set for TrustedInstaller.
Here are the permissions for HKEY_CLASSES_ROOT\eHomeSchedulerService.TVThumbnailCache\CLSID from regedit:
I should note that I am running the code with Administrative privileges. Also, I know I can just use a try-catch block when I am deleting the registry key but I would like to know if I can delete it beforehand.
I was able to do some digging on Google and I came up with this code which seems to do the trick:
/// Checks if we have permission to delete a registry key
/// </summary>
/// <param name="key">Registry key</param>
/// <returns>True if we can delete it</returns>
public static bool CanDeleteKey(RegistryKey key)
{
try
{
if (key.SubKeyCount > 0)
{
bool ret = false;
foreach (string subKey in key.GetSubKeyNames())
{
ret = CanDeleteKey(key.OpenSubKey(subKey));
if (!ret)
break;
}
return ret;
}
else
{
System.Security.AccessControl.RegistrySecurity regSecurity = key.GetAccessControl();
foreach (System.Security.AccessControl.AuthorizationRule rule in regSecurity.GetAccessRules(true, false, typeof(System.Security.Principal.NTAccount)))
{
if ((System.Security.AccessControl.RegistryRights.Delete & ((System.Security.AccessControl.RegistryAccessRule)(rule)).RegistryRights) != System.Security.AccessControl.RegistryRights.Delete)
{
return false;
}
}
return true;
}
}
catch (SecurityException)
{
return false;
}
}
Having read permissions allows you to open the key. Try using:
key.DeleteSubKey(subkey)

Iterate through registry entries

As suggested here, I need to iterate through entries in
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
to find out the installed path of my application. How to iterate so that I can find out the
InstallLocation value given the DisplayName. How to do it efficiently in C#.
Below is code to achieve your goal:
using Microsoft.Win32;
class Program
{
static void Main(string[] args)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
foreach (var v in key.GetSubKeyNames())
{
Console.WriteLine(v);
RegistryKey productKey = key.OpenSubKey(v);
if (productKey != null)
{
foreach (var value in productKey.GetValueNames())
{
Console.WriteLine("\tValue:" + value);
// Check for the publisher to ensure it's our product
string keyValue = Convert.ToString(productKey.GetValue("Publisher"));
if (!keyValue.Equals("MyPublisherCompanyName", StringComparison.OrdinalIgnoreCase))
continue;
string productName = Convert.ToString(productKey.GetValue("DisplayName"));
if (!productName.Equals("MyProductName", StringComparison.OrdinalIgnoreCase))
return;
string uninstallPath = Convert.ToString(productKey.GetValue("InstallSource"));
// Do something with this valuable information
}
}
}
Console.ReadLine();
}
}
Edit: See this method for a more comprehensive way to find an Applications Install Path, it demonstrates the using disposing as suggested in the comments.
https://stackoverflow.com/a/26686738/495455
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Whater\The\Key"))
{
if (key != null)
{
foreach (string ValueOfName in key.GetValueNames())
{
try
{
bool Value = bool.Parse((string)key.GetValue(ValueOfName));
}
catch (Exception ex) {}
}
}
}
With a bool cast :D - so the string is expected to be True or False.
For the user registry hive use Registry.CurrentUser instead of Registry.LocalMachine

Categories