"Acess violation" when using a scripted constant - inno-setup

I need to implement a scripted constant to retrieve a drive of user-selected path.
I tried the code bellow, but I'm getting:
Acess violation ate adress 0043D8E0.Read of address 01CDE694
[Code]
procedure InitializeWizard;
begin
Page := CreateInputDirPage(
wpSelectDir,'Select local', 'Where will be stored?', '', False, 'New Folder');
Page.Add('Local Dserver (APP)');
Page.Add('Local Images (Storage)');
Page.Values[0] := ('F:\TEST1');
Page.Values[1] := ('G:\TEST2');
end;
function ExtractFileDrive(const FileName: string): String;
begin
Result := ExtractFileDrive(Page.Values[0]);
end;
[Run]
Filename: {code:ExtractFileDrive|0}\postgresql-9.4.5-1-windows-x64.exe

Your ExtractFileDrive scripted constant shadows the ExtractFileDrive support function. So you recursively call your ExtractFileDrive function from itself ad infinitum, until the stack overflows.
Just rename your function to anything else.
And once doing that, rename its argument, as the FileName is confusing. And also remove the scripted constant parameter in its use, as you actually do not use it.
[Code]
function GetFileDrive(Param: string): String;
begin
Result := ExtractFileDrive(Page.Values[0]);
end;
[Run]
Filename: {code:GetFileDrive}\postgresql-9.4.5-1-windows-x64.exe

Related

Inno Setup: Function to select a component

I have a small problem. I need that a page is displayed when you select one or two components. But the other is not work only with a single component seems to have an effect. I leave the code that I'm working.
[Setup]
AppName=My Program
AppVerName=My Program v.1.2
DefaultDirName={pf}\My Program
[Types]
Name: full; Description: Full installation
Name: compact; Description: Compact installation
Name: custom; Description: Custom installation; Flags: iscustom
[Components]
Name: program; Description: Program Files; Types: full compact custom; Flags: fixed
Name: help; Description: Help File; Types: full
Name: readme; Description: Readme File; Types: full
Name: readme\en; Description: English; Flags: exclusive
Name: readme\de; Description: German; Flags: exclusive
[Code]
var
Page1: TWizardPage;
Procedure InitializeWizard();
begin
Page1:= CreateCustomPage(wpSelectComponents, 'Custom wizard page 1', 'TButton');
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Case PageID of
Page1.ID: Result:= not IsComponentSelected('help');
Page1.ID: Result:= not IsComponentSelected('readme\de'); // It does not work
end;
end;
A greeting and thanks in advance.
If you need to write more complex conditions, use logical operators for that. In this case you wanted to use the and operator:
Result := not IsComponentSelected('help') and not IsComponentSelected('readme\de');
Which can be read as:
Skip page if "help" component is not selected and "readme\de"
component is not selected as well. In human language it could be, skip
page if neither "help" nor "readme\de" component is selected.
Your code so can be simplified to this:
function ShouldSkipPage(PageID: Integer): Boolean;
begin
// skip the page if it's our custom page and neither "help" nor "readme\de"
// component is selected, do not skip otherwise
Result := (PageID = Page1.ID) and (not IsComponentSelected('help') and
not IsComponentSelected('readme\de'));
end;
One final note (and a possible cause of problems), beware of switching on the same identifier in case statements. Compiler should not allow you doing this but unfortunately does, e.g. this compiles:
var
I: Integer;
begin
I := 1;
case I of
1: MsgBox('Case switch 1.1', mbInformation, MB_OK);
1: MsgBox('Case switch 1.2', mbInformation, MB_OK);
end;
end;
But only the first switch value statement executes, so you'll never see the message "Case switch 1.2".

Pascal Scripting: Canceling setup before {app} variable is set

I have some declarations at the [Dirs]-section in my Inno Setup file. I use "Inno Setup Compiler" and a normal text editor (Notepad++) for developing.
When I cancel the setup before choosing the install directory, the {app} variable is empty for sure.
I get this error (which is totally logic):
How can I fix that no error occurs after pressing the "Cancel" button and committing that I want to cancel the setup?
Internal error: An attempt was made to expand the "app" constant
before it was initialized.
Can I globally set the {app} variable or give it a default value?
Here is a code snippet where I use the variable {app}:
[Dirs]
Name: {app}; Permissions: everyone-readexec
Name: {app}\bin; Permissions: everyone-readexec
[Run]
Filename: "{app}\run.exe; Flags: runhidden
[INI]
Filename: {app}\bin\myIni.ini; Section: Settings;
[InstallDelete]
Name: {app}\*; Type: filesandordirs; Tasks:
Thanks for help,
regards,
C.
Either you should skip the code, which attempts to expand the {app} constant before it's initialized, or as a workaround you can use the WizardDirValue, which actually returns value to the {app} when it's being expanded. Even reference mentions that (emphasized by me):
Returns the current contents of the edit control on the Select
Destination Location page of the wizard.
Unlike ExpandConstant('{app}'), this function will not fail if called after the wizard is shown but prior to the user selecting a
directory. Rather, it will return the default directory name.
In the most recent source code you can see how the {app} constant is expanded on this line.
Thanks for helping, the problem got solved!
Before the user reaches the 'Select Destination Location' the {app} variable is not set.
My DeInitialize-Procedure looked like this:
procedure DeinitializeSetup();
var
SettingsPath: String;
begin
SettingsPath := ExpandConstant('{app}')
DelTree(SettingsPath + '\bin', True, True, True);
end;
What I did is I created a Boolean variable at the beginning:
[Code]
var appIsSet: Boolean;
I set it to false at initializing:
function InitializeSetup(): Boolean;
begin
// interesting code
appIsSet := False;
end;
... and set it to 'true' after the user has reached 'wpSelectDir' in nextButtonClick (see code snippet below:)
begin
if CurPageID = wpSelectDir then
begin
appIsSet := True;
The last step is to check in the Deinitialize-Procedure if the boolean variable is set. If so, he can access on it, if not - do nothing:
procedure DeinitializeSetup();
var
SettingsPath: String;
begin
if appIsSet then begin
SettingsPath := ExpandConstant('{app}')
DelTree(SettingsPath + '\bin', True, True, True);
end;
end;

Inno: Write User and Serial to Registry

During my inno installation I'm trying to write the username and serial to the registry and I get the following error during compile:
Invalid prototype for 'RegisteredUser'
Chunk from Inno
[Code]
function RegisteredUser(): String;
begin
Result := 'test';
end;
[Registry]
Root: HKLM; Subkey: "SOFTWARE\Platform\Brand"; ValueType: string; ValueName: "RegisteredUser"; ValueData: {code:RegisteredUser};
Any ideas?
Or if I can create the registry directly in [Code] that would work also
Thanks
Apparently in inno-setup the function called by {code:block} must be a single string parameter function (even if you do not use it.
function RegisteredUser(Param: String): string;
begin
Result := SerialPage.Values[0];
end;

Inno Setup script: Identifier expected error

Please help me with the following code:
[Code]
var
AppVersionNumber: Integer;
DBVersionNumber: Integer;
function GetAppVersion:Integer;
var
AppVersion: AnsiString;
begin
ExtractTemporaryFile('info.dat');
LoadStringFromFile(ExpandConstant('{tmp}\info.dat'), AppVersion);
AppVersionNumber := StrToInt(Copy(AppVersion, 1, 6));
DBVersionNumber := StrToInt(Copy(AppVersion, 7, 12));
GetAppVersion := AppVersionNumber; <== here is error
end;
I don't understand what's wrong here. The Inno setup says there is "Identifier expected" error. If I try to replace on this line GetAppVersion to Result (why? I don't know but I saw it in examples) it says that "Invalid prototype for GetAppVersion".
What's wrong with this code? Please help
Result := is needed to specify the result/return value of a function (you don't assign it to the function name like VB)
The "Invalid Prototype" error is most likely because you're using it in a {code:...} constant that requires the called function to have a single string parameter at all times.
Try using this taken from the help file:
function GetAppVersion(Param: String): String;

How to automatically determine the path of previous installation using Inno Setup

I'm trying to create a inno setup installer that patches a previous installation but i can't manage to force my installer determine the path where my previous installation is.
I tried using the DefaultDirName={reg:HKxx\SubkeyName,ValueName|DefaultValue} feature from inno but i'm not sure what to put in the DefaultValue's place.
How can i do that?
Edit:
i tried also this part:
[Setup]
DefaultDirName={code:GetPathInstalled}
[Code]
function GetPathInstalled (Param: String): String;
var
Country: String;
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\JoWooD\Painkiller Resurrection', 'Install', Country);
end;
But when i run the installer the path is empty.
Your code should look like:
[Code]
function GetPathInstalled (Param: String): String;
var
Country: String;
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\JoWooD\Painkiller Resurrection', 'Install', Country);
Result:= Country;
end;
The return value from the RegQueryStringValue wasn't being returned as the result of the GetPathInstalled function.

Resources