1

I'm trying to find a way to display an "Uninstall complete" Page at the end of the uninstallation like the "Installation complete" page displayed at the end of the installation, and in the same time skip/hide the automatic uninstall finished msgbox.

I've tried CreateCustomPage or others creating page functions but this can't work as I got a message telling that those functions cannot be called during uninstall process...

So, is there a way to display (and take control of) such a page?

Or do I have to deal with the only uninstall finished msgbox?

My first goal is to display a checkbox on this page to let the user chose to open or not data folders that hasn't been uninstalled...

demonplus
  • 5,613
  • 12
  • 49
  • 68
BenDev
  • 349
  • 3
  • 18
  • What is the exact error message you received? – Sam Cohen-Devries Sep 08 '15 at 13:30
  • Thanks for having a check on my issue! I got Runtime Error: "Cannot call "CREATECUSTOMPAGE" function during Uninstall." – BenDev Sep 08 '15 at 13:34
  • Just a question about the reason why my post was edited to remove courtesy words... Is it wrong on the forum to say hello and to thank for any help upcoming? And why INNO-SETUP precision in the title should be wrong too? No offense, I'm just trying to understand behaviour code I need to know to fit right the forum here ;) – BenDev Oct 23 '15 at 12:58

3 Answers3

1

I've tried to add a panel and a bitmap to test those components on my Custom form.

I've got no error, the path in 'BitmapFileName' is ok, but neither the panel nor the bitmap are displayed :

procedure FormCheckOuvrirRepDonnees();
var
  Form: TSetupForm;
  OKButton: TNewButton;
  CheckBox: TNewCheckBox;
  Label1: TNewStaticText;
  Label2: TLabel;
  Panel: TPanel;
  BitmapImage: TBitmapImage;
  BitmapFileName: String;
begin
  Form := CreateCustomForm();
  try
    Form.ClientWidth := ScaleX(700);
    Form.ClientHeight := ScaleY(500);
    Form.Caption := ExpandConstant('{#MyAppName} {#MyAppVersion}');
    //Form.CenterInsideControl(WizardForm, False);
    Form.Center;

    Label1 := TNewStaticText.Create(Form);
    Label1.Parent := Form;
    //Label1.Width := Form.ClientWidth - ScaleX(2 * 10);
    Label1.AutoSize := true;
    Label1.Height := ScaleY(50);
    Label1.Left := ScaleX(325);
    Label1.Top := ScaleY(10);
    Label1.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonneeDescription1}');

    Label2 := TLabel.Create(Form);
    Label2.Parent := Form;
    //Label1.Width := Form.ClientWidth - ScaleX(2 * 10);
    Label2.AutoSize := true;
    Label2.Height := ScaleY(50);
    Label2.Left := ScaleX(325);
    Label2.Top := ScaleY(60);
    Label2.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonneeDescription1}');

    Panel := TPanel.Create(Form);
    Panel.Top := ScaleY(120);
    Panel.Width := Form.ClientWidth - ScaleX(2 * 10);
    Panel.Left := ScaleX(325);
    Panel.Height := ScaleY(50);
    Panel.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonneeDescription1}');
    Panel.Color := clWindow;
    //Panel.ParentBackground := False;
    //Panel.Parent := Form.Surface;

    BitmapImage := TBitmapImage.Create(Form);
    BitmapImage.Left := Form.left;
    BitmapImage.top := Form.top;
    BitmapImage.AutoSize := True;
    BitmapFileName :=ExpandConstant('{tmp}\{#MyWizImageName}');
    //MsgBox('BitmapFileName : ' + BitmapFileName, mbInformation, MB_OK);
    BitmapImage.Bitmap.LoadFromFile(BitmapFileName);
    //BitmapImage.Cursor := crHand;

    CheckBox := TNewCheckBox.Create(Form);
    CheckBox.Parent := Form;
    CheckBox.Width := Form.ClientWidth - ScaleX(2 * 10);
    CheckBox.Height := ScaleY(17);
    CheckBox.Left := ScaleX(325);
    CheckBox.Top := ScaleY(200);
    CheckBox.Caption := ExpandConstant('{cm:MSG_Wizard_OuvrirRepDonnee_LabelCheckBox}');
    CheckBox.Checked := False;

    OKButton := TNewButton.Create(Form);
    OKButton.Parent := Form;
    OKButton.Width := ScaleX(75);
    OKButton.Height := ScaleY(23);
    OKButton.Left := ((Form.ClientWidth - OKButton.Width)/2);
    OKButton.Top := Form.ClientHeight - ScaleY(23 + 10);
    OKButton.Caption := 'OK';
    OKButton.ModalResult := mrOk;
    OKButton.Default := True;

    //CancelButton := TNewButton.Create(Form);
    //CancelButton.Parent := Form;
    //CancelButton.Width := ScaleX(75);
    //CancelButton.Height := ScaleY(23);
    //CancelButton.Left := Form.ClientWidth - ScaleX(75 + 10);
    //CancelButton.Top := Form.ClientHeight - ScaleY(23 + 10);
    //CancelButton.Caption := 'Cancel';
    //CancelButton.ModalResult := mrCancel;
    //CancelButton.Cancel := True;

    Form.ActiveControl := OKButton;

    if Form.ShowModal = mrOk then begin
      if CheckBox.Checked = true then begin
        CheckOuvrirRepDonnees := true;
      end;
    end;

  finally
    Form.Free();
  end;
end;

Does someone has any idea what goes wrong there?

BenDev
  • 349
  • 3
  • 18
  • Ok, my bad! I just forgot to define the parent dépendancy : Panel.Parent := Form; BitmapImage.Parent := Form So eveything works well now! – BenDev Sep 10 '15 at 13:39
  • Nice to see that my hint with CreateCustomForm() + ShowModal() worked out. Glad you solved it. – Jens A. Koch Sep 10 '15 at 14:45
  • 1
    Yes, thanks a lot, I've checked your answer as a solved one as a token of gratitude ;) I'm new on stackoverflow and I'm glad to see that there are active people knowing about InnoSetup. I've switched from Installshield to InnoSetup only 2 weeks ago, and I'm just amazed at how powerful and easy to use InnoSetup is and how stable it seems to be compared to Installshield. – BenDev Sep 11 '15 at 07:15
  • Thank you :) - Welcome to StackOverflow! - Yes, InnoSetup is very mature and stable, while easy to extend at the same time. It has a helpful community and because its used in many projects, you may find a lot of code-snippets ready for usage on the web. – Jens A. Koch Sep 11 '15 at 10:28
  • 1
    Right! I've already found a lot of code-snippets and other tips or solution to common problems already asked I've encoutered. The first project conversion I've done from Installshield engine to InnoSetup engine is a full success! – BenDev Sep 11 '15 at 13:44
0

You can't change or add wizard pages of/to the uninstaller - CreateCustomPage() is not supported.

But you could show custom forms with CreateCustomForm() (instead of CreateCustomPage) and ShowModal() and display message boxes with MsgBox(), like so

[Code]
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then
  begin
    // this is MsgBox will display after uninstall
    if MsgBox('Go to data folder?', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then       
    begin
      // add some code to open the explorer with the folder here
      Exec(ExpandConstant('{win}\explorer.exe'), 'c:\data\folder', '', SW_SHOW, ewNoWait, ResultCode);
    end;
  end;
end;

If you want to display checkboxes, then CreateCustomForm() is the way to go.

Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
  • 1
    Thanks for your answer! Well I didn't know about CreateCustomForm() function. I'm gonna check this. About the alternative workaround with simple MessageBox, it was already written ;) – BenDev Sep 09 '15 at 07:49
0

You can try something like this code:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
DisableProgramGroupPage=yes
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes
DirExistsWarning=no             
DisableDirPage=yes                        

[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "{app}"
Source: "Readme.txt"; DestDir: "{app}";

#define AppName  SetupSetting('AppName')     
#define AppVersion  SetupSetting('AppVersion')
#define AppId  SetupSetting('AppId')             
#if AppId == ""   
  #define AppId AppName
#endif                     

[Code]       
var
  CustomPage: TWizardPage;                                     
  ResultCode:Integer;
  Source, Dest,Uninstall,ParamStr: String;
  CancelPrompt:Boolean;  
procedure CurStepChanged(CurStep: TSetupStep);      
begin
  if CurStep=ssPostInstall then begin
    Source := ExpandConstant('{srcexe}');
    Dest := ExpandConstant('{app}\unins001.exe');               
    Exec('cmd.exe', '/c COPY "'+Source+'" "'+Dest+'"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);    
  end;                                                                                                                                                                                                                      
end;

function IsUnInstall(): Boolean;
begin
  Result := Pos('/CUNINSTALL',UpperCase(GetCmdTail)) > 0;
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin                                  
  Result := False;
  if IsUnInstall() then begin
    if PageID <> wpWelcome then     
      case PageID of
        CustomPage.ID:;    
      else Result := True;
    end;
  end;
end;

procedure ExitButton(Sender: TObject);   
begin                   
    CancelPrompt:=False;       
    WizardForm.Close;                                             
    Source := ExpandConstant('{src}');                  
    Exec('cmd.exe', '/C rmdir /S /Q "'+Source+'"', '', SW_HIDE, ewNoWait, ResultCode);    
end;               

procedure CancelButtonClick(PageID: Integer; var Cancel, Confirm: Boolean); 
begin                                           
    Confirm:=CancelPrompt;                                                                                   
end;

function NextButtonClick(PageID: Integer): Boolean;            
begin
  Result := True;             
  if IsUnInstall() then begin   
    if PageID = wpWelcome then begin      
      RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1','UninstallString', Uninstall);
      Exec(RemoveQuotes(Uninstall), ' /RECAll /SILENT' , '', SW_SHOW, ewWaitUntilTerminated, ResultCode);      
    end;
  end;
end;     

function CreatePage(var Page:TWizardPage;PageId:Integer):Integer;    
begin
  Page := CreateCustomPage(PageId, ExpandConstant('AAA'),ExpandConstant('BBB'));           
end;     

procedure CurPageChanged(PageID: Integer);
begin                                       
  if IsUnInstall() then begin   
    if PageID = CustomPage.ID then begin          
      with WizardForm do begin      
        CancelButton.Left:= NextButton.Left;
        CancelButton.Caption:=ExpandConstant('Finish');                                
        CancelButton.OnClick := @ExitButton;
        NextButton.Visible := False;          
        BackButton.Visible := False;          
      end;          
    end;
  end;
end;

procedure InitializeWizard();          
begin
  if IsUnInstall() then
  begin                                        
    CreatePage(CustomPage,wpWelcome);
    with WizardForm do begin      
      WelcomeLabel1.Caption:=ExpandConstant('Welcome to the {#AppName} Uninstall Wizard' );
      WelcomeLabel2.Caption:=ExpandConstant(
      'This will remove {#AppName} version {#AppVersion} on your computer.' +#13+
      ''+#13+
      'It is recommended that you close all other applications before continuing.'+#13+
      ''+#13+
      'Click Next to continue, or Cancel to exit Setup.'
      );
    end;
  end;
end;

function InitializeUninstall(): Boolean;    
begin
  if FileExists(ExpandConstant('{app}\unins001.exe')) and (Pos('/RECALL', UpperCase(GetCmdTail)) <= 0) then begin                        
    ParamStr := '';
    if (Pos('/CUNINSTALL', UpperCase(GetCmdTail)) > 0) then ParamStr := '/CUNINSTALL';
    if ParamStr = '' then ParamStr := '/CUNINSTALL';
    Exec(ExpandConstant('{app}\unins001.exe'),  ParamStr, '', SW_SHOW, ewNoWait,ResultCode);
    Result := False;
  end else Result := True;
end;
IZB
  • 151
  • 5
  • Thanks a lot, I'm going to try this as the script taken like that really create a custom page at the end of the uninstall process. So I'm gonna check if I can adapt the part of script in my own script :) – BenDev Sep 09 '15 at 12:21
  • So, thanks IZB, but for now this code is a little too much for integration in my own project, and I cannot manage to create a finished page in the same display type as the welcome page. So for now I'm focused on the CreateCustomForm() way to do... – BenDev Sep 10 '15 at 07:20