Introduction
Recently I was faced with the challenge
of uninstalling an application programmatically. I had scoured the internet
only to find a large amount of developers taking the registry key approach
(finding the uninstall string then shelling to Windows installer). This however
has its disadvantages…this uninstall string is located in different areas
depending on your Windows build and architecture (x86 or x64). I decided to do
a little research with Windows Management Instrumentation (WMI) and came up
with the following solution.
Using the code
The first step is to add a COM
reference to System.Management, adding the namespace is not enough, the COM
reference contains the classes we will use.
using System.Management
Listing installed applications
Next, let's get a collection of applications that are installed on the system (note that some items may show up in
Win32_Product
that don't actually have an uninstall string and are
not listed in add/remove programs, i'm unsure why...)
The first step in achieving this is by creating a
ManagementObjectSearcher
which Retrieves a collection of management objects based on a specified query, our query is based on the Win32_Product class:
ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
After the query has been set the command needs to be executed, to do so we call the
ManagementObjectSearcher
Get()
function (which we initiated as
mos
):
*Take note that the Get()
method is resource intensive and may take a bit to return*
foreach (ManagementObject mo in mos.Get())
{
Since the Get()
statement is IEnumerable
we can enumerate its contents in a for loop, exposing each
ManagementObject
. We are simply looking for the "Name
" property (you can find others on the MSDN site: http://msdn.microsoft.com/en-us/library/windows/desktop/aa394378(v=vs.85).aspx )
We get a
ManagementObject
property by using the following format:
mo["Name"].ToString()
Since it is an Object
, we need to convert it to a string (which is the
[Name]
data type), this is very simple in C#.
The full block of code to list installed applications:
using System.Management
private List<string> ListPrograms()
{
List<string> programs = new List<string>();
try
{
ManagementObjectSearcher mos =
new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach (ManagementObject mo in mos.Get())
{
try
{
programs.Add(mo["Name"].ToString());
}
catch (Exception ex)
{
}
}
return programs;
}
catch (Exception ex)
{
return programs;
}
}
Now that we have a list of installed applications we should be able to pass the
[Name]
property to our uninstall method.
Uninstalling an application
Now it's time to uninstall. Note that the uninstall method is pretty much the same as our method to enumerate and list installed
applications, the only difference here is we now need to Invoke the Win32_Product
method to “Uninstall” (there are a list of other available methods in the link above).
The query has also changed. Now that we know the name of the application, we do not need to enumerate the entire list of applications installed:
"SELECT * FROM Win32_Product WHERE Name = '" + ProgramName + "'"
Here is the entire block to uninstall an application, I'll get in detail after you take a look.
private bool UninstallProgram(string ProgramName)
{
try
{
ManagementObjectSearcher mos = new ManagementObjectSearcher(
"SELECT * FROM Win32_Product WHERE Name = '" + ProgramName + "'");
foreach (ManagementObject mo in mos.Get())
{
try
{
if (mo["Name"].ToString() == ProgramName)
{
object hr = mo.InvokeMethod("Uninstall", null);
return (bool)hr;
}
}
catch (Exception ex)
{
}
}
return false;
}
catch (Exception ex)
{
return false;
}
}
After the search is executed with mos.Get()
we will have a list (most likely just 1 instance) of the chosen application to uninstall (You can see that I placed
a simple safety net of comparing the application about to be uninstalled with the actual application we want to remove). Now lets focus on the method that actually uninstalls the application:
object hr = mo.InvokeMethod("Uninstall", null);
Note: ManagementObject.Invoke() requires Full trust for the immediate caller. This member cannot be used by partially trusted code, so you should be an administrator or add a manifest to your application with “requireadministrator” set.
Now that our ManagementObject
is set to an
instance of the application we want to uninstall we need to invoke the
Win32_Product
class' “Uninstall”. Above I demonstrated on how to call this synchronous
method (the second parameter in InvokeMethod()
is to pass any parameters, which "Uninstall" takes nothing, thus null... There are several more overloads). Cast hr
to a boolean
value to get the results returned.
That's it!
Take note that the attached code contains a BackgroundWorker
that prevents the UI locking up during the WMI search (which
I do not cover here),
yes, this search is resource intensive and may take a bit to list applications depending on your system specs...
Points of
interest
After facing trial and error I have successfully used this code in my own personal projects to uninstall my applications during certain update scenarios… I have found this method
more reliable than looking for registry keys that contain the applications Uninstall string.