Access remote registry key with C# in .Net MVC2 - c#

I'm using the following code
private static string GetLogonFromMachine(string machine)
{
//1. To read the registry key that stores this value.
//HKEY_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\DefaultUserName
var rHive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine);
var rKey = rHive.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\WinLogon");
var rItem = rKey.GetValue("DefaultUserName");
return rItem.ToString();
}
and I've confirmed that my user has access, the MVC site is using integrated authentication and that the listed REG_SZ "DefaultUserName" has a value on the machine targetted but rItem doesn't grab a value.
I guess I'm doing something silly and I'd love to know what!

I was indeed being silly. I wasn't sorting the list of machine names before use and so I was looking at the registry of the wrong machine. The machine that was actually in focus was correctly returning "".
I've ended up with
private static string GetLogonFromMachine(string machine)
{
//1. To read the registry key that stores this value.
//HKEY_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\DefaultUserName
RegistryKey rHive;
try
{
rHive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine);
}
catch (IOException)
{
return "offline";
}
var rKey = rHive.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\\");
if (rKey == null)
{
return "No Logon Found";
}
var rItem = rKey.GetValue("DefaultUserName");
return rItem==null ? "No Logon Found" : rItem.ToString();
}

Related

Reading registry value crashes

My below code fails no matter if I run it as Administrator or not:
var suff = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\CCM\\LocationServices", true);
var value = suff.GetValue("DnsSuffix").ToString();
I get this error message which I can't decode:
An unhandled exception of type 'System.NullReferenceException' occurred in MyApp.exe Additional information: Object reference not set to an instance of an object.
I know for a fact that the value exists and it contains data as well.
*Edit: So like I said it shouldn't be null as the data exists. And if it is null then I will need to know why is it null. Therefore, a question regarding what is System.NullReferenceException won't help me at all.
As raj's answer pointed out in this SO question, which is similar to yours, the problem could be that you're opening the registry on a 64bits OS.
Try this approach instead (.NET 4.0 or later) :
public class HKLMRegistryHelper
{
public static RegistryKey GetRegistryKey()
{
return GetRegistryKey(null);
}
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);
}
public static object GetRegistryValue(string keyPath, string keyName)
{
RegistryKey registry = GetRegistryKey(keyPath);
return registry.GetValue(keyName);
}
}
... and replace your code with :
string keyPath = #"SOFTWARE\Microsoft\CCM\LocationServices";
string keyName = "DnsSuffix";
var value = HKLMRegistryHelper.GetRegistryValue(keyPath, keyName);
Reading the registry with "Registry.LocalMachine" can be unreliable as it defaults to the current application platform target (x86/x64) and when it's 64bit Registry.LocalMachine can view the key but can't access the data within.
Try specifying the view with RegistryKey.
var stuff = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey("Software\\Microsoft\\CCM\\LocationServices", true);
var value = stuff.GetValue("DnsSuffix").ToString();

Why is OpenSubKey() returning null on my Windows 10 64-bit system?

I'm developing x86 app to translate self-created "programming language" to assembler. At some point I need to get path to MASM32. I have read a couple of related topics, but they didn't help me, maybe because I'm new to C#.
MASM32 is situated here:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MASM32.
When I run my program, I always get "Masm32 is not found" message.
What should I do? Thanks in advance!
WindowsIdentity ident = WindowsIdentity.GetCurrent();
WindowsPrincipal myPrincipal = new WindowsPrincipal(ident);
if (!myPrincipal.IsInRole(WindowsBuiltInRole.Administrator))
{
string user = Environment.UserDomainName + "\\" + Environment.UserName;
RegistrySecurity rs = new RegistrySecurity();
rs.AddAccessRule(new RegistryAccessRule(user,
RegistryRights.ReadKey | RegistryRights.Delete | RegistryRights.CreateSubKey | RegistryRights.WriteKey | RegistryRights.ChangePermissions | RegistryRights.SetValue,
InheritanceFlags.None,
PropagationFlags.None,
AccessControlType.Deny));
}
try
{
RegistryKey baseKey = RegistryKey.OpenBaseKey(
RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey key = baseKey.OpenSubKey(#"SOFTWARE\Wow6432Node\");
PathMasm32 = baseKey.GetValue("MASM32").ToString();
}
catch {
erTxt = "Masm32 is not found";
}
It is probably not OpenSubKey() that is causing the null reference exception, but the baseKey.GetValue().ToString() call. The baseKey.GetValue() returns null (because in that case you are trying to get a value right under the HKEY_LOCAL_MACHINE root node) and you invoke ToString() on a null reference. Instead of baseKey.GetValue(), you should try key.GetValue(), assuming MASM32 is really a value under HKLM\SOFTWARE\Wow6432Node which is highly unlikely.
key.GetValue("MASM32").ToString();
Security Note: If you are looking for the installation path of MASM32, even though I do not have any expertise on that, they clearly state that The MASM32 SDK is registry safe and writes nothing to the registry.
Thus, MASM32 is probably a KEY not a VALUE, therefore please execute this method and print the output of it, and you will see the key/value pairs registered under the MASM32 key assuming it exists at the registry path HKLM\SOFTWARE\Wow6432Node\MASM32
public static string GetMASM32LocationFromRegistry()
{
RegistryKey localMachineRegistryKey;
RegistryKey masm32RegistryKey;
RegistryView currentRegistryView = RegistryView.Registry64;
localMachineRegistryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, currentRegistryView);
masm32RegistryKey = localMachineRegistryKey.OpenSubKey(#"SOFTWARE\Wow6432Node\MASM32");
if (masm32RegistryKey == null)
{
return #"ERROR: The registry key HKLM\SOFTWARE\Wow6432Node\MASM32 could not be found";
}
StringBuilder masm32RegistryKeyValuesBuilder = new StringBuilder("Key/Value pairs for registry key HKLM\\SOFTWARE\\Wow6432Node\\MASM32:\r\n");
foreach (string masm32RegistryKeyValueName in masm32RegistryKey.GetValueNames())
{
masm32RegistryKeyValuesBuilder.AppendFormat
(
"Key: [{0}], Value: [{1}], Value Type: [{2}]\r\n",
masm32RegistryKeyValueName,
masm32RegistryKey.GetValue(masm32RegistryKeyValueName),
masm32RegistryKey.GetValueKind(masm32RegistryKeyValueName)
);
}
return masm32RegistryKeyValuesBuilder.ToString();
}

Find and Read registry key within CLR

I need to check the availability and also read some registry key by CLR(C#), registry keys already written by another application.
As a sample:
public bool IsKeyAvailable(string KeyID)
{
string keyToRead = #"Software\myRoot\myApp\" + KeyID;
using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(keyToRead, RegistryKeyPermissionCheck.ReadSubTree))
{
if (regKey == null)
return false;
return true;
}
}
Checking & reading code are working fine outside of the CLR, but within the CLR the same code doesn't working, Already signed the CLR and assembly created WITH PERMISSION_SET = UNSAFE.
What could be missed for this scenario to find and read my registry keys by CLR?
Use this code :
Registry.LocalMachine.OpenSubKey("SOFTWARE", true);
RegistryKey masterKey = Registry.LocalMachine.CreateSubKey("SOFTWARE\yourapp\yourkey");
string value = "";
if (masterKey != null)
{
value = masterKey.GetValue("yourvalue").ToString();
}
masterKey.Close();

how to spoof MAC address via code

I'm trying to spoof the MAC address of the computer that executes my program. Right now I'm getting the current MAC address of the machine using the 'getmac' command via cmd, then I want to change it via the 'RegistryKey' class(windows.system32).
The issue is that I don't know the string to pass to the OpenSubKey method.
For example this is the method to read the current MAC with registry key reading:
private string readMAC()
{
RegistryKey rkey;
string MAC;
rkey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\0012", true); //--->this is the string to change
MAC = (string)rkey.GetValue("NetworkAddress");
rkey.Close();
return MAC;
}
I got curious so I pulled the source for MadMACs. Turned out to be pretty straightforward to port the core logic to C#, so here it is if anyone is interested.
private const string baseReg =
#"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\";
public static bool SetMAC(string nicid, string newmac)
{
bool ret = false;
using (RegistryKey bkey = GetBaseKey())
using (RegistryKey key = bkey.OpenSubKey(baseReg + nicid))
{
if (key != null)
{
key.SetValue("NetworkAddress", newmac, RegistryValueKind.String);
ManagementObjectSearcher mos = new ManagementObjectSearcher(
new SelectQuery("SELECT * FROM Win32_NetworkAdapter WHERE Index = " + nicid));
foreach (ManagementObject o in mos.Get().OfType<ManagementObject>())
{
o.InvokeMethod("Disable", null);
o.InvokeMethod("Enable", null);
ret = true;
}
}
}
return ret;
}
public static IEnumerable<string> GetNicIds()
{
using (RegistryKey bkey = GetBaseKey())
using (RegistryKey key = bkey.OpenSubKey(baseReg))
{
if (key != null)
{
foreach (string name in key.GetSubKeyNames().Where(n => n != "Properties"))
{
using (RegistryKey sub = key.OpenSubKey(name))
{
if (sub != null)
{
object busType = sub.GetValue("BusType");
string busStr = busType != null ? busType.ToString() : string.Empty;
if (busStr != string.Empty)
{
yield return name;
}
}
}
}
}
}
}
public static RegistryKey GetBaseKey()
{
return RegistryKey.OpenBaseKey(
RegistryHive.LocalMachine,
InternalCheckIsWow64() ? RegistryView.Registry64 : RegistryView.Registry32);
}
For brevity's sake, I've left out the implementation of InternalCheckIsWow64(), but that can be found here. Without this, I was running into issues with not finding the registry I wanted due to structural differences between 32- and 64-bit OSes.
Obligatory disclaimer -- play with the registry at your own peril.
This should point you in the right direction, but you're going to have to figure out the code:
look in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\ and you'll see a few sub keys corresponding to the interfaces in the "network connections" control panel. Probably only one will have a valid IP, and the others will have 0.0.0.0 You'll need to do some pattern matching to figure out which one is the right one.
get the key name for the interface (it's a GUID, or at least looks like one), and go back to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} and check each one's NetCfgInstanceId value (or search) for the GUID of the interface.
Windows 10
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class{4d36e972-e325-11ce-bfc1-08002be10318}\0004\NetworkAddress

Getting location of file tnsnames.ora by code

How can I get the location of the tnsnames.ora file by code, in a machine with the Oracle client installed?
Is there a windows registry key indicating the location of this file?
Some years ago I had the same problem.
Back then I had to support Oracle 9 and 10 so the code only takes care of those versions, but maybe it saves you from some research.
The idea is to:
search the registry to determine the oracle client version
try to find the ORACLE_HOME
finally get the tnsnames from HOME
public enum OracleVersion
{
Oracle9,
Oracle10,
Oracle0
};
private OracleVersion GetOracleVersion()
{
RegistryKey rgkLM = Registry.LocalMachine;
RegistryKey rgkAllHome = rgkLM.OpenSubKey(#"SOFTWARE\ORACLE\ALL_HOMES");
/*
* 10g Installationen don't have an ALL_HOMES key
* Try to find HOME at SOFTWARE\ORACLE\
* 10g homes start with KEY_
*/
string[] okeys = rgkLM.OpenSubKey(#"SOFTWARE\ORACLE").GetSubKeyNames();
foreach (string okey in okeys)
{
if (okey.StartsWith("KEY_"))
return OracleVersion.Oracle10;
}
if (rgkAllHome != null)
{
string strLastHome = "";
object objLastHome = rgkAllHome.GetValue("LAST_HOME");
strLastHome = objLastHome.ToString();
RegistryKey rgkActualHome = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\ORACLE\HOME" + strLastHome);
string strOraHome = "";
object objOraHome = rgkActualHome.GetValue("ORACLE_HOME");
string strOracleHome = strOraHome = objOraHome.ToString();
return OracleVersion.Oracle9;
}
return OracleVersion.Oracle0;
}
private string GetOracleHome()
{
RegistryKey rgkLM = Registry.LocalMachine;
RegistryKey rgkAllHome = rgkLM.OpenSubKey(#"SOFTWARE\ORACLE\ALL_HOMES");
OracleVersion ov = this.GetOracleVersion();
switch(ov)
{
case OracleVersion.Oracle10:
{
string[] okeys = rgkLM.OpenSubKey(#"SOFTWARE\ORACLE").GetSubKeyNames();
foreach (string okey in okeys)
{
if (okey.StartsWith("KEY_"))
{
return rgkLM.OpenSubKey(#"SOFTWARE\ORACLE\" + okey).GetValue("ORACLE_HOME") as string;
}
}
throw new Exception("No Oracle Home found");
}
case OracleVersion.Oracle9:
{
string strLastHome = "";
object objLastHome = rgkAllHome.GetValue("LAST_HOME");
strLastHome = objLastHome.ToString();
RegistryKey rgkActualHome = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\ORACLE\HOME" + strLastHome);
string strOraHome = "";
object objOraHome = rgkActualHome.GetValue("ORACLE_HOME");
string strOracleHome = strOraHome = objOraHome.ToString();
return strOraHome;
}
default:
{
throw new Exception("No supported Oracle Installation found");
}
}
}
public string GetTNSNAMESORAFilePath()
{
string strOracleHome = GetOracleHome();
if (strOracleHome != "")
{
string strTNSNAMESORAFilePath = strOracleHome + #"\NETWORK\ADMIN\TNSNAMES.ORA";
if (File.Exists(strTNSNAMESORAFilePath))
{
return strTNSNAMESORAFilePath;
}
else
{
strTNSNAMESORAFilePath = strOracleHome + #"\NET80\ADMIN\TNSNAMES.ORA";
if (File.Exists(strTNSNAMESORAFilePath))
{
return strTNSNAMESORAFilePath;
}
else
{
throw new SystemException("Could not find tnsnames.ora");
}
}
}
else
{
throw new SystemException("Could not determine ORAHOME");
}
}
On Windows, the most likely locations are either %ORACLE_HOME%/network/admin or %TNS_ADMIN% (or the TNS_ADMIN registry setting). These two cover almost every installation.
Of course it is possible to have a working Oracle client without this file. Oracle has bewildering array of networking options, and there are plenty of ways to achieve a working setup with using TNSNAMES. Depending on what you are trying to achieve here, your first port of call might be the sqlnet.ora file, which is also found in %ORACLE_HOME%/network/admin. This should contain a line that looks something like this:
NAMES.DIRECTORY_PATH= (LDAP, TNSNAMES, HOSTNAME)
TNSNAMES means it will use the TNSNAMES.ora file (second in this case). LDAP and HOSTNAME are alternate ways of resolving the database. If there is no TNSNAMES the TNSNAMES.ora file will be ignored if it exists in the right place.
In C# / .NET this should get you the environment variables:
Environment.GetEnvironmentVariable("ORACLE_HOME");
Environment.GetEnvironmentVariable("TNS_ADMIN");
List<string> logicalDrives = Directory.GetLogicalDrives().ToList();
List<string> result = new List<string>();
foreach (string drive in logicalDrives)
{
Console.WriteLine("Searching " + drive);
DriveInfo di = new DriveInfo(drive);
if(di.IsReady)
result = Directory.GetFiles(drive, "tnsnames.ora", SearchOption.AllDirectories).ToList();
if (0 < result.Count) return;
}
foreach (string file in result) { Console.WriteLine(result); }
According to the net that depends on the version of Oracle and the working directory of the SQL*Plus process. This first link tells you the environment variable that specifies the base path for some versions (7, 8, 9i) of Oracle. If you use a different one, I'm sure there's a similar way to get to the system directory.
If you spread versions of these files all over the place though and rely on the "look for a local tnsnames.ora first" behaviour of the client, then I guess you're out of luck.
I'm not a C# or a Windows guy for that matter so hopefully this helps. The tnsnames.ora file should be located in:
ORACLE_HOME\network\admin
If an alternate location has been specified, it should be available via the TNS_ADMIN registry key.
See this link for more information on how Oracle handles tns names on Windows.

Categories