Windows MSI File Clean Remove ProductName

Jump to: navigation, search


To cleanly remove an MSI installed item, save this as a file, then pass a reasonable part of the ProductName to it, to remove. See the example at the bottom for usage. It will remove multiple items if the partial ProuctName matches.

  • Relies on msizap.exe and msiinfo.exe [both from "Windows SDK Components for Windows Installer Developers"]
  • The great thing about this is you dont need to know the GID in advance. I developed this for removing Flash Player mainly. See the separate page about that as it does some other things too.

How it works

In a nutshell, it

  1. looks in the registry for a ProductName matching what you give it
  2. 'decyphers' the GID from the ProductCode
  3. runs the gid against msiexec to try and cleanly uninstall it
  4. runs the gid against msizap to remove what the above failed too
  5. finally tries to remove the registry keys that usually block a reinstall working if above two fail, these use the PackageCode and GID depending on where they are,
  6. then removes any remaining .msi files in the Windows Installer cache.


@echo off

rem ProductName to remove as named in HKLM\SOFTWARE\Classes\Installer\Products
if [%1] == [] (
	echo Please supply command line arguement for ProductName to remove, enclosed in double quotes if spaced
) else (
	set i=%1
	set prodname=!i:"=!

rem Log output
set log=%temp%\%prodname%-remove-log.txt
goto start

rem -------------------------------
rem Package Code to GID conversion
rem -------------------------------
set n=0
set rstr=
call :rev %1
goto :end
set str=%1
call set t=%%str:~%n%,1%%%
set /a n+=1
if not "%t%" equ "" (
	set rstr=%t%%rstr%
	goto rev
) else (
	set gid=%gid%%rstr%
goto :end

rem -------------------------------
rem Main Cleaning Program
rem -------------------------------
for /F "delims=" %%i in ('reg query "HKLM\SOFTWARE\Classes\Installer\Products" ^| findstr Products\') do (
	reg query "%%i" /v ProductName | findstr /c:"!prodname!" >> "!log!"
	if [!errorlevel!] == [0] (
		set gid=
		set p=%%i
		set pc=!p:~55,32!
		call :go -!p:~55,8!
		call :go -!p:~63,4!
		call :go -!p:~67,4!
		call :go !p:~71,2!
		call :go -!p:~73,2!
		call :go !p:~75,2!
		call :go !p:~77,2!
		call :go !p:~79,2!
		call :go !p:~81,2!
		call :go !p:~83,2!
		call :go !p:~85,2!
		set gid={!gid!}
		echo Requested ProductName !prodname! found
		echo Please wait, removing PackageCode:!pc! GID:!gid!
		msiexec /x !gid! /qn /L* "!log!-msiexec.txt"
		%~dp0msizap.exe TWAP !gid! >> "!log!" 2>&1
		reg delete HKLM\SOFTWARE\Classes\Installer\Products\!pc! /f >> "!log!" 2>&1
		reg delete HKLM\SOFTWARE\Classes\Installer\Features\!pc! /f >> "!log!" 2>&1
		reg delete HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\!gid! /f >> "!log!" 2>&1
		reg delete HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\!pc! /f >> "!log!" 2>&1
		echo Removing associated Windows Installer files
		for /f "delims=" %%a in ('dir /b "%windir%\installer\*.msi"') do (
			%~dp0msiinfo.exe "%windir%\installer\%%a" | findstr /c:"!prodname!" > nul
			if [!errorlevel!] == [0] (
				echo Found and deleted "%windir%\installer\%%a"
				del /f /q "%windir%\installer\%%a" >> "!log!" 2>&1
echo Finished processing %prodname%
echo Please check the log: %log% for details
goto :end

Example Usage

e.g. To remove a Microsoft C++ 2005 redistributable (any version).

Use quotes for the ProductName, it will match a partial string but words must be adjacent, e.g. ProductName-remove.bat "2005 Redistributable"

C:\>ProductName-remove.bat "2005 Redistributable"
Requested ProductName 2005 Redistributable found
Please wait, removing PackageCode:b25099274a207264182f8181add555d0 GID:{7299052b-02a4-4627-81f2-1818da5d550d}
Removing associated Windows Installer files
Finished processing 2005 Redistributable
Please check the log: c:\Temp\2005 Redistributable-remove-log.txt for details
Press any key to continue . . .