I am not able to retrieve a software's Installdir. I have tried GetValue and even OpenSubKey but everytime I get a NULL. I am using VS2008, .Net 3.5, 64bit machine, 32bit process setting.
private string GetInstallPath()
{
string keyValue = string.Empty;
Object key = Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\My Company\\My Tool", "Installdir", null);
...
}
key is returning NULL though there is a valid string there. Equivalent code works in VC++. Please provide your insight to the issue. What am I doing wrong for this supposedly easy task? I cannot use a 'Hive' as it's 4.0 standard. Code level help instead of links would be helpful.
VC++ equivalent
HKEY hkey = NULL;
LSTATUS status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\My Company\\My Tool\\", 0, KEY_READ, &hkey );
if ( status == ERROR_SUCCESS )
{
DWORD type;
char buff[ 100 ];
DWORD numBytes = sizeof( buff );
if ( RegQueryValueExA( hkey, REGISTRY_ENTRY, NULL, &type, (LPBYTE) buff, &numBytes ) == ERROR_SUCCESS )
{
...
}
You mentioned your machine is x64, and your app is 32 bit unless I misread. Given your environment the firs thing I would check is to be sure the key exists in the 64 bit node, HKCU\Software\My Company\... and not in the 32 bit node HKCU\Software\Wow6432Node\My Company\..., if your key exists in the 32 bit node, you will need to make sure your app is a 32 bit app, otherwise, you will need to make sure your app is 64 bit or you won't find the key.
The following code worked for me, running in 64 bit and found the key outside of the Wow6432Node. I don't understand why you can't user 'Hive', it works in both 3.5 and 4.0
RegistryKey regKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\VisualStudio\\10.0");
if (regKey != null)
{
object val = regKey.GetValue("FullScreen");
}
Update:
The following also worked for me, running .NET 3.5, if it's not a platform (x86 vs x64) issue, then it is possibly a permissions problem, make sure that the context under which your app is running has access to the registry key (try running the app as administrator or even system)
object test = Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\VisualStudio\\10.0", "FullScreen", null);
Related
I'm trying to fetch some data on the Office Click-To-Run currently installed.
I've read these posts : Can't Read Registry Key or OpenSubKey() returns null for a registry key that I can see in regedit.exe
I'm on Windows 10 64bit. My application is an Outlook add-in, so I can't change the target platform (32/64bit), it's the Host that determine if I'm running in 32bit or 64bit. So I've to handle both cases.
So I've this (test) code :
using (var hklmTest64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
var test = hklmTest64.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
if (test == null)
{
using (var hklmTest32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
{
test = hklmTest32.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
}
}
}
So I first fetch the registry key using the 64bit view, then if null I retry using the 32bit view.
Problem: test is always NULL.
Of course the key exists and I can see it using regedit:
Of course I first tried simple code that until now always worked for me, but doesn't work to fetch this key:
test = Registry.LocalMachine.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
test = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration", "AudienceData", null);
And more strange thing, it's that I had exactly the same problem for fetching the windows build number. This code was not working :
var wBuild = Registry.LocalMachine.GetValue(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId");
But this one works perfectly for windows build (not for outlook key):
var wBuild = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", null);
Any idea how to fetch this registry key ?
UPDATE 1
See the post C# get Office ClickToRun Registry Key returns null
But reading the post, my code using RegistryView.RegistryXX should work...
UPDATE 2
I've reprod the problem using LinqPad, so this is not due to the Outlook host / add-in. I tried to reprod in a .NET Fiddle but indeed the code is not allowed to access the registry :)
I can get the correct values using P/Invoke like explained in this article. So for me it's clearly a 32/64bit (wow6432node) problem.
you dont need
RegistryKey.OpenBaseKey
just use Registry.GetValue(keyName, valueName, defualt value)
this is working example
string InstallPath = (string)Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\" + path, "ActivationCode", null);
I can get the correct values using P/Invoke like explained in this article. So for me it's clearly a 32/64bit (wow6432node) problem.
I need to retrieve a string from the registry in 32/64 bit windows computers.
I have successfully retrieved info with registry.getvalue in a 64 bit environment, but it returns null in a 32 bit environment.
RegistryKey localKey;
localKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default);
string value = localKey.OpenSubKey(#"Software\MCS").GetValue("path").ToString();
if (value != null)
{
EventLog.WriteEntry("SMS_Service", "Path:" + value);
}
else
{
EventLog.WriteEntry("SMS_Service", "Registry path not found.");
}
Reg query Verification
event viewer
Everything checks out as far as I can tell. I feel like it has to be some kind of permission problem with the registry on the 32 bit machine.
I'm finding that when pinvoking GetBinaryType from managed code, I'm getting the opposite result of calling GetBinaryType from native code on the same machine.
I've borrowed the marshalling declaration from elsewhere:
public enum BinaryType : uint
{
SCS_32BIT_BINARY = 0, // A 32-bit Windows-based application
SCS_64BIT_BINARY = 6, // A 64-bit Windows-based application.
SCS_DOS_BINARY = 1, // An MS-DOS – based application
SCS_OS216_BINARY = 5, // A 16-bit OS/2-based application
SCS_PIF_BINARY = 3, // A PIF file that executes an MS-DOS – based application
SCS_POSIX_BINARY = 4, // A POSIX – based application
SCS_WOW_BINARY = 2 // A 16-bit Windows-based application
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetBinaryType(
string lpApplicationName,
out BinaryType dwBinType
);
and then call the function as
bool is64bit = false;
BinaryType binType = BinaryType.SCS_32BIT_BINARY;
// Figure out if it's 32-bit or 64-bit binary
if (GetBinaryType(phpPath, out binType) &&
binType == BinaryType.SCS_64BIT_BINARY)
{
is64bit = true;
}
For 32-bit native binaries, GetBinaryType returns BinaryType.SCS_64BIT_BINARY (6), and for 64-bit native binaries, returns BinaryType.SCS_32BIT_BINARY (0).
To verify, I wrote a native command line tool, and ran it against the same binaries.
PCWSTR rgBinTypes[] = {
L"SCS_32BIT_BINARY", // 0
L"SCS_DOS_BINARY", // 1
L"SCS_WOW_BINARY", // 2
L"SCS_PIF_BINARY", // 3
L"SCS_POSIX_BINARY", // 4
L"SCS_OS216_BINARY", // 5
L"SCS_64BIT_BINARY", // 6
};
int _tmain(int argc, _TCHAR* argv[])
{
DWORD binType;
if (argc < 2)
{
wprintf(L"Usage: %S <binary-path>\n", argv[0]);
goto Cleanup;
}
if (!GetBinaryType(argv[1], &binType))
{
wprintf(L"Error: GetBinaryType failed: %d\n", GetLastError());
goto Cleanup;
}
wprintf(L"Binary type: %d (%s)\n", binType, binType < 7 ? rgBinTypes[binType] : L"<unknown>");
Cleanup:
return 0;
}
The command line tool correctly returns 0 (SCS_32BIT_BINARY) for 32-bit native binaries, and 6 (SCS_64BIT_BINARY) for 64-bit native binaries.
I found one reference to someone else having this same issue, but no answer was provided: https://social.msdn.microsoft.com/Forums/en-US/fc4c1cb4-399a-4636-b3c3-a3b48f0415f8/strange-behavior-of-getbinarytype-in-64bit-windows-server-2008?forum=netfx64bit
Has anyone else run into this issue?
I realize I could just flip the definitions in my Managed enum, but that seems awfully kludgy.
This is a WinAPI bug/developer's oversight. You may find this related question useful to read, and it's top answer may help you find the appropriate workaround,
Use a separate 64 bit process, and some IPC, to retrieve the information.
Use WMI to get the module file name.
Use QueryFullProcessImageName.
I ended up going for a completely different workaround. This answer about PE headers mentions the PE headers among 32 and 64 bit Windows executables. You can completely circumvent the WinAPI checking, and have your target executable checked via reading it in the Binary mode and checking if it matches the PE signature.
Sadly, there isn't much info on the problem online. I remember seeing this problem on some forum, where is was clearly listed as bug, but this was about ~10 years ago. I hope as we discuss this problem, more people become aware of it.
This question already has answers here:
64 bit & 32 bit Registry issue in Windows (Programming in c#)
(2 answers)
Closed 8 years ago.
I'm having hard time with access the registry in my program (C#), here is the details :
My program run on 32 bit & 64 bit OS.
My program will need to get registry keys of software that some has 64 version and some not.
For example:
I'm running a 64 bit OS and i need to read 2 registry keys so i can know the install locations of the 2 different software, one has a 64 bit version so i don't need the "\Wow64node\" and one have only has 32 bit version so i will need the "\Wow64node\"
// 1.MSE: (64 bit version)
string installPath = (string)Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Antimalware", "InstallLocation", null);
if (installPath != null)
{
listViewAV.Items.Add("MSE");
}
// 2.Avast: (32 bit version)
installPath = (string)Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\AVAST Software\Avast", "ProgramFolder", null);
if (installPath != null)
{
listViewAV.Items.Add("Avast");
}
Notice that the Avast is in the Wow Node and MSE isnt, but if my program will be running on a 32 bit OS they both be without the Wow Node.
How can i write this code so it works on every scenario?
Scenario 1 : running on a 32 bit machine so all the softwares will be 32 bit as well(no "Wow64node").
Scenario 2 : running on a 64 bit machine so some of the softwares will be 32 bit and some and some 64 bit(need to handle with "Wow64node")
Please write a detailed answer(prefer with a code example).
Thank you
This is essentially the same question as you asked earlier today, and that I answered. I won't repeat my answer. What you are asking for is some code. I can give you that, but I fear that you still don't really understand the registry redirector. I think you are going to have to get on top of that before you can expect to make any progress.
To read a value from the 32 bit view of the registry, for instance Avast, use this code:
RegistryKey rk = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry32);
rk = rk.OpenSubKey(#"SOFTWARE\AVAST Software\Avast");
string installPath = null;
if (rk != null)
{
installPath = rk.GetValue("ProgramFolder", null);
}
if (installPath != null)
{
.... // Avast registry setting found
}
For a program registered in the 64 bit view of the registry, for instance MSE, do it like this:
RegistryKey rk = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
rk = rk.OpenSubKey(#"SOFTWARE\Microsoft\Microsoft Antimalware");
string installPath = null;
if (rk != null)
{
installPath = rk.GetValue("InstallLocation", null);
}
if (installPath != null)
{
.... // Avast registry setting found
}
You don't need to worry about whether or not you are running on a 32 bit or 64 bit system. On a 64 bit system, both views exist, and you get the view that you request. On a 32 bit system, only the 32 bit view exists, and the value of the RegistryView enumeration that you pass is ignored. The documentation says it like this:
If you request a 64-bit view on a 32-bit operating system, the returned keys will be in the 32-bit view.
So I'm creating an installer for the Java Access Bridge for my application and it is required to find the Java installation directory. I was using this piece of code which worked..
public static string GetJavaInstallationPath()
{
try
{
string environmentPath = Environment.GetEnvironmentVariable("JAVA_HOME");
if (!string.IsNullOrEmpty(environmentPath))
{
return environmentPath;
}
string javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
using (Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(javaKey))
{
string currentVersion = rk.GetValue("CurrentVersion").ToString();
using (Microsoft.Win32.RegistryKey key = rk.OpenSubKey(currentVersion))
{
return key.GetValue("JavaHome").ToString();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return null;
}
}
until.. I ran a clean Windows 7 64 bit install on my Virtual Machine and installed Java from java.com. It installed the 32 bit version of Java by default but I really thought it wouldn't matter because 32 bit would also require or the JAVA_HOME variable or the Registry Key. Well, this wasn't the case! There was no Registry Key, no entry in the PATH variable and there was no JAVA_HOME variable either. So this code wouldn't work! My question is, how would I detect the java installation directory even when it's the 32 bit Java version that's installed. There is nothing I know of that I can use..
You're forgetting about the registry path being different for 32bit application. See this MS article: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072%28v=vs.85%29.aspx