This tool allows you to uninstall programs as well as see when they were installed. It lets you search through the apps. It can remove files left over by the program. It can clean clean the uninstall registry key.
To see how to use it just open the exe file.
program qinstall; {$apptype console} {$RESOURCE QINSTALL-32.RES} uses SysUtils,filectrl, windows,shellapi, Classes; const KiloBytes=1.0; MegaBytes=1024*kilobytes; GigaBytes=1024*megabytes; ERROR_REGOPENKEY='RegOpenKey: %s'; prompt_yesno='Type yes or no: '; filesize_fmt='#,##0.000'; reg_installdir='InstallLocation'; error_regdeletekey='RegDeleteKey: %s'; error_regqueryvalueex='RegQueryValueEx: %s'; var uninstallkey:hkey; appcount:dword; ftUninstall:filetime; Command_Switch:String; stinfo:systemtime; err:longint; function FormatLanguage(lpLang:pchar):string; var langs:tstringlist; begin langs:=tstringlist.Create; langs.CommaText:=stringreplace(lpLang,';',',',[rfReplaceall]); result:=langs[0]; langs.Free; end; function GetLanguageID(lang:word):string; var hklangs:hkey; rs:dword; langsz:array[0..4]of char; language:array[0..128]of char; begin rs:=129; regopenkey(hkey_classes_root,'MIME\Database\Rfc1766',hklangs); regqueryvalueex(hklangs,Strpcopy(langsz,inttohex(lang,4)),nil,nil,@language,@rs); regclosekey(hklangs);result:=formatlanguage(language); end; function FormatRegValue(const RegName:string;data:array of byte; DataType:dword):String; var x,y:extended; lpdw:pdword; lpStr:pchar; metric:char; begin lpdw:=@data[0]; lpstr:=@data[0]; result:=regname+':'; if lowercase(regname)='estimatedsize'then begin x:=lpdw^;metric:='K';y:=x; if x>=megabytes then begin y:=x/megabytes;metric:='M';end; if x>=gigabytes then begin y:=x/gigabytes;metric:='G';end; result:=result+formatfloat(filesize_fmt,y)+#32+Metric+'B'; end else if lowercase(regname)='language'then result:=result+GetLanguageID(lpdw^) else case datatype of reg_sz,reg_expand_sz:result:=regname+':'+strpas(lpstr); reg_dword:result:=regname+':'+inttostr(lpdw^); end; end; procedure listsoftware; var i,j:integer; st:systemtime; hkapp:hkey; ftinstalled:filetime; progname,vname:array[0..max_path]of char; value:array[0..2048]of byte; vcount,typ,rs,ns:dword; begin for i:=0to appcount-1do begin regenumkey(uninstallkey,i,progname,max_path); if(pos(lowercase(paramstr(2)),lowercase(progname))>0)or(paramcount=1)then begin writeln('AppName:',progname); regopenkey(uninstallkey,progname,hkapp); regqueryinfokey(hkapp,nil,nil,nil,nil,nil,nil,@vcount,nil,nil,nil,@ftinstalled); filetimetosystemtime(ftinstalled,st); writeln('Program installed: ',datetimetostr(systemtimetodatetime(st))); for j:=0to vcount-1 do begin ns:=max_path;rs:=2048;regenumvalue(hkapp,j,vname,ns, nil,@typ,@value,@rs);writeln(formatregvalue(vname,value,typ));end; regclosekey(hkapp);writeln; end; end; end; procedure uninstallinfo; begin writeln('Last Install/Uninstall: ',datetimetostr(systemtimetodatetime(stinfo))); writeln('There are ',formatfloat('#,###',appcount),' programs installed'); end; function execString(commandline:pchar):longint; var urlexec:shellexecuteinfo; confirm:string; label badconfirm,skipconfirm; begin result:=0; if lowercase(paramstr(4))='/yes'then confirm:='yes'; if confirm='yes' then goto skipconfirm; badconfirm:write(prompt_yesno); readln(confirm); if(confirm<>'yes')and(confirm<>'no')then goto badconfirm; if confirm='no'then exit; skipconfirm: result:=winexec(commandline,sw_show); if result<32 then begin zeromemory(@urlexec,sizeof(urlexec));urlexec.cbSize:= sizeof(urlexec);urlexec.fMask:=see_mask_nocloseprocess or see_mask_flag_no_ui; result:=33;urlexec.lpFile:=commandline;urlexec.nShow:=sw_show; if not shellexecuteex(@urlexec)then begin result:=urlexec.hInstApp;exit;end; waitforsingleobject(urlexec.hprocess,infinite);closehandle(urlexec.hProcess); end; end; function removetree(const Dir:string):longint; var comspec,params:array[0..max_path+15]of char; shellexec:shellexecuteinfo; begin getenvironmentvariable('ComSpec',comspec,max_path+15); zeromemory(@shellexec,sizeof(shellexec)); shellexec.cbsize:=sizeof(shellexec); shellexec.lpfile:=comspec; shellexec.lpparameters:=strplcopy(params,'/C RD /S /Q "'+dir+'"',max_path+15); shellexec.fMask:=see_mask_nocloseprocess or see_mask_no_console or SEE_MASK_FLAG_NO_UI; shellexec.nShow:=sw_show; result:=33; if not shellexecuteex(@shellexec)then begin result:=shellexec.hInstApp;exit;end; waitforsingleobject(shellexec.hprocess,infinite); closehandle(shellexec.hProcess); end; procedure RemoveFiles; var confirm:string; installdir,progname:array[0..max_path]of char; rs:dword; hkapp:hkey; err:longint; label badconfirm1,skipwarning; begin if paramcount<2 then raise exception.Create('Need more parameters'); err:=regopenkey(uninstallkey,strplcopy(progname,paramstr(2),max_path),hkapp); if err<>error_success then raise exception.CreateFmt(Error_regopenkey,[ syserrormessage(err)]); rs:=max_path+1; err:=regqueryvalueex(hkapp,reg_installdir,nil,nil,@installdir,@rs); if err<>error_success then raise exception.CreateFmt(ERROR_REGQUERYVALUEEX,[ syserrormessage(err)]); if uppercase(paramstr(3))='/YES'then confirm:='yes'; if confirm='yes'then goto skipwarning; writeln('Warning you are about to delete everything in "',installdir,'" continue?'); badconfirm1: write(prompt_yesno);readln(confirm);confirm:=lowercase(confirm); skipwarning: case confirm[1] of 'y':begin removetree(installdir);regclosekey(hkapp);err:=regdeletekey( uninstallkey,progname);if err<>error_success then writeln(error_regdeletekey, syserrormessage(err));exit;end; 'n':writeln('Deletion canceled'); end; regclosekey(hkapp); end; procedure cleanregistry; var szPath,progname:array[0..max_path]of char; hkapp:hkey; rs:dword; i:integer; err:longint; begin for I:=0to appcount-1do begin regenumkey(uninstallkey,i,progname,max_path); strcopy(szpath,'');rs:=max_path+1;regopenkey(uninstallkey,progname,hkapp); regqueryvalueex(hkapp,reg_installdir,nil,nil,@szpath,@rs);regclosekey(hkapp); if(strlen(szPath)>0)and(not directoryexists(szpath))then begin err:=regdeletekey( uninstallkey,progname);if err<>error_success then writeln('Found:',progname,' - ', syserrormessage(err)); end; end; end; procedure searchexec; var hkapp:hkey; progname,cmdline1,cmdline2,szName:array[0..max_path]of char; typ,err,rs:dword; i:integer; begin if paramcount<3then raise Exception.Create('Need search_text and method strings'); strpcopy(szName,paramstr(2)); for i:=0to appcount-1do begin regenumkey(uninstallkey,i,progname,max_path); if pos(lowercase(paramstr(3)),lowercase(progname))>0then begin writeln('Found:', progname); err:=regopenkey(uninstallkey,progname,hkapp); if err<>error_success then raise exception.CreateFmt(error_regopenkey,[ syserrormessage(err)]); rs:=max_path+1; err:=regqueryvalueex(hkapp,szname,nil,@typ,@cmdline1,@rs); if err<>error_success then begin regclosekey(hkapp);raise exception.CreateFmt( error_regqueryvalueex,[syserrormessage(err)]);end; case typ of reg_sz:strcopy(cmdline2,cmdline1); reg_expand_sz:expandenvironmentstrings(cmdline1,cmdline2,max_path); else raise exception.CreateFmt('The value "%s" is not a REG_SZ or REG_EXPAND_SZ value',[ paramstr(2)]); end;//case end err:=execstring(cmdline2); if(err<33)and(err>0)then writeln('ExecError:',syserrormessage(err)); regclosekey(hkapp); end; end; end; begin if paramcount=0then begin writeln('Usage: ',extractfilename(paramstr(0)),' [/LIST "seach_text"] [/EXEC "method" "search_text" [/YES]] [/REM "appname" [/YES]] [/CLEAN] [/INFO]'); writeln('Parameters:'); writeln('/LIST Lists software that is installed on here. The next parameter is the optional search text.'); writeln('/EXEC Executes a string found in the app that matches ["search_text"]'); writeln('method string can be QuietUninstallString,UninstallString,URLInfoAbout,HelpLink,URLUpdateInfo, or Readme'); writeln('/CLEAN Removes any uninstaller registry information left over by an uninstalled program.'); writeln('/INFO Shows last install/uninstall information'); writeln('/REM Remove the directory of files left over. This should be used only when the program fails to uninstall. To uninstall a program use /EXEC command switch with "UninstallString" as the method'); writeln('/YES Automatically use yes option on prompts'); write('Press enter to return...');readln;exitprocess(0); end; try err:=regopenkey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',uninstallkey); if err<>error_success then raise exception.CreateFmt(error_regopenkey,[ syserrormessage(err)]); err:=regqueryinfokey(uninstallkey,nil,nil,nil,@appcount,nil,nil,nil,nil,nil,nil, @ftuninstall);filetimetosystemtime(ftuninstall,stinfo); if err<>error_success then raise exception.CreateFmt('RegQueryInfoKey: %s',[ syserrormessage(err)]); command_switch:=uppercase(paramstr(1)); if '/LIST'=command_switch then listsoftware else if '/INFO'=command_switch then uninstallinfo else if '/EXEC'=command_switch then searchexec else if '/REM'=command_switch then removefiles else if '/CLEAN'=command_switch then cleanregistry else writeln('Unknown command "',paramstr(1),'"'); except on e:exception do writeln(e.message);end; regclosekey(uninstallkey); end.