[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 do 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 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 + 'Do 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 SkipAllReadOnly) then if DelMsgBox(SR.Name) then Exec('attrib', ' -h -s -r ' + '"' + str + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); if DelAllReadOnly then Exec('attrib', ' -h -s -r ' + '"' + str + '"', '', SW_HIDE, ewWaitUntilTerminated, 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 be removed.' + #10#13 + 'These can be removed manually.' + #10#13#13 + 'Choose which are 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;