Introduction
I have a problem where I periodically have to rollback many machines on the network to an older version of our software (distributed as MSI package).
Thus I made a simple console application that can run from a BAT script or similar. It allows me to uninstall MSI packages on a computer, even when I don't know exactly which version is currently installed on the machine. And further, if the correct (old version) is already installed, I can skip the uninstallation of the package.
Using the Code
The MSIUninstaller.exe calls the Microsoft MsiExec.exe to handle the actual uninstallation of the MSI package.
It looks up all the installed packages in the registry database under
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall.
Then it loops through them to find the packages, which match the specific input parameters and then they are uninstalled.
The program allows you to specify input parameters like quiet, log and wild cards.
This function shows the primary functionality of the program:
Sub Process(ByVal DisplayName As String, ByVal bUninstall As Boolean, _
ByVal bDisplay As Boolean, ByVal bQuiet As Boolean, ByVal bLog As Boolean, _
ByVal strSkip As String)
Dim names As String() = m_rKey.GetSubKeyNames
Dim version As String = ""
Dim publisher As String = ""
Dim dispName As String = ""
Dim iFound As Integer
For Each s As String In names
dispName = GetKeyValue(s, "DisplayName")
If dispName <> "" Then
If WildCardCompare(dispName, DisplayName) Then
version = GetKeyValue(s, "DisplayVersion")
publisher = GetKeyValue(s, "Publisher")
If strSkip <> "none" And WildCardCompare(version, strSkip) Then
Continue For
End If
Dim cmd As String = Environment.SystemDirectory.ToString + _
"\MsiExec.exe /x " + s
If bQuiet Then
cmd += " /qn"
End If
If bLog Then
cmd += " /lie+c:\MSIUninstaller.log.txt"
End If
If Not bDisplay Then
Console.WriteLine("Publisher = " + publisher)
Console.WriteLine("DisplayName = " + dispName)
Console.WriteLine("version = " + version)
Console.WriteLine("GUID = " + s)
Console.WriteLine("EsitmatedSize = " + (CDbl(GetKeyValue_
(s, "EstimatedSize")) / 1024).ToString("N2") + " Mb")
Dim dato As String = GetKeyValue(s, "InstallDate")
dato = dato.Substring(6) + "-" + dato.Substring(4, 2) + _
"-" + dato.Substring(0, 4)
Console.WriteLine("InstallDate = " + CDate(dato).ToString_
("dd-MMM-yyy"))
Console.WriteLine("InstallSource = " + GetKeyValue_
(s, "InstallSource") + vbLf)
End If
If bUninstall Then
Shell(cmd)
End If
iFound += 1
End If
End If
Next s
If Not bQuiet And iFound = 0 Then
Console.WriteLine(DisplayName + " was not found in HKEY_LOCAL_MACHINE\_
Software\Microsoft\Windows\CurrentVersion\Uninstall _
on this computer" + vbLf)
End If
End Sub
Private Function GetKeyValue(ByVal keyName As String, ByVal valueName As String) _
As String
Dim obj As Object = m_rKey.OpenSubKey(keyName).GetValue(valueName)
If Not obj Is Nothing Then
Return obj
Else
Return ""
End If
End Function
Private Function WildCardCompare(ByVal strInput As String, _
ByVal strWildCard As String) As Boolean
strWildCard = "^" + Regex.Escape_
(strWildCard).Replace("\*", ".*").Replace("\?", ".") + "$"
Return Regex.IsMatch(strInput, strWildCard, RegexOptions.IgnoreCase)
End Function
History
- 7th August, 2008: Initial post