2

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.. enter image description here

Community
  • 1
  • 1
BongJae
  • 49
  • 5
  • 1
    Are you sure your app has permission to uninstall? Are you running this as admin? Also, have you tried running it without the /quiet and with /L logging enabled – pstrjds Sep 10 '18 at 08:55
  • 6
    Whatever is placed inside `UninstallString` is intended to be a *complete*, standalone command to uninstall the program. There's no guarantee that `msiexec /x` is the correct way to uninstall any given program, and even if it *is*, `UninstallString` will already *contain* that text. – Damien_The_Unbeliever Sep 10 '18 at 08:57
  • 2
    Could you please tell us what `does not seem to be working` mean? It will be more helpful if you can give us some sort of "error message" you're getting while running this program. – Aniket Inge Sep 10 '18 at 08:57
  • 2
    The first thing that hits me when I read your code is `void IsApplicationInstalled`. Considering the name, I would have expected `bool` instead of `void`. The body of your function also does not match its name at all. It's like if you asked someone "*Hey, do you have some milk?*" and he answered "*mmh lemme check... yup, I just poured it in the toilets*" or even worse: he pours it in the toilet and doesn't tell you anything. (Just saying) – Rafalon Sep 10 '18 at 08:59
  • 1
    the Popup implies you got the syntax of the command wrong. Did you provide the msi/product code to go with that /x or the display name? the display name isnt the same. – BugFinder Sep 10 '18 at 09:02
  • @BugFinder as shown in the code i gave the Uninstallstring ... I think...not the display name – BongJae Sep 10 '18 at 09:05
  • 1
    A general remark: don't do `if (p_name.Equals(value) == true)` - IMO it is bad style, it returns a boolean already, just do `if (p_name.Equals(value))` – Peter B Sep 10 '18 at 09:06
  • The uninstall string can be other uninstall methods, so for example ive got a couple which are c:\users\name\appdata\local\app\uninstall.exe or one thats c:\program files\...blah\something configuration - uninstallApp more blah... You can assume they are all msi uninstall files – BugFinder Sep 10 '18 at 09:16
  • Possible duplicate of [MSI installer option- uninstalling an application](https://stackoverflow.com/questions/52267512/msi-installer-option-uninstalling-an-application) – Lance U. Matthews Sep 11 '18 at 02:27

1 Answers1

2

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:


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;
        }
    }
}
Matt
  • 25,467
  • 18
  • 120
  • 187
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • You answer is informativ, but why `string.ToLower().Contains(string.Tolower())`? and that in a loop... You are constructing 2 new strings per iteration, you don't need them. Is this in any way better performing than `string.IndexOf(string, StringComparison) > -1`? – Steeeve Aug 06 '21 at 16:18
  • @Steeve - Yes, you can lowercase the productname before the loop which is more efficient. But I don't think there is a significant performance difference between `string.IndexOf(myString, StringComparison) > -1` and `myString.Contains(StringComparison)`. – Matt Jan 27 '22 at 08:55