Limit installations to one or two time per day - inno-setup

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;

Related

Provide the file size for Inno Setup download feature

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.

How to alter the default target directory ({app}) after User Info page in Inno Setup

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.

How to store serial numbers in a Sharepoint List, for to call from Inno Setup and verify if is autorized user?

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

How to call an exe when Inno Setup installation fails (within the installer itself)?

I've been using Inno Setup for several months now, but I'm struggling to find how to detect, from within the installer itself, an error that would cause Inno Setup to end with a non-zero exit code.
I've thought about using CurStepChanged with the ssDone step, or even DeinitializeSetup, but I can't find how to get access to the wizard's exit-code.
Did I miss something? There must be a way to do it...
I'd like to know if anything went wrong so that I can start a rollback procedure on the machine. Your proposed answer did the trick.
You cannot find out installer exit code from the Pascal Scripting.
If you want to detect that the installer failed, remember if CurStepChanged was called with ssDone and test that in DeinitializeSetup.
var
Succeeded: Boolean;
procedure DeinitializeSetup();
begin
if Succeeded then
begin
Log('Installation succeeded');
end
else
begin
Log('Installation failed');
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssDone then
begin
Succeeded := True;
end;
end;
There are edge cases, when ssDone is used even, if the installer fails.
For example, when it fails because a machine was not restarted to complete the previous installation. In this case the CurStepChanged is not called with ssPostInstall. So you may want to check for both steps, if this scenario can happen in your installer.

Inno Setup - prevent executing the installer multiple times simultaneously

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;

Resources