I have an installation file for my app and it contains the .exe file and a .zip file as well.
What I want is:
Recently I added a code in the [Code] section that is extracting files from zip, But actually, it happened after the installation is done, and the progress bar is 100%, So what I want is to make that code's (unzipping) process work with the progress bar and show the user what is extracting at the moment.
For example: let's say extracting files will take 50% of the progress bar and the rest will take it the code section while it is unzipping, with the state about what is extracting at the moment.
Here is the code:
[Code]
procedure InitializeWizard;
begin
ForceDirectories(ExpandConstant('{localappdata}\folder-A\app\folder-B'))
end;
const
SHCONTCH_NOPROGRESSBOX = 4;
SHCONTCH_RESPONDYESTOALL = 16;
procedure unzip(ZipFile, TargetFldr: variant);
var
shellobj: variant;
SrcFldr, DestFldr: variant;
shellfldritems: variant;
begin
if FileExists(ZipFile) then begin
if not DirExists(TargetFldr) then
if not ForceDirectories(TargetFldr) then begin
MsgBox('Can not create folder '+TargetFldr+' !!', mbError, MB_OK);
Exit;
end;
shellobj := CreateOleObject('Shell.Application');
SrcFldr := shellobj.NameSpace(ZipFile);
DestFldr := shellobj.NameSpace(TargetFldr);
shellfldritems := SrcFldr.Items;
DestFldr.CopyHere(
shellfldritems, SHCONTCH_NOPROGRESSBOX or SHCONTCH_RESPONDYESTOALL);
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
unzip(ExpandConstant('{app}\example.zip'),ExpandConstant('{app}\'));
end;
end;
The easiest solution is to use the WizardForm.StatusLabel:
WizardForm.StatusLabel.Caption := 'Extracting...';
For more fancy solution you can use TOutputProgressWizardPage. For an example that even displays a progress bar (though by using a DLL for the extraction), see:
Inno Setup - How to add cancel button to decompressing page?
This post lists more related examples:
Inno Setup: How to modify long running script so it will not freeze GUI?
Related
I made a custom wizard page, and I want it to show a sort of installation checklist at the end of the install, showing what installed successfully or not.
Something like
Crucial Step......................SUCCESS
Optional Step.....................FAILURE
So I have this code in my initializeWizard()
Page := CreateCustomPage(wpInstalling, 'Installation Checklist', 'Status of all installation components');
RichEditViewer := TRichEditViewer.Create(Page);
RichEditViewer.Width := Page.SurfaceWidth;
RichEditViewer.Height := Page.SurfaceHeight;
RichEditViewer.Parent := Page.Surface;
RichEditViewer.ScrollBars := ssVertical;
RichEditViewer.UseRichEdit := True;
RichEditViewer.RTFText := ''// I want this attribute to be set in CurStepChanged()
Is there a way to add or edit RichEditViewer.RTFText at a later point in time? Page is a global variable but trying to access any attributes gives me an error. I'd like to do edit the text after wpInstalling, so I can tell whether or not install steps were successful.
I'm not a huge fan of this method, but you Can set your RichEditViewer as a global, and then editing it at any point, in any function, is trivial.
var
RichEditViewer: TRichEditViewer;
procedure InitializeWizard();
var
Page: TWizardPage;
begin
Page := CreateCustomPage(wpInstalling, 'Installation Checklist', '');
RichEditViewer := TRichEditViewer.Create(Page);
RichEditViewer.Width := Page.SurfaceWidth;
RichEditViewer.Height := Page.SurfaceHeight;
RichEditViewer.Parent := Page.Surface;
RichEditViewer.ScrollBars := ssVertical;
RichEditViewer.UseRichEdit := True;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep=ssPostInstall then RichEditViewer.RTFText := 'STUFF';
end;
Worthwhile to note, the page itself doesn't even need to be global.
I'm currently creating an installer, which has Program Files as its default installation directory. To do this, I used {pf}.
It's a German program and only used in Germany and while the installer is entirely in German during selection of the destination directory, setup still displays C:\Program Files instead of the localized name C:\Programme.
Is it possible to get it to display C:\Programme instead? Functionally everything works fine, the application is installed in C:\Programme. I'm just concerned a basic user may be confused by reading C:\Program Files.
EDIT: Further information: I know C:\Programme or any other localized name for Program Files is just a display name, the physical path is always Program Files. Doesn't matter which Windows version or what language Windows has. Yet I'd still like setup to display C:\Programme during installation.
My test machines are on Windows 7 and Windows 10.
Inno Setup does not support that.
You would have to fake it. You can dynamically translate contents of the DirEdit to/from a display name as needed:
translate to display name, when the "Select Destination Location" page is activated
translate to physical path, when "Browse" button is clicked.
translate to display name, when new path is selected.
translate to physical path, when "Next" button is clicked.
function ToDisplayName(Path: string): string;
begin
Result := ???;
end;
function FromDisplayName(Path: string): string;
begin
Result := ???;
end;
var
DirBrowseButtonClickOrig: TNotifyEvent;
OnSelectDir: Boolean;
procedure DirBrowseButtonClick(Sender: TObject);
begin
WizardForm.DirEdit.Text := FromDisplayName(WizardForm.DirEdit.Text);
DirBrowseButtonClickOrig(Sender);
WizardForm.DirEdit.Text := ToDisplayName(WizardForm.DirEdit.Text);
end;
procedure InitializeWizard();
begin
DirBrowseButtonClickOrig := WizardForm.DirBrowseButton.OnClick;
WizardForm.DirBrowseButton.OnClick := #DirBrowseButtonClick;
OnSelectDir := False;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if CurPageID = wpSelectDir then
begin
OnSelectDir := True;
WizardForm.DirEdit.Text := ToDisplayName(WizardForm.DirEdit.Text);
end
else
begin
if OnSelectDir then
begin
OnSelectDir := False;
WizardForm.DirEdit.Text := FromDisplayName(WizardForm.DirEdit.Text);
end;
end;
end;
A tricky part is of course the implementation of the ToDisplayName and FromDisplayName functions.
A real native implementation would be pretty complex and it's even questionable if you can implement it with limited features of the Pascal Script (particularly a lack of pointers).
But for your specific needs, you can use something as trivial as:
[CustomMessages]
ProgramFilesLocalized=Programme
[Code]
function ToDisplayName(Path: string): string;
begin
StringChange(Path, '\Program Files', '\' + CustomMessage('ProgramFilesLocalized'));
Result := Path;
end;
function FromDisplayName(Path: string): string;
begin
StringChange(Path, '\' + CustomMessage('ProgramFilesLocalized'), '\Program Files');
Result := Path;
end;
If you need a real implementation for converting to/from display name, consider asking a separate question.
My problem is that i would like to make an "hyperlink"(i know there is now such thing in inno) when you click label a document(rtf) with instructions will open.
The problem: i DON'T want to copy this program along with the setup,
it should be inside the setup and after the installation it is no more
needed, thus it should be deleted or thrown out.
cant use {tmp} folder since it is accesed only in [run] phase(that is installation if i am not mistaken) and i need it earlier.
Any suggestions?
The temporary folder is not explicitly reserved for [Run] section. It can be used whenever needed (it is widely used e.g. for DLL libraries). And there is no such thing as a hyperlink label in Inno Setup as far as I know. I've made an example of a link lable and extended it for opening files that are extracted from the setup archive into a temporary folder (a folder that is deleted when the installer terminates):
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Files]
; the dontcopy flag tells the installer that this file is not going to be copied to
; the target system
Source: "File.txt"; Flags: dontcopy
[Code]
var
LinkLabel: TLabel;
procedure LinkLabelClick(Sender: TObject);
var
FileName: string;
ErrorCode: Integer;
begin
FileName := ExpandConstant('{tmp}\File.txt');
// if the file was not yet extracted into the temporary folder, do it now
if not FileExists(FileName) then
ExtractTemporaryFile('File.txt');
// open the file from the temporary folder; if that fails, show the error message
if not ShellExec('', FileName, '', '', SW_SHOW, ewNoWait, ErrorCode) then
MsgBox(Format('File could not be opened. Code: %d', [ErrorCode]), mbError, MB_OK);
end;
procedure InitializeWizard;
begin
LinkLabel := TLabel.Create(WizardForm);
LinkLabel.Parent := WizardForm;
LinkLabel.Left := 8;
LinkLabel.Top := WizardForm.ClientHeight - LinkLabel.ClientHeight - 8;
LinkLabel.Cursor := crHand;
LinkLabel.Font.Color := clBlue;
LinkLabel.Font.Style := [fsUnderline];
LinkLabel.Caption := 'Click me to read something important!';
LinkLabel.OnClick := #LinkLabelClick;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
LinkLabel.Visible := CurPageID <> wpLicense;
end;
Is it possible to disable the the Preparing To Install wpPreparing and the Installing wpInstalling Wizard Pages (i.e. the ones with the progress bar) so that they do not show during installation? There does not appear to be a built-in directive or method (e.g. for the Ready Wizard Page you can use DisableReadyPage=yes to do so). Am I missing something, or is it, as I suspect, simply not possible?
I have already tried using:
function ShouldSkipPage(CurPageID: Integer): Boolean;
begin
if CurPageID = wpPreparing then
Result := True;
if CurPageID = wpInstalling then
Result := True;
end;
Have you tried this - DisableReadyPage=yes in the [Setup] section.
Seems the only other option is to use the "install silently" command line switch. I'd be careful though this essentially installs a potentially destructive program without the users knowledge.
It is not possible to skip the wpPreparing or wpInstalling Wizard Pages. However, if the installer is not actually installing anything and is being used to return something, say an unlock code, as is the use case here, the following could be done instead:
//Disable the Exit confirmation prompt
procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
begin
Cancel := True;
Confirm := False;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
//Get the unlock code
if CurPageID = UnlockCodePage.ID then
begin
if UnlockCodePage.Values[0] = '' then
begin
MsgBox('You must enter an installation ID to generate an unlock code.',
mbError, MB_OK);
end
else
begin
UnlockCodePage.Values[1] := GetUnlockCode;
end;
Result := False;
end;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
//Define button visibility, whether the Back button is enabled and change the Next and Cancel button labels
WizardForm.CancelButton.Caption := '&Close';
if CurPageID = UnlockCodePage.ID then
begin
WizardForm.BackButton.Enabled := False;
WizardForm.NextButton.Caption := '&Generate';
end;
end;
Hopefully this may help someone looking to do something similar.
so i am currently trying to modify the setup script,
What i was trying to do was after installing i enter in a custom page, this custom page executes 2 scritps(one for creating the database and the other for creating the tables).
while this is executing i want to display a custom label,and a continuous progress bar.
When the execution finish, i want to go directly to the finish page.
I wanto to also remove the next button.
Is this possible?
For the moment i have the custom page with a constinuous progress bar, this page appears after install.i will then add the label after finishing the progress bar part.
here is my code:
[CODE]
var
Page: TWizardPage;
ProgressBar3: TNewProgressBar;
procedure CreateTheWizardPages;
begin
Page := CreateCustomPage(wpInstalling, 'Base de dados', 'A verificar a base de dados');
ProgressBar3 := TNewProgressBar.Create(Page);
ProgressBar3.Left := 5;
ProgressBar3.Width := Page.SurfaceWidth - 5;
ProgressBar3.Parent := Page.Surface;
ProgressBar3.Style := npbstMarquee;
end;
procedure InitializeWizard();
begin
CreateTheWizardPages;
end;
//check the current page,if page equals to wpSelectCompnets, then we add the method on choose to the combobox fo types of installation
procedure CurPageChanged(CurPageID: Integer);
begin
//msgbox(IntToStr( CurPageID),mbInformation, MB_OK);
if CurPageID = wpSelectComponents then
begin
comboboxTypesInstalacao:=WizardForm.TypesCombo;
WizardForm.TypesCombo.OnChange:=#ComboBoxChange;
end
else if CurPageID = Page.ID then
begin
try
CreateDBAndTables('idontimedb.des');
finally
//close this custom wizard page and go to finish page
end;
end;
end;
Thanks in advance.