I tried this,this to uninstall the application programmatically. I am not getting any error or exception but the application is not uninstalled from my machine. Please see tried code also
public static string GetUninstallCommandFor(string productDisplayName)
{
RegistryKey localMachine = Registry.LocalMachine;
string productsRoot = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products";
RegistryKey products = localMachine.OpenSubKey(productsRoot);
string[] productFolders = products.GetSubKeyNames();
foreach (string p in productFolders)
{
RegistryKey installProperties = products.OpenSubKey(p + #"\InstallProperties");
if (installProperties != null)
{
string displayName = (string)installProperties.GetValue("DisplayName");
if ((displayName != null) && (displayName.Contains(productDisplayName)))
{
string uninstallCommand =(string)installProperties.GetValue("UninstallString");
return uninstallCommand;
}
}
}
return "";
}
Please help me to uninstall the application programmatically using C#.
The above routine will return a string, assuming it found a match that may look like:
MsiExec.exe /X{02DA0248-DB55-44A7-8DC6-DBA573AEEA94}
You need to take that and run it as a process:
System.Diagnostics.Process.Start(uninstallString);
Note that it may not be always msiexec, it can be anything that the program chooses to specify. In case of msiexec, you can append /q parameter to your uninstallString to make it uninstall silently (and it won't show those Repair/Remove dialogs).
Update: If you're using Windows installer 3.0 or above, you can also use /quiet for silent install/uninstall. It's basically same as /qn (if you're on older versions). Source. Thanks #JRO for bringing it up!
Related
I have a small subroutine to check for the existence of a required server program, as follows:
private bool IsProgramInstalled(string programDisplayName)
{
string logstr = string.Format("Checking install status of {0}....", programDisplayName);
RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Bridge Club Utilities");
foreach (string s in rk.GetSubKeyNames())
{
Console.WriteLine(s);
if (s != null)
{
if (s.Equals(programDisplayName))
{
AppendToLog(logstr + " INSTALLED");
return true;
}
}
}
AppendToLog(logstr + " NOT INSTALLED", Color.Red);
return false;
}
I have installed the program containing the above subroutine on many Windows boxes with no problems, but one customer receives an 'Unhandled Exception' error on program startup, as shown below:
When I loaded VS2022 on the customer's machine and ran it in debug mode, the exception appears on the line that sets RegistryKey rk, as shown below:
So I thought this user had maybe installed the required server program (BridgeComposer) in the wrong place, or the registry was screwed up somehow, or there was a permissions issue. I tried running my app in 'administrative mode', but this did not solve the problem.
Next, I tried to see if the user's PC had the same registry entries as my PC, and it appears that they do. If I manually navigate to 'Computer\HKEY_LOCAL_MACHINE\SOFTWARE\RegisteredApplications' on both machines, I see the same entry for 'BridgeComposer' as shown below:
Clearly I'm doing something wrong/stupid, but I have no clue what it is. Any pointers/clues would be appreciated.
Most likely your program is running as 32-bit on a 64-bit computer and is therefore searching in HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node.
There are a number of ways one can approach this:
Use Registry.OpenBaseKey and specify the desired Registry View.
Compile for AnyCPU, but uncheck Prefer 32-bit (Project => <project name> Properties... => Build => Uncheck Prefer 32-bit)
Compile for 64-bit
Option 1:
Note: The following is untested, but should work - it's a slight modification of the code in your OP.
private bool IsProgramInstalled(string programDisplayName, RegistryView regView = RegistryView.Registry64)
{
string logstr = string.Format("Checking install status of {0}....", programDisplayName);
using (RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, regView))
{
if (localKey != null)
{
using (RegistryKey rk = localKey.OpenSubKey(#"SOFTWARE\Bridge Club Utilities"))
{
if (rk != null)
{
foreach (string s in rk.GetSubKeyNames())
{
Console.WriteLine(s);
if (s != null)
{
if (s.Equals(programDisplayName))
{
AppendToLog(logstr + " INSTALLED");
return true;
}
}
}
}
}
}
}
AppendToLog(logstr + " NOT INSTALLED", Color.Red);
return false;
}
I'm trying to uninstall a program with this code.. But it doesn't seem to work. I've tried the other answers but didn't seem to work either.. Can someone help me with this? I'm trying to uninstall the program by a given name(displayName)
For example I give the displayName = Appname then this code should uninstall the Appname program from my computer.
public static void UninstallApplictionInstalled(string p_name)
{
string displayName;
string uninstlString;
RegistryKey key;
ProcessStartInfo info = new ProcessStartInfo();
Process uninstallProcess = new Process();
string temp;
// search in: CurrentUser
key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = Convert.ToString(subkey.GetValue("DisplayName"));
uninstlString = Convert.ToString(subkey.GetValue("UninstallString"));
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + uninstlString + " /quiet /norestart";
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
// search in: LocalMachine_32
key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = Convert.ToString(subkey.GetValue("DisplayName"));
uninstlString = Convert.ToString(subkey.GetValue("UninstallString"));
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + uninstlString + " /quiet /norestart";
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
// search in: LocalMachine_64
key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = Convert.ToString(subkey.GetValue("DisplayName"));
uninstlString = Convert.ToString(subkey.GetValue("UninstallString"));
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
//string prdctId = uninstlString.Substring((uninstlString.IndexOf("{")));
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + uninstlString + " /quiet /norestart";
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
}
Only this pops up..
Duplicates: Welcome to Stackoverflow. Just to mention to you that I see this question asked in at least 3 different flavors. We will have to close some of your questions since the duplication scatters replies and can waste a lot of time if people answer the (seemingly) unanswered duplicates.
In short: please don't post the same question several times. Here are the other questions:
MsiExec.exe product id uninstall
MSI installer option- uninstalling an application
C#: Using C# for this can be clunky - no matter how you do it. I would not push a command line to msiexec.exe, but go directly via the MSI API. This API can be accessed via Win32 functions or COM automation.
Uninstall Appraches for MSI: For your reference, there is a myriad of ways to kick of an MSI
uninstall:
Uninstalling an MSI file from the command line without using msiexec.
Section 14 from the link above shows how to uninstall using C++ - if that is an option. However:, there are changes in the Visual Studio 2017 templates again, so it might need a tune-up to work "out-of-the-box".
However, I would use the MSI API - as already stated - and I would recommend you go via the native Win32 functions and that you use DTF (Deployment Tools Foundation) which is part of the WiX toolkit. It is a .NET wrapper for the MSI API - which will save you a lot of boilerplate code, at the expense of having to deploy the DTF DLL: Microsoft.Deployment.WindowsInstaller.dll along with your product. I do not know if this is acceptable. I have code that does not depend on DTF if need be, but it is much longer.
Mock-up C# Sample. Project reference to Microsoft.Deployment.WindowsInstaller.dll needed. Then try the below code in a fresh C# .NET project. You can get that DLL by installing the WiX toolkit - the open source toolkit to create MSI files. After installation check in %ProgramFiles(x86)%\WiX Toolset v3.11\bin (adjust for WiX version - current as of September 2018).
Installer GUI: Important note first: the setup's UI level is set via the Installer.SetInternalUI function. If you run in silent mode, then you need to run the executable elevated for the uninstall to work properly, or an access exception occurs. When you run in Full GUI mode, you need to elevate the install yourself - provided you have the rights to do so.
Run Elevated: How to check for admin rights: Check if the current user is administrator.
using System;
using Microsoft.Deployment.WindowsInstaller;
namespace UninstallMsiViaDTF
{
class Program
{
static void Main(string[] args)
{
// Update this name to search for your product. This sample searches for "Orca"
var productcode = FindProductCode("orca");
try
{
if (String.IsNullOrEmpty(productcode)) { throw new ArgumentNullException("productcode"); }
// Note: Setting InstallUIOptions to silent will fail uninstall if uninstall requires elevation since UAC prompt then does not show up
Installer.SetInternalUI(InstallUIOptions.Full); // Set MSI GUI level (run this function elevated for silent mode)
Installer.ConfigureProduct(productcode, 0, InstallState.Absent, "REBOOT=\"ReallySuppress\"");
// Check: Installer.RebootInitiated and Installer.RebootRequired;
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}
Console.ReadLine(); // Keep console open
}
// Find product code for product name. First match found wins
static string FindProductCode(string productname)
{
var productcode = String.Empty;
var productname = productname.ToLower();
foreach (ProductInstallation product in ProductInstallation.AllProducts)
{
if (product.ProductName.ToLower().Contains(productname))
{
productcode = product.ProductCode;
break;
}
}
return productcode;
}
}
}
I need list of installed application on the computer and their path directory, and I find this:
//Registry path which has information of all the softwares installed on machine
string uninstallKey = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey))
{
foreach (string skName in rk.GetSubKeyNames())
{
using (RegistryKey sk = rk.OpenSubKey(skName))
{
// we have many attributes other than these which are useful.
Console.WriteLine(sk.GetValue("DisplayName") +
" " + sk.GetValue("DisplayVersion"));
}
}
}
How I get the path? I tried sk.GetValue("DisplayPath")but it not work.
Thanks!
Each software will have a different name for InstallLocation, if it will be there at all.
The one thing that will always be is UninstallString, which returns the path of the uninstaller (exe), which you can strip the directory from.
However, you should know that you will not get all installed programs there, if you go by HKEY_CURRENT_USER.
You should go via HKEY_LOCAL_MACHINE.
So, the code you are seeking is:
string uninstallExePath = sk.GetValue("UninstallString");
DirectoryInfo directory = new FileInfo(uninstallExePath).Directory;
string directoryPath = directory.FullName;
For get the path I find that: GetValue("InstallLocation")
It's work but for so many value it get 'null' or "".
I am building an app and its a simple one, all I want it to do is display os information in plain english and the architecture as well as check for installed browsers and then I'll add the ability for it to delete cookies and what not.
What Im stuck on is the browser detection part. Can anyone point me to some decent tutorials or how tos? Thanks.
Edit: OK I managed to finally scratch out some working code using the snippet provided by hcb below and the comments from the others (thanks everyone). So far it is doing exactly what I want so I thought id share what I have for those trying to do the same thing:
RegistryKey browserKeys;
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\WOW6432Node\Clients\StartMenuInternet");
if (browserKeys == null)
{
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Clients\StartMenuInternet");
}
string[] browserNames = browserKeys.GetSubKeyNames();
foreach (string browser in browserNames)
{
using (RegistryKey tempKey = browserKeys.OpenSubKey(browser))
{
foreach (string keyName in tempKey.GetValueNames())
{
if (tempKey.GetValue(keyName).ToString() == "Internet Explorer")
{
internetExplorerButton.Enabled = true;
internetExplorerButton.BackgroundImage = Properties.Resources.iExplorer;
if (internetExplorerButton.Enabled == true)
{
Label ieLabel = new Label();
ieLabel.Text = "Found!";
explorerLable.Text = ieLabel.Text;
}
}
To my extreme annoyance, I noticed that Google want to install their browser in the Local App Data. I managed to work this out writing the code again separately and checking:
Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Google\Update\Clients");
Edit2: Checking CurrentUser for Chrome seems to work fine for a few friends so it must be OK.
Like this:
RegistryKey browserKeys;
//on 64bit the browsers are in a different location
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\WOW6432Node\Clients\StartMenuInternet");
if (browserKeys == null)
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Clients\StartMenuInternet");
string[] browserNames = browserKeys.GetSubKeyNames();
I want to check whether certain microsoft components like wmencoder, directx or wmplayer
are installed or not. If it is installed, can I also get its version number?
How can I do that?
Thanks in advance.
I use the below to determine if other applications are installed, however you will need to know the "unique" product code (from the setup project in Visual Studio) that the application is installed with in the registry.
Include
using System.Diagnostics;
using Microsoft.Win32;
Usage:
// HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{0006F03A-0000-0000-C000-000000000046} << This is outlook 2003
String retval = "";
// Look to see if Outlook 2003 is installed and if it is...
if ((checkComServerExists("{0006F03A-0000-0000-C000-000000000046}", out retval)))
{
// Update boolean flag if we get this far so we don't have to check again
Console.WriteLine("Office CSLID exists - Version: " + retval);
}
Function:
// Checks to see if the given CLSID is registerd and exists on the system
private static Boolean checkComServerExists(String CLSID, out String retval)
{
RegistryKey myRegKey = Registry.LocalMachine;
Object val;
try
{
// get the pathname to the COM server DLL/EXE if the key exists
myRegKey = myRegKey.OpenSubKey("SOFTWARE\\Classes\\CLSID\\" + CLSID + "\\LocalServer32");
val = myRegKey.GetValue(null); // the null gets default
}
catch
{
retval = "CLSID not registered";
return false;
}
FileVersionInfo myFileVersionInfo = null;
try
{
// parse out the version number embedded in the resource
// in the DLL
myFileVersionInfo = FileVersionInfo.GetVersionInfo(val.ToString());
}
catch
{
retval = String.Format("DLL {0} not found", val.ToString());
return false;
}
retval = myFileVersionInfo.FileVersion;
return true;
}
My first thought would be WMI. Class Win32_SoftwareElement (on MSDN)
But likely to take some work to get the right classes and queries. Start with the WMI tools for WMI CIM Studio.
Using PowerShell, something like:
gwmi win32_softwareelement -filter "name like '%play%'" | ft
will allow finding the right ids. (Warning: this is extremely slow.)
Possible that the MS Installer (MSI) API has something quicker.
I use RegShot to determine registry setting that can be used to check if a softwre is installed ..
Here is also a small code snippet that uses, among others, Type.GetTypeFromProgID and registry access.