I'm finishing a application in C# which contains a SQL Server database.
How can I check if the user has SQL Server 2012 Express Local DB installed?
Is it possible to check via registry both on x86, x64?
Basically the idea is if the user does not have SQL Server installed, the application advise to install it.
As the installer I'm working for setup does not have dependencies for SQL Server 2012 Express Local DB.
Thanks.
You'll have to loop through the Uninstall GUIDs and find one that starts with keyword "Microsoft SQL Server 2012". You can find it by going to Control Panel > Programs and Features > and look at the "Display Name" column.
//HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall{guidVariable}\DisplayName
.. should match the "Microsoft SQL Server 2012*" wild card.
I don't have the exact code, but this should get you started. Just loop through all children of the "Uninstall" key, and then find the "DisplayName" key by getting the value. The "GUID" variable below should be your iterator, since you do not know that value. I'm sure you can get a list of all of the GUID values that are sub keys of "Uninstall" key.
string UninstallRegKeyPath = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
Guid UninstallGuid = new Guid(GUID);
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(UninstallRegKeyPath, true))
{
if (key == null)
{
return;
}
try
{
string guidText = UninstallGuid.ToString("B");
RegistryKey child = key.OpenSubKey(guidText);
if (child != null)
{
string displayName = child.GetValue("DisplayName").ToString();
if (displayName.Contains("Microsoft SQL Server 2012"))
{
// implement logic when MSSQL 2012 is found
}
child.Close();
}
}
}
Just be cautious. There are both 32 bit installations and 64 bit installations. Wow6432Node contains the 32 bit programs I believe, so everything installed in C:\Program Files (x86)\ by default (but may be anywhere). And there is the other location, which I'll let you find, for all of the 64 bit programs, which are installed in C:\Program Files\ by default (and again may be installed anywhere).
EDIT:
Try this. You may also want to replace "LocalMachine" with "CurrentUser" since many installers let you configure them for your user, or all users.
using (RegistryKey root = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"))
{
string searchKey = #"Microsoft SQL Server 2012";
string subKeyName = "DisplayName";
foreach (string keyname in root.GetSubKeyNames())
{
//Console.WriteLine(keyname);
using (RegistryKey key = root.OpenSubKey(keyname))
{
try // in case "DisplayName doesn't exist
{
string displayName = key.GetValue(subKeyName).ToString();
if (displayName.StartsWith(searchKey))
Console.WriteLine("GUID: " + keyname + Environment.NewLine + displayName + Environment.NewLine);
}
catch
{
}
}
}
}
Console.ReadLine();
Related
I use this code to get the installed .NET Version on a remote machine. With Windows 7 it works perfect but with Windows 10 the following exception throws
System.Security.SecurityException: Requested registry access is not allowed.
The user with i connect, is in the Administrators Group
The Service "RemoteRegistry" is set to Startup type "Manual"
Code example
using (RegistryKey remoteHklm = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, hostName))
{
using (RegistryKey serviceKey = remoteHklm.OpenSubKey(#"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", true))
{
if (serviceKey != null)
{
version = serviceKey.GetValue("Version").ToString();
}
else
{
version = "error on get version from registry";
}
}
}
You have with Windows 10 no write Access to this registry key. Change the second OpenSubKey parameter to false, you can check in Registry Editor the permission of the key.
using (RegistryKey serviceKey = remoteHklm.OpenSubKey(#"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full", false))
I am reading the path for the latest version of Word installed from the registry, however even though the key exists, it does not return the path.
private string GetWordInstallPath()
{
int[] versions = new int[]
{
16, // 2016
15, // 2013
14, // 2010
12, // 2007
11, // 2003
10, // XP
9, // 2000
8, // 98
7 // 97
};
string path = "";
string hklm = #"SOFTWARE\Microsoft\Office\{0}.0\Word\InstallRoot";
foreach (int ver in versions)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey(string.Format(hklm, ver), false);
if (key != null)
{
path = key.GetValue("Path", "").ToString();
key.Close();
break;
}
}
return path;
}
}
In my case, I have Office 2016 installed, and I do not have Office 2013 installed, however the above method returns :
C:\Program Files\Microsoft Office 15\root\Office 15\
As you can see here, there is no such entry for SOFTWARE\Microsoft\Office\15.0\Word\InstallRoot, however there is a path for Office 2016.
Why is 'key' null when reading the path for 16, but returns a path for a non-existent installation in a folder that doesn't even exist on my system. The expected result from the above code is to loop through the values in versions checking for the subkey InstallPath for word, and on the first match, return the path for that version as it would be the most current version of word installed.
That's kind of impossible to do when it is pulling values for non-existent installs and NOT returning the existing install. This also needs to be done without using Interop.
The method above is from mangling together bits and pieces from here, here, here, and to detect that any version is installed I used code from here (as follows fyi)
private bool IsWordInstalled()
{
Type officeType = Type.GetTypeFromProgID("Word.Application");
return (officeType == null) ? false : true;
}
If using the default compile mode or 32 bit compile mode, the application will automatically try and grab any registry data from SOFTWARE\WoW6432Node\* instead of the specified path SOFTWARE\*. In this case, it worked as follows:
32 bit compile/debug
SOFTWARE\Microsoft\Office\16.0\Word\InstallRoot
was automatically translated in the background to
SOFTWARE\WoW6432Node\Microsoft\Office\16.0\Word\InstallRoot
since there was no 64 bit application entries in the subkey inside WoW6432Node, key returned null as it did not exist.
64 bit compile/debug
SOFTWARE\Microsoft\Office\16.0\Word\InstallRoot
reads the correct key from the exact path as specified.
It is important to note, that the translation of the registry path happens silently, without any error, and does not prompt the user or mention the adjustment in the debug logs.
Also, any application compiled with a 'preference' to 32 bit, even if it is a hybrid compile, will still silently translate the key by inserting WoW6432Node into it.
A 64 bit application will read the registry keys as is without modification and as such can read both the WoW6432Node entries as well as the normal ones.
I have written a code that can create ODBC DSN Connections remotely. I am able to add registry entries to ODBC.INI. The connections show up in The ODBC Data Source Administrator.
What I am struggling with is that when I choose SQL Server authentication using a login ID and password entered by the user. By default it takes up the user which runs the program while I want it to be decided by the user while running the code. All other entries are entered by the user.
How should I go about achieving this? I tried adding attributes to the registry entries, but that did not seem to work.
This is a section of my code that basically adds the registry key.
string reg_location = "SOFTWARE\\ODBC\\ODBC.INI";
dsn_name = reg_location + "\\" + dsn_name;
RegistryKey Key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, destination_server).CreateSubKey(dsn_name);
using (Key)
{
Key.SetValue("Database", database);
Key.SetValue("Description", description);
Key.SetValue("Driver", driver);
Key.SetValue("Server", server);
if (trusted_connection.ToLower().Equals("yes") || trusted_connection.ToLower().Equals("true") || trusted_connection.ToLower().Equals("sspi"))
Key.SetValue("Trusted_Connection", trusted_connection);
else if (trusted_connection.ToLower().Equals("false") || trusted_connection.ToLower().Equals("no"))
{
Key.SetValue("User Id", ss_username.Text);
Key.SetValue("Password ", ss_password.Text);
}
Key.SetValue("LastUser", System.Security.Principal.WindowsIdentity.GetCurrent().Name);
}
I want to modify a data in registry path SOFTWARE\Wow6432Node\Program\SubProgram using C# code in windows 7. I am able to read the value but I can't write into Registry.
Here is the code:
RegistryKey SUBKEY;
RegistryKey TAWKAY = RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, "");
string subkey = "SOFTWARE\\Wow6432Node\\Program\\SubProgram ";
if (TAWKAY.OpenSubKey(subkey) != null) // Get values from Registry
{
TAWKAY = RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, "");
SUBKEY = TAWKAY.OpenSubKey(subkey); // subkey opens
SUBKEY = TAWKAY.OpenSubKey(subkey,true); // subkey not open shows error Requested registry access is not allowed
SUBKEY.SetValue("Some name", "1234567890");
Console.WriteLine(SUBKEY.GetValue("Some name").ToString());
}
else
{
Console.WriteLine("Cannot open registry");
}
Console.Read();
If I set OpenSubKey(subkey, true), it shows an error message Requested registry access is not allowed
Is there any permission needed to write into registry?
Please help me to solve the issue
Wow6432Node is not a real path in the registry. It is an alias for 32 bit keys in 64 bit OS.
You must use RegistryView.Registry32 in order to specify you want to work with 32 bits.
RegistryKey reg32key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
RegistryKey reg_32bit_AppKey = reg32key.OpenSubKey(#"SOFTWARE\Program\SubProgram");
if (reg_32bit_AppKey != null)
{
// Here you can work with "SOFTWARE\\Wow6432Node\\Program\\SubProgram "
}
Modifying/deleting/adding keys in HKLM requires administrator rights.
In that case you want to do that you will need to change your applications manifest requestedExecutionLevel value to requireAdministrator
It is better to use "Reg" command inorder to perform any operation on registry.
Even though if you want to access the registry of remote machine you don't nedd credentials of that machine, having the machine name is sufficient.
For more information about "REG" command refer to the following link
http://technet.microsoft.com/en-us/library/cc732643(v=ws.10).aspx
I'd like to know where the installation path for an application is. I know it usually is in ...\Program Files... but I guess some people install it in different locations. I do know the name of the application.
Thank you.
The ideal way to find a program's installation path (on Windows) is to read it from the registry. Most installers will create a registry key for that program that contains the installation path. Exactly where this key is and what it will be named varies depending on the program in question.
To find if the program has a key in the registry, open 'regedit' and use the Edit > Find option to try and locate a key with the program name. If such a key exists, you can read it using the RegistryKey class in the .NET Framework library.
If the program does not have a registry key then another option is just to ask the user to locate the .exe file with the OpenFileDialog, although this is obviously not ideal.
Many (most?) programs create an App Paths registry key. Have a look at
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
If you know the application in question (as compared to any application) registry key is the probably the best option (if one exists).
The install might put in its own custom "install path key" somewhere (so do a find as Fara mentioned) or it might be in the uninstall section for installed programs, so you could check:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
But be aware that any new version of an install could change the key it writes out, both for a custom key or for the uninstall entry. So checking the registry should probably be only for a known install\version.
tep
Best way is to use Installer APIs to find the program location.
You can write a Managed wrapper over the APIs
Search for MsiGetProductInfo
Reference: http://msdn.microsoft.com/en-us/library/aa369558(VS.85).aspx
You can use MSI (I wrote a C# wrapper for it here https://github.com/alialavia/MSINet). Here is a simple example:
var location = "";
foreach (var p in InstalledProduct.Enumerate())
{
try
{
if (p.InstalledProductName.Contains("AppName"))
{
location = p.InstallLocation;
break;
}
}
catch { }
}
Take a look in the registry.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
or
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
Each of the above contain a list of sub-keys, one for each installed application (as it appears, for example, in the "Programs and Features" applet)
You can search for your application there, or if you know the product code, access it directly.
public string GetInstallPath(string applicationName)
{
var installPath = FindApplicationPath(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", applicationName);
if (installPath == null)
{
installPath = FindApplicationPath(#"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", applicationName);
}
return installPath;
}
private string FindApplicationPath(string keyPath, string applicationName)
{
var hklm = Registry.LocalMachine;
var uninstall = hklm.OpenSubKey(keyPath);
foreach (var productSubKey in uninstall.GetSubKeyNames())
{
var product = uninstall.OpenSubKey(productSubKey);
var displayName = product.GetValue("DisplayName");
if (displayName != null && displayName.ToString() == applicationName)
{
return product.GetValue("InstallLocation").ToString();
}
}
return null;
}