I have a common application -like a media player- for each different retail product that is installed in the same folder i.e.
C:\program files\myapp
and the different content -like movies- are all installed in the same folder
C:\program files\myapp\movies
For each separate installation (separate retail product), I just create a shortcut to open the application with the specific content like mediaplayer -f movie1.mp4
, but it can open all other content from the same environment.
The problem in my case, is the uninstallation. Inno Setup does not support component selection to uninstall.
My strategy (in my mind at the time) is to present the user a custom form to select the content to uninstall. For example.
[X] Main Application
[X] Movie1 Full Title Description
[X] Movie2 Full Title Description
[X] Movie3 Full Title Description
With that way the common uninstall will work for every separate retail installation.
The problems
- How to create such a form
- How to scan the common shared folder i.e.
movies
for this example to find all installed content i.e. movie1.mp4
, movie2.mp4
, .....
- How to open and read the header of each movie to read some data like the full title to show it in the uninstallation procedure instead of the filename.
I used to write Pascal code at the DOS era but I now I am a C++/MFC programmer.
Any ideas, recommendations, strategies?
Best regards.
Inno Setup does not support partial uninstallations.
Once the uninstallation completes, your whole application with all installed components (movies) will be deleted.
What you can do is to present a custom form with movies list in the InitializeUninstall
. If the user chooses to uninstall only (some) movies, but not whole application (the viewer), you delete the movies with your own code and abort the uninstallation (by returning False
from the InitializeUninstall
). If the user chooses to uninstall everything, you let the uninstallation complete.
function InitializeUninstall(): Boolean;
var
Form: TSetupForm;
OKButton, CancelButton: TNewButton;
CheckListBox: TNewCheckListBox;
I, Count, Deleted: Integer;
FindRec: TFindRec;
MoviePath: string;
Movies: TArrayOfString;
begin
MoviePath := ExpandConstant('{app}\movies\');
Count := 0;
if FindFirst(MoviePath + '*', FindRec) then
begin
try
repeat
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin
Inc(Count);
SetArrayLength(Movies, Count);
Movies[Count - 1] := FindRec.Name;
end;
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
if Count = 0 then
begin
Log('Found no movies proceeding with a complete uninstallation');
Result := True;
end
else
begin
Log(Format('Found %d movies', [Count]));
Form := CreateCustomForm();
try
Form.ClientWidth := ScaleX(350);
Form.ClientHeight := ScaleY(250);
Form.Caption := 'Uninstall';
Form.Position := poDesktopCenter;
CheckListBox := TNewCheckListBox.Create(Form);
CheckListBox.Parent := Form;
CheckListBox.Left := ScaleX(10);
CheckListBox.Width := Form.ClientWidth - 2*CheckListBox.Left;
CheckListBox.Top := ScaleY(10);
CheckListBox.Height := Form.ClientHeight - ScaleY(23 + 10 + 10 + CheckListBox.Top);
CheckListBox.AddCheckBox(
'Uninstall viewer and all movies', '', 0, True, True, True, True, nil);
for I := 0 to Count - 1 do
begin
CheckListBox.AddCheckBox(Movies[I], '', 1, True, True, False, True, nil);
end;
OKButton := TNewButton.Create(Form);
OKButton.Parent := Form;
OKButton.Width := ScaleX(75);
OKButton.Height := ScaleY(23);
OKButton.Left := Form.ClientWidth - ScaleX(75 + 6 + 75 + 10);
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 := OKButton.Width;
CancelButton.Height := OKButton.Height;
CancelButton.Left := OKButton.Left + OKButton.Width + ScaleX(6);
CancelButton.Top := OKButton.Top;
CancelButton.Caption := 'Cancel';
CancelButton.ModalResult := mrCancel;
CancelButton.Cancel := True;
Form.ActiveControl := CheckListBox;
if Form.ShowModal() <> mrOk then
begin
Log('User cancelled the uninstallation');
Result := False;
end
else
begin
if CheckListBox.State[0] = cbChecked then
begin
Log('User selected complete uninstallation');
Result := True;
end
else
begin
for I := 0 to Count - 1 do
begin
if CheckListBox.Checked[I + 1] then
begin
if DeleteFile(MoviePath + Movies[I]) then
begin
Inc(Deleted);
Log(Format('Deleted movie %s', [Movies[I]]));
end
else
begin
MsgBox(Format('Error deleting %s', [Movies[I]]), mbError, MB_OK);
end;
end;
end;
MsgBox(Format('Deleted %d movies', [Deleted]), mbInformation, MB_OK);
Result := False;
end;
end;
finally
Form.Free();
end;
end;
end;