Uninstalling program - c#

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;
}
}
}

Related

program fails to get RegistryKey on particular Win10 box

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;
}

MSI installer option- uninstalling an application [duplicate]

This question already has an answer here:
Uninstalling program
(1 answer)
Closed 4 years ago.
If I run the code below I'm pretty sure I'm supposed to get the Product Name and GUID (ex. App Path | {xxx}) for the application. But I'm only getting the path and no GUID is shown. Can someone help me?
// 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))
{
Console.WriteLine(subkey.GetValue("UninstallString"));
//string prdctId = uninstlString.Substring((uninstlString.IndexOf("{")));
string prdctId = uninstlString.Substring(12);
uninstallProcess.StartInfo.FileName = "MsiExec.exe";
uninstallProcess.StartInfo.Arguments = " /x " + prdctId + " /quiet /norestart";
uninstallProcess.StartInfo.UseShellExecute = true;
uninstallProcess.Start();
uninstallProcess.WaitForExit();
break;
//Console.WriteLine(subkey.GetValue("UninstallString"));
}
}
This is the image that I got running the code
I believe the UninstallString value is what gets executed when uninstalling an application via Add/Remove Programs. As your console output shows, it's the path to an executable.
The way you are retrieving the product ID...
string prdctId = uninstlString.Substring(12);
...therefore, is incorrect because you are taking a partial path. What you need to pass to MsiExec.exe /x is the product code, which is the registry key name itself, i.e....
string prdctId = keyName;
If you were invoking that command line from Command Prompt I'm pretty sure the curly brackets would necessitate putting quotes around the product code; I'm not sure if you'll need to do so when invoking the executable directly, but it can't hurt...
uninstallProcess.StartInfo.Arguments = " /x \"" + prdctId + "\" /quiet /norestart";

C# Windows how ro run exe after detect .Net version

I Have a Three EXE's
EXE1 build with 3.5 net framework
EXE2 build with 4.5 net framework
EXE3 build with 4.6 net framework
I want to run exe after detect which.Net version already installed and according to that start exe
if 3.5 installed
RUN(EXE1)
if 4.5 installed
RUN(EXE2)
if 4.6 installed
RUN(EXE3)
i think about wix setup, iexpress but didnt get any thing so how can we do this ?
or its is possible? if yes then how and if no then so can we do this with the help of third party software?
so I need a way to run exe as per platform because each platform has
their own .Net framework
there is 2 way: using bath file to detect .net version after that run exe for this version
or build a porogram exe depend .net 2 after that this exe decide witch file must run
Update:
this samples give you version of .net freamwork are inistaled
for.net 4 and older
private static void GetVersionFromRegistry()
{
// Opens the registry key for the .NET Framework entry.
using (RegistryKey ndpKey =
RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "").
OpenSubKey(#"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
{
// As an alternative, if you know the computers you will query are running .NET Framework 4.5
// or later, you can use:
// using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
// RegistryView.Registry32).OpenSubKey(#"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
foreach (string versionKeyName in ndpKey.GetSubKeyNames())
{
if (versionKeyName.StartsWith("v"))
{
RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
string name = (string)versionKey.GetValue("Version", "");
string sp = versionKey.GetValue("SP", "").ToString();
string install = versionKey.GetValue("Install", "").ToString();
if (install == "") //no install info, must be later.
Console.WriteLine(versionKeyName + " " + name);
else
{
if (sp != "" && install == "1")
{
Console.WriteLine(versionKeyName + " " + name + " SP" + sp);
}
}
if (name != "")
{
continue;
}
foreach (string subKeyName in versionKey.GetSubKeyNames())
{
RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
name = (string)subKey.GetValue("Version", "");
if (name != "")
sp = subKey.GetValue("SP", "").ToString();
install = subKey.GetValue("Install", "").ToString();
if (install == "") //no install info, must be later.
Console.WriteLine(versionKeyName + " " + name);
else
{
if (sp != "" && install == "1")
{
Console.WriteLine(" " + subKeyName + " " + name + " SP" + sp);
}
else if (install == "1")
{
Console.WriteLine(" " + subKeyName + " " + name);
}
}
}
}
}
}
}
and for get .net 4.5 and upper
using System;
using Microsoft.Win32;
public class GetDotNetVersion
{
public static void Get45PlusFromRegistry()
{
const string subkey = #"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey != null && ndpKey.GetValue("Release") != null) {
Console.WriteLine(".NET Framework Version: " + CheckFor45PlusVersion((int) ndpKey.GetValue("Release")));
}
else {
Console.WriteLine(".NET Framework Version 4.5 or later is not detected.");
}
}
}
// Checking the version using >= will enable forward compatibility.
private static string CheckFor45PlusVersion(int releaseKey)
{
if (releaseKey >= 460798) {
return "4.7 or later";
}
if (releaseKey >= 394802) {
return "4.6.2";
}
if (releaseKey >= 394254) {
return "4.6.1";
}
if (releaseKey >= 393295) {
return "4.6";
}
if ((releaseKey >= 379893)) {
return "4.5.2";
}
if ((releaseKey >= 378675)) {
return "4.5.1";
}
if ((releaseKey >= 378389)) {
return "4.5";
}
// This code should never execute. A non-null release key should mean
// that 4.5 or later is installed.
return "No 4.5 or later version detected";
}
}
// Calling the GetDotNetVersion.Get45PlusFromRegistry method produces
// output like the following:
// .NET Framework Version: 4.6.1
and by this sample you can run exe file
using System;
using System.Diagnostics;
using System.ComponentModel;
namespace MyProcessSample
{
class MyProcess
{
public static void Main()
{
Process myProcess = new Process();
try
{
myProcess.StartInfo.UseShellExecute = false;
// You can start any process, HelloWorld is a do-nothing example.
myProcess.StartInfo.FileName = "C:\\HelloWorld.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
// This code assumes the process you are starting will terminate itself.
// Given that is is started without a window so you cannot terminate it
// on the desktop, it must terminate itself or you can do it programmatically
// from this application using the Kill method.
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Update2:
by this Update you get latest version of .net at batch File
#echo off
setlocal
#SET INSTALLUTILDIR=
#for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5" /v "Version"') DO (
if "%%i"=="Version" (
SET .NetVer=%%k
)
)
#for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v "Version"') DO (
if "%%i"=="Version" (
SET .NetVer=%%k
)
)
ECHO The most current version of Net in use is %.NetVer%
and by this code you can run program but dont forget the bat file must be in folder the exe files are there
start myProgram.exe
exit
If you use Windows Installer (such as through wix), you can use the MsiNetAssemblySupport property to condition a custom action that launches your executable. If you use wix specifically, the WixNetfxExtension can be asked to set other properties that may be easier to use. Here is wix's list of .NET properties.
However I suspect this is the wrong approach. It should be much easier to write a single .NET executable that targets the lowest framework version you support, and include a .config file1 with a supportedRuntime element that enables it to run on a wider spread of frameworks. (See How to: Configure an App to Support .NET Framework 4 or 4.5.
Also, depending on what the executable does, you may be better off writing a C++ executable, a C++ DLL (so it can interact with Windows Installer), or even leveraging native Windows Installer functionality instead of custom actions. (If applicable, the last option is ideal.)
1Note that Windows Installer EXE custom action support for temporary files will only extract a single file to the temp folder, so your .config file would not be found in these configurations. Alternate approaches would be required; various Windows Installer tools have their own approaches for mitigating this problem.

How to uninstall application programmatically

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!

find application path in Registry

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 "".

Categories