Original: Inno Setup uninstaller Add a custom form
[Setup] Appname=my Program Appvername=my program v.1.2 defaultdirname={pf}/my program [Files] source:files/*; DestDir: {app} [Code] const Biddelall = 1; Bidskipall = 2; var form:tsetupform; Checklistbox:tnewchecklistbox; Allbutton, Unallbutton:tbutton; CancelButton, Delbutton:tbutton; Statictext:tnewstatictext; Msgform:tsetupform; Msgallbutton, Msgskipallbutton:tbutton; Msgcancelbutton, Msgdelbutton:tbutton; Delallreadonly:boolean; Skipallreadonly:boolean; Checkdirs, Checkfiles:boolean; function Size64 (Hi, Lo:integer): Extended; var I:integer; Begin result:= Lo; If Lo < 0 then result:= Result + 2147483647 + 2147483647 + 2; I:= Hi; While i > 0 does begin result:= Result + 2147483647 + 2147483647 + 2; I:= i-1; End End Procedure Filllistbox (const fromdir, filemask:string; Level:byte); var FSR, Dsr:tfindrec; Findresult:boolean; apath:string; I:integer; Begin Apath: = Addbackslash (fromdiR); Findresult: = FindFirst (Apath + filemask, FSR); Try while Findresult and checkfiles the do begin if FSR. Attributes and file_attribute_directory = 0 THEN begin {files} i:= Checklistbox.addcheckbox (FSR. Name, Floattostr (Size64 (FSR. Sizehigh, FSR. Sizelow)) + ' byte ', level, true, True, False, true, tstringlist.create); TStrings (Checklistbox.itemobject[i]). text:= Apath + FSR. Name; End Findresult: = FindNext (FSR); End Findresult: = FindFirst (Apath + ' *. * ', DSR); While Findresult and checkdirs do begin checkfiles:= True; if (DSR. Attributes and file_attribute_directory) = File_attribute_directory) and not (DSR. Name = '. ') or (DSR. Name = '.. ')) Then begin {Dir} i:= Checklistbox.addcheckbox (DSR. Name, ' DIR ', level, true, True, False, true, tstringlist.create); TStrings (Checklistbox.itemobject[i]). text:= Apath + DSR. Name; {Recursion} filllistbox (Apath + DSR. Name, Filemask, level+1); End Findresult: = FindNext (DSR); End Finally FindClose (FSR); FindClose (DSR); End End Procedure Buttononclick (Sender:tobject); Begin if TButton (Sender). Tag = 0 Then Checklistbox.checkitem (0, Cocheckwithchildren) Else Checklistbox.checkitem (0, Councheck); End Procedure Msgbuttononclick (Sender:tobject); Begin Case TButton (Sender). Tag of biddelall:delallreadonly:= True; Bidskipall:skipallreadonly:= True; End Msgform.close; End function Delmsgbox (filename:string): Boolean; var Msglabel:tlabel; Begin msgform:= Createcustomform; Msgform.clientwidth: = ScaleX (400); Msgform.clientheight: = ScaleY (120); Msgform.caption: = ' Files to delete '; Msgform.center; Msglabel: = Tlabel.create (Msgform); Msglabel.left: = ScaleX (20); Msglabel.top: = ScaleY (20); msglabel.caption:= FileName + ' is protected file or directory! ' + #10 #10#13 + ' does you want to deletE The file with READONLY attribute? '; Msglabel.parent: = Msgform; Msgallbutton: = Tbutton.create (Msgform); Msgallbutton.parent: = Msgform; Msgallbutton.width: = ScaleX (75); Msgallbutton.height: = ScaleY (23); Msgallbutton.left: = ScaleX (20); Msgallbutton.top: = Msgform.clientheight-scaley (23 + 10); Msgallbutton.caption: = ' Delete all '; Msgallbutton.tag:= Biddelall; Msgallbutton.onclick: = @MsgButtonOnClick; Msgskipallbutton: = Tbutton.create (Msgform); Msgskipallbutton.parent: = Msgform; Msgskipallbutton.width: = ScaleX (75); Msgskipallbutton.height: = ScaleY (23); Msgskipallbutton.left: = msgallbutton.left + msgallbutton.width + ScaleX (10); Msgskipallbutton.top: = Msgform.clientheight-scaley (23 + 10); Msgskipallbutton.caption: = ' Skip all '; Msgskipallbutton.tag:= Bidskipall; Msgskipallbutton.onclick: = @MsgButtonOnClick; Msgcancelbutton: = Tbutton.create (Msgform); Msgcancelbutton.parent: = Msgform; Msgcancelbutton.width: = ScaleX (75); MSgcancelbutton.height: = ScaleY (23); Msgcancelbutton.left: = Msgform.clientwidth-msgcancelbutton.width-scalex (20); Msgcancelbutton.top: = Msgform.clientheight-scaley (23 + 10); Msgcancelbutton.caption: = ' Skip '; Msgcancelbutton.modalresult: = Mrcancel; Msgdelbutton: = Tbutton.create (Msgform); Msgdelbutton.parent: = Msgform; Msgdelbutton.width: = ScaleX (75); Msgdelbutton.height: = ScaleY (23); Msgdelbutton.left: = Msgcancelbutton.left-msgdelbutton.width-scalex (10); Msgdelbutton.top: = Msgform.clientheight-scaley (23 + 10); Msgdelbutton.caption: = ' Delete '; Msgdelbutton.modalresult: = Mrok; Msgform.activecontrol:= Msgcancelbutton; If Msgform.showmodal () = Mrok then result:= True else result:= False; End Procedure Deletefiles (); var Sr:tfindrec; I:integer; str:string; Resultcode:integer; Begin delallreadonly:= False; Skipallreadonly:= False; For i:= checklistbox.items.count-1 Downto 0 DO BEGIN if Checklistbox.staTe[i] = cbchecked THEN BEGIN str:= Trim (TStrings (checklistbox.itemobject[i)). Text); FindFirst (str, SR); if (SR. Attributes and file_attribute_readonly) = file_attribute_readonly) Then if not (Delallreadonly or Skipallreado nly) Then if Delmsgbox (SR. Name) then Exec (' attrib ', '-h-s-R ' + ' "' + str + '" ', ' ', Sw_hide, ewwaituntiltermin Ated, ResultCode); If Delallreadonly then Exec (' attrib ', '-h-s-R ' + ' "' + str + '" ', ' ", Sw_hide, Ewwai tuntilterminated, ResultCode); FindClose (SR); DeleteFile (str); RemoveDir (str); End End End Procedure Browseremainedfiles (); Begin form:= Createcustomform; Form.clientwidth: = ScaleX (400); Form.clientheight: = ScaleY (400); Form.caption: = ' Files to delete '; Form.center; Statictext: = Tnewstatictext.create (Form); statictext.left:= ScaleX (20); StaticText.top: = ScaleY (8); Statictext.caption: = ' Some elements could not being removed. ' + #10 #13 + ' These can be removed Manua lly. ' + #10 #13#13 + ' Choose which is necessary to delete ' + #10 #13 + ' or Press Cancel button. '; Statictext.font.color:= Clblue; statictext.font.style:= [Fsbold]; Statictext.autosize: = True; Statictext.parent: = Form; Checklistbox: = Tnewchecklistbox.create (Form); checklistbox.left:= ScaleX (20); checklistbox.top:= ScaleY (20); checklistbox.width:= Form.clientwidth-scalex (20*2); checklistbox.height:= Form.clientheight-scaley (23*2 + 20); checklistbox.offset:= 0; Checklistbox.parent:= Form; Allbutton: = Tbutton.create (Form); Allbutton.parent: = Form; Allbutton.width: = ScaleX (75); Allbutton.height: = ScaleY (23); Allbutton.left: = ScaleX (20); Allbutton.top: = Form.clientheight-scaley (23 + 10); Allbutton.caption: = ' Select all '; allbutton.tag:= 0; AlLbutton.onclick: = @ButtonOnClick; Unallbutton: = Tbutton.create (Form); Unallbutton.parent: = Form; Unallbutton.width: = ScaleX (75); Unallbutton.height: = ScaleY (23); Unallbutton.left: = allbutton.left + allbutton.width + ScaleX (10); Unallbutton.top: = Form.clientheight-scaley (23 + 10); Unallbutton.caption: = ' Clear all '; Unallbutton.tag:= 1; Unallbutton.onclick: = @ButtonOnClick; CancelButton: = Tbutton.create (Form); Cancelbutton.parent: = Form; Cancelbutton.width: = ScaleX (75); Cancelbutton.height: = ScaleY (23); Cancelbutton.left: = Form.clientwidth-cancelbutton.width-scalex (20); Cancelbutton.top: = Form.clientheight-scaley (23 + 10); Cancelbutton.caption: = ' Cancel '; Cancelbutton.modalresult: = Mrcancel; Cancelbutton.cancel: = True; Delbutton: = Tbutton.create (Form); Delbutton.parent: = Form; Delbutton.width: = ScaleX (75); Delbutton.height: = ScaleY (23); Delbutton.left: = Cancelbutton.left-delbutton.width-scalex (10); DelbUtton. Top: = Form.clientheight-scaley (23 + 10); Delbutton.caption: = ' Delete '; Delbutton.modalresult: = Mrok; Form.activecontrol:= CancelButton; Checklistbox.addcheckbox (Expandconstant (' {app} '), ', ', 0, True, True, False, true, tstringlist.create); TStrings (Checklistbox.itemobject[0]). text:= Expandconstant (' {app} '); Checkdirs:= True; Filllistbox (Expandconstant (' {app} '), ' * ', 1); Checkdirs:= False; Filllistbox (Expandconstant (' {app} '), ' * ', 1); If Form.showmodal () = Mrok then Deletefiles (); End Procedure curuninstallstepchanged (Curuninstallstep:tuninstallstep); Begin If Direxists (Expandconstant (' {app} ')) and (Curuninstallstep = Uspostuninstall) then Browseremainedfiles (); End
Add a custom form to the Inno Setup uninstaller