I have this definition:
#define HelpDocSetupFileSize FileSize("..\HelpNDoc\CHM\Output\MSAHelpDocumentationSetup.exe")
It obtains the file size by looking at the data file on my computer rather than working it out remotely. I've used that value with Inno Setup Download plugin to specify the size of the file to download.
I'm rewriting the code for the new Inno Setup download feature. My code for managing it all (stripped down) is:
function NextButtonClick(CurPageID: integer): boolean;
begin
Result := True;
if (CurPageID = wpReady) then
begin
DownloadPage.Clear;
if (WizardIsTaskSelected('downloadhelp')) then
DownloadPage.Add('{#HelpDocSetupURL}', 'HelpDocSetup.exe', '');
DownloadPage.Show;
try
try
DownloadPage.Download;
Result := True;
except
SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbCriticalError, MB_OK, IDOK);
Result := False;
end;
finally
DownloadPage.Hide;
end;
end;
end;
I can't find any documentation in the beta for Add and from looking at the sample the third and fourth parameters are not for providing the file size. Is it the fifth?
Some official clarification about the Add parameters appreciated.
The TDownloadWizardPage.Add has three arguments only.
You do not need to (and you cannot) specify the file size upfront. Inno Setup finds out the size on its own from the Content-Length HTTP header.
Related
I need to create a setup package that will allow multiple instances of the same application to be installed on the same PC/server. So, I wish to dynamically amend the default "install to" location after the UserInfo page has been processed.
i.e. in the NextButtonClick event I wish to change the value on the SelectDir wizard page when the CurPageID=wpUserInfo. Something like this below (which throws an exception). I'm also assuming that I can access the user name by expanding {userinfoname}. Any help would be appreciated.
function NextButtonClick(CurPageID: Integer): Boolean;
var
Page: TInputDirWizardPage;
begin
case CurPageID of
........
wpUserInfo:
begin
Page := TInputDirWizardPage(PageFromID(wpSelectDir));
Page.Values[0] := MyAppDirFunction;
end;
end;
Result := True;
end;
To access the "Destination folder" box, use WizardForm.DirEdit:
WizardForm.DirEdit.Text := Path;
See TWizardForm reference.
I have Inno Script Create Using IKG (Inno Key generator)
I want Add This Step to My Script
Please Help me.
User can install this setup one or two time per day only.
Eg:
1.get and check date using Internet (because user can change PC date)
2.Save date to registry and a file in program folder ({app}) (date limitation file), like date.txt. Registry and date limitation file must be created after all installation files are copied.
3.Check per date limitation and before installation starts (using registry and date limitation file)
i.limit Over : Msg Cant Install
ii.Limit Not over or registry And Limitation File not Have : Installation Start
Files: all files link
Please help me. Thanks
To implement your test for "too many installations", implement the InitializeSetup event function.
The best place to increment your "hidden" installation counters is the CurStepChanged event function, when called with ssPostInstall argument.
[Code]
function TooManyInstallations: Boolean;
begin
{ Here you implement your test }
Result := False;
end;
function InitializeSetup(): Boolean;
begin
Result := True;
if TooManyInstallations then
begin
MsgBox('You have installed this too many times', mbError, MB_OK);
Result := False;
end;
end;
procedure IncrementInstallationCounter;
begin
{ increment your installation counter here }
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
{ Installation has beed completed }
IncrementInstallationCounter;
end;
end;
I continue looking for the better way to distribute my application making use of Inno Setup, therefore I would to know if is possible to do a (check-serial).
I tried with the follows methods:
CustomPage for Serial Number in Inno Setup
How to create dynamically changing serial numbers using Inno Setup?
I want some similar like this. But with the exception that I have where to save my passwords (I think that SharePoint List could be helpful, I am not sure!)
How to do a dynamic password in Inno Setup?
Not Is enough for my boss! and I want to believe that is possible do something more elegant.
Finally, I have a SharePoint account and I would like do some in my code of Inno Setup for to control of installations, i.e. Whether I have 123 number like a serial then it works normal until I change this value in the List.
I don't want that always be a same serial
Thanks again!
To check a serial number against an HTTP resource, you can use the below code.
I do not know SharePoint, so I cannot give you details on how to adjust it to SharePoint.
[Setup]
UserInfoPage=yes
[Code]
var
SerialNumber: string;
function InitializeSetup(): Boolean;
var
WinHttpReq: Variant;
begin
Result := True;
try
WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
WinHttpReq.Open('GET', 'https://www.example.com/serial.php', false);
WinHttpReq.Send();
if WinHttpReq.Status = 200 then
begin
SerialNumber := Trim(WinHttpReq.ResponseText);
end;
except
end;
if SerialNumber = '' then
begin
MsgBox('Cannot retrieve serial number.', mbError, MB_OK);
Result := False;
end;
end;
function CheckSerial(Serial: String): Boolean;
begin
Result := (SerialNumber = Serial);
end;
For a similar question, see:
Inno Setup - How to validate serial number online
I've got a bit of a pickle with Inno Setup: on a user machine, my installer was running slowly (something I've yet to diagnose, might be a problem specific with that computer, I still don't know). This lead to said user to run the installer again, while the first instance was still executing - and to my surprise, they both seemed to be running for a time, before crashing and burning...
I searched around but have not found any way to disable this behavior - most of my queries wound up on Inno Setup mutex feature, which is not really what I'm looking for. Anyone got tips on how to make sure there is only one instance / process of the installer executing? Thank you!
Since Inno Setup 5.5.6 you can use the SetupMutex directive:
[Setup]
AppId=MyProgram
SetupMutex=SetupMutex{#SetupSetting("AppId")}
If you want to change a text of the message, that displays when another installer is running already, use:
[Messages]
SetupAppRunningError=Setup has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.
Before this version, there was no built-in mechanism available. But you could write your own pretty simply. Principle is that you create a unique mutex when the setup starts. But, as first you check if there is no such mutex already created. If so, you exit the setup, if not, you create the mutex:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Code]
const
// this needs to be system-wide unique name of the mutex (up to MAX_PATH long),
// there is a discussion on this topic http://stackoverflow.com/q/464253/960757
// you can expand here e.g. the AppId directive and add it some 'salt'
MySetupMutex = 'My Program Setup 2336BF63-DF20-445F-AAE6-70FD7E2CE1CF';
function InitializeSetup: Boolean;
begin
// allow the setup to run only if there is no thread owning our mutex (in other
// words it means, there's no other instance of this process running), so allow
// the setup if there is no such mutex (there is no other instance)
Result := not CheckForMutexes(MySetupMutex);
// if this is the only instance of the setup, create our mutex
if Result then
CreateMutex(MySetupMutex)
// otherwise tell the user the setup will exit
else
MsgBox('Another instance is running. Setup will exit.', mbError, MB_OK);
end;
If your installer was called setup.exe for example, then you could use the following code to check if setup.exe is running and terminate the install.
[Code]
function IsAppRunning(const FileName : string): Boolean;
var
FSWbemLocator: Variant;
FWMIService : Variant;
FWbemObjectSet: Variant;
begin
Result := false;
FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
FWbemObjectSet := FWMIService.ExecQuery(Format('SELECT Name FROM Win32_Process Where Name="%s"',[FileName]));
Result := (FWbemObjectSet.Count > 0);
FWbemObjectSet := Unassigned;
FWMIService := Unassigned;
FSWbemLocator := Unassigned;
end;
function InitializeSetup: boolean;
begin
result := not IsAppRunning('setup.exe');
if not result then
MsgBox('setup.exe is already running', mbError, MB_OK);
end;
I would like to swap the SelectDir page with the Components page in my setup.
I found a solution where the content of the other page is assigned to the current page.
Procedure CurPageChanged(CurPageID: Integer);
Begin
Case CurPageID of
wpSelectDir:
begin
WizardForm.SelectDirPage.Notebook.ActivePage:= WizardForm.SelectComponentsPage;
WizardForm.PageNameLabel.Caption:= SetupMessage(msgWizardSelectComponents)
WizardForm.Hint:= WizardForm.PageDescriptionLabel.Caption;
WizardForm.PageDescriptionLabel.Caption:= SetupMessage(msgSelectComponentsDesc)
end;
wpSelectComponents:
begin
WizardForm.SelectComponentsPage.Notebook.ActivePage:= WizardForm.SelectDirPage;
WizardForm.DiskSpaceLabel.Caption:= WzardForm.ComponentsDiskSpaceLabel.Caption;
WizardForm.PageNameLabel.Caption:= SetupMessage(msgWizardSelectDir)
WizardForm.PageDescriptionLabel.Caption:= WizardForm.Hint
end;
end;
End;
The problem using this method is that only the content but not the actual page is changed. Message boxes and error messages are not affected. I wrote many lines of code to work around these problems but I encounter more and more problems...
Is there a better solution? I hope you can help me!
Edit: After experimenting a bit I came up with this:
procedure RedesignWizard;
var
Page: TWizardPage;
begin
Page := CreateCustomPage(wpWelcome, 'bla', 'bla');
WizardForm.ComponentsList.Parent := Page.Surface;
//Here I am changing the layout of the pages...
end;
procedure InitializeWizard;
begin
RedesignWizard;
end;
procedure CurPageChanged(CurPageID: Integer);
begin
if (CurPageID = Page.ID) then
begin
//perform your actions specific to the Custom page here.
end;
end;
This way the components list appears before the SelctDirPage and I do not have any more problems with those message boxes.
There is absolutely no way to safely swap the order of any of the builtin pages. (And usually, the only time people ask is when they are trying to replicate the flow of a different installation system. Relax and let it go; Inno works differently, embrace it instead of fighting it.)
Having said that, it is possible to give the appearance of swapping the pages, by recreating one or the other of them as a custom page. However by doing this you will forfeit all of the built-in functionality associated with that page -- eg. if you replace the components page then you cannot use the [Components] section or parameters, and if you replace the directory page then you cannot use {app} (not even in those places that use it implicitly, such as the UninstallFilesDir).
If you're willing to put in a lot of time and effort (especially testing), it can be done. But everything is worse off as a result -- so normally you're better off not doing so.
To add to what Miral said:
[Setup]
DisableDirPage=yes // disable the built-in page
[Code]
var
ApacheDirPage: TInputDirWizardPage;
ApacheDir: AnsiString;
procedure InitializeWizard;
begin
{ Create the custom wizard pages }
ApacheDirPage :=
CreateInputDirPage( wpSelectComponents, // display AFTER select Type/Components page
'Select Apache Directory',
'Select the Apache x.x Directory' + #13#10 + '(the one that contains the BIN folder)',
'Select the Apache directory, then click Next.',
False, '' );
ApacheDirPage.Add( '');
ApacheDirPage.Values[0] := csApacheLocation;
end;