Skip to main content

Auto Uninstaller For ClickOnce Deployment Applications

A small windows application to uninstall the click once deployment applications silently. Generally if you want uninstall click once application, we have to perform multiple clicks and actions. This application loads all the installed click once applications from the machine for logged in user and user can select the application to uninstall, after clicking on uninstall button, it silently uninstall the application without user intervention.
AutoUninstaller.Designer.cs:
 namespace ClickOnceUninstaller
{
    partial class AutoUninstaller
    {
        /// 
        /// Required designer variable.
        /// 
        private System.ComponentModel.IContainer components = null;
 
        /// 
        /// Clean up any resources being used.
        /// 
        /// "disposing">true if managed resources should be disposed; otherwise, false.
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
 
        #region Windows Form Designer generated code
 
        /// 
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// 
        private void InitializeComponent()
        {
            this.btnUninstall = new System.Windows.Forms.Button();
            this.panel1 = new System.Windows.Forms.Panel();
            this.grpBoxUninstaller = new System.Windows.Forms.GroupBox();
            this.clickOnceAppView = new System.Windows.Forms.ListView();
            this.progressBar = new System.Windows.Forms.ProgressBar();
            this.labelAppBeingUninstalled = new System.Windows.Forms.Label();
            this.btnClose = new System.Windows.Forms.Button();
            this.panel1.SuspendLayout();
            this.grpBoxUninstaller.SuspendLayout();
            this.SuspendLayout();
            // 
            // btnUninstall
            // 
            this.btnUninstall.Location = new System.Drawing.Point(257, 539);
            this.btnUninstall.Name = "btnUninstall";
            this.btnUninstall.Size = new System.Drawing.Size(231, 23);
            this.btnUninstall.TabIndex = 0;
            this.btnUninstall.Text = "Choose Application and Click Me To UnInstall";
            this.btnUninstall.UseVisualStyleBackColor = true;
            this.btnUninstall.Click += new System.EventHandler(this.btnUninstall_Click);
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.grpBoxUninstaller);
            this.panel1.Location = new System.Drawing.Point(7, 12);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(537, 520);
            this.panel1.TabIndex = 1;
            // 
            // grpBoxUninstaller
            // 
            this.grpBoxUninstaller.Controls.Add(this.clickOnceAppView);
            this.grpBoxUninstaller.Dock = System.Windows.Forms.DockStyle.Fill;
            this.grpBoxUninstaller.ForeColor = System.Drawing.Color.MediumBlue;
            this.grpBoxUninstaller.Location = new System.Drawing.Point(0, 0);
            this.grpBoxUninstaller.Name = "grpBoxUninstaller";
            this.grpBoxUninstaller.Size = new System.Drawing.Size(537, 520);
            this.grpBoxUninstaller.TabIndex = 0;
            this.grpBoxUninstaller.TabStop = false;
            this.grpBoxUninstaller.Text = "Installed ClickOnce Deployment Applications";
            // 
            // clickOnceAppView
            // 
            this.clickOnceAppView.CheckBoxes = true;
            this.clickOnceAppView.Dock = System.Windows.Forms.DockStyle.Fill;
            this.clickOnceAppView.Location = new System.Drawing.Point(3, 16);
            this.clickOnceAppView.Name = "clickOnceAppView";
            this.clickOnceAppView.Size = new System.Drawing.Size(531, 501);
            this.clickOnceAppView.Sorting = System.Windows.Forms.SortOrder.Ascending;
            this.clickOnceAppView.TabIndex = 2;
            this.clickOnceAppView.UseCompatibleStateImageBehavior = false;
            this.clickOnceAppView.View = System.Windows.Forms.View.List;
            // 
            // progressBar
            // 
            this.progressBar.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
            this.progressBar.Location = new System.Drawing.Point(7, 539);
            this.progressBar.Name = "progressBar";
            this.progressBar.Size = new System.Drawing.Size(244, 23);
            this.progressBar.TabIndex = 9;
            this.progressBar.Visible = false;
            // 
            // labelAppBeingUninstalled
            // 
            this.labelAppBeingUninstalled.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
            this.labelAppBeingUninstalled.AutoSize = true;
            this.labelAppBeingUninstalled.ForeColor = System.Drawing.Color.Green;
            this.labelAppBeingUninstalled.Location = new System.Drawing.Point(10, 571);
            this.labelAppBeingUninstalled.Name = "labelAppBeingUninstalled";
            this.labelAppBeingUninstalled.Size = new System.Drawing.Size(13, 13);
            this.labelAppBeingUninstalled.TabIndex = 10;
            this.labelAppBeingUninstalled.Text = "--";
            this.labelAppBeingUninstalled.Visible = false;
            // 
            // btnClose
            // 
            this.btnClose.Location = new System.Drawing.Point(494, 539);
            this.btnClose.Name = "btnClose";
            this.btnClose.Size = new System.Drawing.Size(50, 23);
            this.btnClose.TabIndex = 11;
            this.btnClose.Text = "Cancel";
            this.btnClose.UseVisualStyleBackColor = true;
            this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
            // 
            // AutoUninstaller
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            this.ClientSize = new System.Drawing.Size(553, 590);
            this.Controls.Add(this.btnClose);
            this.Controls.Add(this.labelAppBeingUninstalled);
            this.Controls.Add(this.progressBar);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.btnUninstall);
            this.MaximizeBox = false;
            this.Name = "AutoUninstaller";
            this.Text = "Auto Uninstaller For ClickOnce Deployment Applications";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AutoUninstaller_FormClosing);
            this.panel1.ResumeLayout(false);
            this.grpBoxUninstaller.ResumeLayout(false);
            this.ResumeLayout(false);
            this.PerformLayout();
 
        }
 
        #endregion
 
        private System.Windows.Forms.Button btnUninstall;
        private System.Windows.Forms.Panel panel1;
        private System.Windows.Forms.GroupBox grpBoxUninstaller;
        private System.Windows.Forms.ListView clickOnceAppView;
        private System.Windows.Forms.ProgressBar progressBar;
        private System.Windows.Forms.Label labelAppBeingUninstalled;
        private System.Windows.Forms.Button btnClose;
    }
}
AutoUninstaller.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Diagnostics;
 
namespace ClickOnceUninstaller
{
    /// 
    /// AutoUninstaller Class
    /// 
    public partial class AutoUninstaller : Form
    {
        //Private Members
        private IDictionary<stringstring> _clickonceInstalledApps;
        private List<string> _appsToBeUninstall;
        private BackgroundWorker _backgroundWorker;
        /// 
        /// AutoUninstaller Constructor
        /// 
        public AutoUninstaller()
        {
            InitializeComponent();
            this.Load +=new EventHandler(AutoUninstaller_Load);
        }
 
        /// 
        /// AutoUninstaller Load
        /// 
        /// "sender">
        /// "e">
        private void AutoUninstaller_Load(object sender, EventArgs e)
        {
            try
            {
                LoadInstalledClickOnceApps();
            }
            catch (Exception)
            {
                MessageBox.Show("Not able to load the installed click once applications!");
            }
        }
 
        /// 
        /// Bind installed application names to the VIEW
        /// 
        private void LoadInstalledClickOnceApps()
        {
            _clickonceInstalledApps = GetInstalledClickOnceApps();
            foreach (KeyValuePair<stringstring> keyValuePair in _clickonceInstalledApps)
            {
                clickOnceAppView.Items.Add(keyValuePair.Value);
            }
        }
 
        /// 
        /// Read the installed click once applications from Registry;add it to the list and return the list
        /// 
        /// 
        private IDictionary<stringstring> GetInstalledClickOnceApps()
        {
            IDictionary<stringstring> installedApps = new Dictionary<stringstring>();
            RegistryKey registryKeys = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
            string[] appKeyNames = registryKeys.GetSubKeyNames();
            string displayName = null;
            string uninstallString = null;
            foreach (string appKeyName in appKeyNames)
            {
                RegistryKey appKey = registryKeys.OpenSubKey(appKeyName);
                displayName = (string)appKey.GetValue("DisplayName");
                uninstallString = (string)appKey.GetValue("UninstallString");
                installedApps.Add(uninstallString, displayName);
                appKey.Close();
            }
            registryKeys.Close();
            return installedApps;
        }
 
        /// 
        /// Uninstall Button Click Event Handler
        /// 
        /// "sender">
        /// "e">
        private void btnUninstall_Click(object sender, EventArgs e)
        {
            if (clickOnceAppView.CheckedItems.Count > 0)
            {
                UninstallApps();
            }
            else
            {
                MessageBox.Show("Choose a application to UnInstall!""Warning!");
            }
        }
 
        /// 
        /// Method to Uninstall Applications
        /// 
        private void UninstallApps()
        {
            _appsToBeUninstall = GetAppsToBeUninstall();
            if (_appsToBeUninstall.Count > 0)
            {
                this.StartUninstallAppsInBackgroundTask(_appsToBeUninstall);
            }
        }
 
        /// 
        /// Background Task Method to handle uninstalling
        /// 
        /// "appsToBeUninstall">
        private void StartUninstallAppsInBackgroundTask(List<string> appsToBeUninstall)
        {
            this.DeactivateActionControls();
            this._backgroundWorker = new BackgroundWorker();     
            this._backgroundWorker.WorkerReportsProgress = true;     
            this._backgroundWorker.WorkerSupportsCancellation = true;
            //DoWork
            this._backgroundWorker.DoWork += (_, args) =>
            {
                int progressCount = 0;
                List<string> apps = args.Argument as List<string>;
                foreach (string app in apps)
                {
                    if (this._backgroundWorker.CancellationPending)
                    {
                        args.Cancel = true;
                        return;
                    }
                    this._backgroundWorker.ReportProgress((++progressCount * 100) / apps.Count, app);
                    UninstallMe(app);
                }
                args.Result = progressCount;    
            };
            //Progress Changed
            this._backgroundWorker.ProgressChanged += (_, args) =>
            {
                string appName = args.UserState as string;
                this.labelAppBeingUninstalled.Text = "Uninstalling " + appName + "....";
                this.progressBar.Value = args.ProgressPercentage;   
            };
            //RunWorker Completed
            this._backgroundWorker.RunWorkerCompleted += (_, args) =>
            {
                this.progressBar.Value = 100;
                if (args.Error != null)
                    MessageBox.Show("Background task error: " + args.Error.ToString());
                else if (args.Cancelled)
                    MessageBox.Show("Uninstall background task cancelled");
 
                this.ActivateActionControls();
            };
 
            this._backgroundWorker.RunWorkerAsync(appsToBeUninstall);
        }
 
        /// 
        /// Get Apps to be Uninstall
        /// 
        /// 
        private List<string> GetAppsToBeUninstall()
        {
            List<string> uninstallApps = new List<string>();
            foreach (ListViewItem item in clickOnceAppView.Items)
            {
                if (item.Checked)
                {
                    uninstallApps.Add(item.Text);
                }
            }
            return uninstallApps;
        }
 
        /// 
        /// Uninstall the application
        /// 
        /// "uninstallAppName">
        private void UninstallMe(string uninstallAppName)
        {
            string uninstallString = GetUninstallString(uninstallAppName);
            string runDLL32 = uninstallString.Substring(0, 12);
            string args = uninstallString.Substring(13);
            Process uninstallProcess = Process.Start(runDLL32, args);
            PushUninstallOKButton(uninstallAppName);
        }
 
        /// 
        /// Gives the application uninstall string
        /// 
        /// "uninstallAppName">
        /// 
        private string GetUninstallString(string uninstallAppName)
        {
            string uninstallString = null;
            foreach (KeyValuePair<stringstring> keyValuePair in _clickonceInstalledApps)
            {
                if (keyValuePair.Value.Equals(uninstallAppName, StringComparison.OrdinalIgnoreCase))
                {
                    uninstallString = keyValuePair.Key;
                    break;
                }
            }
            return uninstallString;
        }
 
        /// 
        /// Auto Push for Uninstall Window OK button
        /// 
        /// "DisplayName">
        private static void PushUninstallOKButton(string DisplayName)
        {
            IntPtr uninstallerWindow = FindUninstallerWindow(DisplayName);
            IntPtr WindowOKButton = FindUninstallerOKButton(uninstallerWindow);
            Win32API.WindowDoButtonClick(WindowOKButton);
        }
 
        /// 
        /// Finder for Uninstaller OK Button
        /// 
        /// "UninstallerWindow">
        /// 
        private static IntPtr FindUninstallerOKButton(IntPtr UninstallerWindow)
        {
            Win32API win32 = new Win32API();
            IntPtr WindowOKButton = IntPtr.Zero;
            while (WindowOKButton == IntPtr.Zero)
            {
                WindowOKButton = win32.SearchForChildWindowAPI(UninstallerWindow, "&OK");
                System.Threading.Thread.Sleep(500);
            }
 
            return WindowOKButton;
        }
 
        /// 
        /// Finder for Uninstaller Window
        /// 
        /// "DisplayName">
        /// 
        private static IntPtr FindUninstallerWindow(string DisplayName)
        {
            Win32API win32 = new Win32API();
            IntPtr uninstallerWindow = IntPtr.Zero;
            while (uninstallerWindow == IntPtr.Zero)
            {
                uninstallerWindow = win32.SearchForTopLevelWindowAPI(DisplayName + " Maintenance");
                System.Threading.Thread.Sleep(500);
            }
            return uninstallerWindow;
        }
 
        /// 
        /// Deactivate the Action Controls
        /// 
        private void DeactivateActionControls()
        {
            this.progressBar.Visible = true;
            this.labelAppBeingUninstalled.Visible = true;
            this.btnUninstall.Enabled = false;
            this.btnClose.Enabled = false;
        }
 
        /// 
        /// Activate the Action Controls
        /// 
        private void ActivateActionControls()
        {
            this.progressBar.Visible = false;
            this.labelAppBeingUninstalled.Visible = false;
            RefreshListView();
            this.btnUninstall.Enabled = true;
            this.btnClose.Enabled = true;
        }
 
        /// 
        /// Abort the Background Worker
        /// 
        private void AbortBackgroundWorker()
        {
            if (this._backgroundWorker != null && this._backgroundWorker.WorkerSupportsCancellation)
            {
                this._backgroundWorker.CancelAsync();
            }
        }
 
        /// 
        /// Refresh List View
        /// 
        private void RefreshListView()
        {
            clickOnceAppView.Items.Clear();
            IDictionary<stringstring> clickOnceApps = GetInstalledClickOnceApps();
            foreach (KeyValuePair<stringstring> keyValuePair in clickOnceApps)
            {
                if (_appsToBeUninstall.Contains(keyValuePair.Value))
                    continue;
                clickOnceAppView.Items.Add(keyValuePair.Value);
            }
        }
 
        /// 
        /// Form closing
        /// 
        /// "sender">
        /// "e">
        private void AutoUninstaller_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.AbortBackgroundWorker();
        }
 
        /// 
        /// Close Button Handler
        /// 
        /// "sender">
        /// "e">
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
Win32API.cs: For Win32API.cs source is Google search results.
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections;
 
namespace ClickOnceUninstaller
{
    /// 
    /// Win32API
    /// 
    public class Win32API
    {
        [DllImport("user32.Dll")]
        private static extern int EnumWindows(EnumWindowsCallbackDelegateAPI callback, IntPtr lParam);
        [DllImport("User32.Dll")]
        private static extern void GetWindowText(int h, StringBuilder s, int nMaxCount);
        [DllImport("User32.Dll")]
        private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsCallbackDelegateAPI lpEnumFunc, IntPtr lParam);
        [DllImport("User32.Dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        private static extern short FlashWindow(ref FLASHWINDOWINFO pwfi);
        private const int BM_CLICK = 0x00F5;
        /// 
        /// EnumWindowsCallbackDelegateAPI
        /// 
        /// "hwnd">
        /// "lParam">
        /// 
        private delegate bool EnumWindowsCallbackDelegateAPI(IntPtr hwnd, IntPtr lParam);
        /// 
        /// SearchForTopLevelWindowAPI
        /// 
        /// "WindowTitle">
        /// 
        public IntPtr SearchForTopLevelWindowAPI(string WindowTitle)
        {
            ArrayList windowHandles = new ArrayList();
            GCHandle gch = GCHandle.Alloc(windowHandles);
            try
            {
                EnumWindows(new EnumWindowsCallbackDelegateAPI(EnumProcess), (IntPtr)gch);
            }
            finally
            {
                gch.Free();
            }
            foreach (IntPtr handle in windowHandles)
            {
                StringBuilder sb = new StringBuilder(1024);
                GetWindowText((int)handle, sb, sb.Capacity);
                if (sb.Length > 0)
                {
                    if (sb.ToString().StartsWith(WindowTitle))
                    {
                        return handle;
                    }
                }
            }
            return IntPtr.Zero;
        }
        /// 
        /// SearchForChildWindowAPI
        /// 
        /// "ParentHandle">
        /// "Caption">
        /// 
        public IntPtr SearchForChildWindowAPI(IntPtr ParentHandle, string Caption)
        {
            ArrayList windowHandles = new ArrayList();
            GCHandle gch = GCHandle.Alloc(windowHandles);
            try
            {
                EnumChildWindows(ParentHandle, new EnumWindowsCallbackDelegateAPI(EnumProcess), (IntPtr)gch);
            }
            finally
            {
                gch.Free();
            }
            foreach (IntPtr handle in windowHandles)
            {
                StringBuilder sb = new StringBuilder(1024);
                GetWindowText((int)handle, sb, sb.Capacity);
                if (sb.Length > 0)
                {
                    if (sb.ToString().StartsWith(Caption))
                    {
                        return handle;
                    }
                }
            }
            return IntPtr.Zero;
        }
        /// 
        /// EnumProcess
        /// 
        /// "hWnd">
        /// "lParam">
        /// 
        private static bool EnumProcess(IntPtr hWnd, IntPtr lParam)
        {
            GCHandle gch = (GCHandle)lParam;
            ArrayList list = (ArrayList)(gch.Target);
            list.Add(hWnd);
            return true;
        }
        /// 
        /// WindowDoButtonClick
        /// 
        /// "ButtonHandle">
        public static void WindowDoButtonClick(IntPtr ButtonHandle)
        {
            SendMessage(ButtonHandle, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
        }
        /// 
        /// FlashWindowAPI
        /// 
        /// "handleToWindow">
        /// 
        public static bool FlashWindowAPI(IntPtr HandleToWindow)
        {
            FLASHWINDOWINFO flashwindowinfo = new FLASHWINDOWINFO();
            flashwindowinfo.cbSize = (uint)Marshal.SizeOf(flashwindowinfo);
            flashwindowinfo.hwnd = HandleToWindow;
            flashwindowinfo.dwFlags = 15;
            flashwindowinfo.uCount = uint.MaxValue;
            flashwindowinfo.dwTimeout = 0;
            return (Win32API.FlashWindow(ref flashwindowinfo) == 0);
        }
    }
    /// 
    /// FLASHWINDOWINFO
    /// 
    [StructLayout(LayoutKind.Sequential)]
    public struct FLASHWINDOWINFO
    {
        public uint cbSize;
        public IntPtr hwnd;
        public uint dwFlags;
        public uint uCount;
        public uint dwTimeout;
    }
}
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
 
namespace ClickOnceUninstaller
{
    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new AutoUninstaller());
        }
    }
}

Popular posts from this blog

Error : Task Scheduler - This task requires that the user account specified has Log on as batch job rights

In one of the production environment, we were running with low disk space problem because of the logs. To cleanup the old logs created a  task within the scheduler and have specified "Run whether use is logged on or not". The user account we used was the system logged on user. The task was running fine, after few months as a security policy the password expired. Since the old password expired we had to apply the new password for the task also, but this time we decided to create a new account specifically for the task scheduler with password never expire option. While setting up the new user account and password, run into the below issue: "The task required that the user account specified has log on as batch job rights" To fix the issue follow below steps: From Run type "secpol.msc /s" and enter, the local security policy snap in will open. Select "Local Policies" in MSC snap in Select "User Rights Assignment" Righ...

ISAPI & CGI Restriction configuration missing in IIS

In windows 7 by default ISAPI & CGI Restrictions are not configured. To enable ISAPI & CGI restrictions, GoTo -> Control Panel -> Programs -> Click on "Windows features on or off -> Expand Internet Information Services - >Expand World Wide Web Services ->Select CGI and ISAPI extensions and Click OK. After enabling, Check in IIS, Open your IIS and the feature will be available. What is ISAPI and CGI restrictions : ISAPI and CGI restrictions are request handlers that allow dynamic content to execute on a server. These restrictions are either CGI files (.exe) or ISAPI extensions (.dll). You can add custom ISAPI or CGI restrictions if the IIS configuration system allows this.

Implementing Parallelism With A SearchResultCollection

Implementing Parallel.ForEach with a SearchResultCollection: The below piece of code helps to check the given user is a part of the given active directory group. To implement Parallel.ForEach with a SearchResultCollection, do the casting with the SearchResult object and covert it into a list. //// Directory Searcher var directorySearcher = new DirectorySearcher(string.Format("(CN={0})", groupName)); //// Find group var searchResultCollection = directorySearcher.FindAll().Cast ().ToList(); Parallel.ForEach(searchResultCollection, searchResult => {  // enumerate members  var resultPropColl = searchResult.Properties;  Parallel.ForEach(resultPropColl["member"].Cast ().ToList(), member =>  {    var memberEntry = new DirectoryEntry("LDAP://" + member);    var userProperties = memberEntry.Properties;    if (GetUserNameFromProperties(userProperties, "sAMAccountName") == userName)    {      return true; ...