Windows MSI File Clean Remove ProductName
Jump to navigation
Jump to search
Contents
Purpose
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
- looks in the registry for a ProductName matching what you give it
- 'decyphers' the GID from the ProductCode
- runs the gid against msiexec to try and cleanly uninstall it
- runs the gid against msizap to remove what the above failed too
- 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,
- then removes any remaining .msi files in the Windows Installer cache.
Code
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SETLOCAL ENABLEEXTENSIONS
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
pause
exit
) 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 -------------------------------
:go
set n=0
set rstr=
call :rev %1
goto :end
:rev
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 -------------------------------
:start
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
pause
goto :end
: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 . . .