How to get the file name of the current Inno Setup script file? - inno-setup

I want to obtain the name of the current Inno Setup script file in order to name the generated setup package after it. For example if the current Inno Setup script file is "MyAppSetup.iss", I want the generated setup file to be "MyAppSetup.exe".
The name of the generated setup file is controlled by the OutputBaseFilename declaration in the [Setup] section of Inno Setup, so if there's an Inno Setup preprocessor variable that returns the name of the current script file that would be great. Something like:
OutputBaseFilename={#SourceFileName}.exe
Unfortunately, there isn't an Inno Setup preprocessor variable {#SourceFileName}. I know about the {#SourcePath} variable, but it returns the directory path of the script file without it's file name. Here's a list with some predefined Inno Setup preprocessor variables, but none of them seems to return the name of the current script file. I hoped the __FILE__ variable would work after reading the descriptions of the variables in the list, but it returns an empty string.

It's not possible. There's the __FILE__, but it has a value for #included files only.
If you never have more than one .iss file in a directory, you can use the FindFirst to find its name.
#define ScriptFindHandle = FindFirst(SourcePath + "\*.iss", 0)
#if !ScriptFindHandle
#error "No script found"
#endif
#define SourceFileName = FindGetFileName(ScriptFindHandle)
#if FindNext(ScriptFindHandle)
#error "More than one script found"
#endif
#expr FindClose(ScriptFindHandle)
#define SourceBaseName = RemoveFileExt(SourceFileName)
Then to name the setup file after the current script file in the [Setup] section you should use:
[Setup]
OutputBaseFilename={#SourceBaseName}
But if you are automating compilation of a large number of installers, I assume you use a command-line compilation. So then you can simply pass a script name in a parent batch file (or a similar script):
set SCRIPT=MyAppSetup
"C:\Program Files (x86)\Inno Setup 5\ISCC.exe" %SCRIPT%.iss /DBaseName=%SCRIPT%
Use the BaseName like:
[Setup]
OutputBaseFilename={#BaseName}

I know this is not exactly what you want, but why can't you do this:
[ISPP]
#define ScriptFileName "MyAppSetup"
[Setup]
AppPublisher={#AppPublisher}
OutputBaseFilename={#ScriptFileName}Setup
Then all you need to do it edit the one reference at the top of your file.
Update
I came across this link where it states:
You can use:
#expr SetSetupSetting("OutputBaseFilename", sFileName)
However, the difficult part is automatically finding the file name.
You could use the following ISPP functions to do additional
compile-time tasks that can't be done by ISPP built-in functions:
Exec function: Executes an external program to do the additional
functionality, and writes the result to an INI file. By default Exec
waits for the process to finish.
ReadIni function: Reads the result
from the INI file, and incorporates it into the script.
How do you determine the file name is up to you. Perhaps you could
enumerate the windows and extract the file name from Inno Setup
window title, but because you may be having multiple Inno Setup
copies open, you must find a reliable way to do it. Inno adds
[Compiling] to the title during compilation which makes it easier to
find which copy is being used, but there could be multiple copies in
compiling state. You can be absolutely sure about which copy is
running your program by checking the process ID of the parent
process, you can get that by using Process32First/Process32Next and
checking the 32ParentProcessID for your process. Too much work, I
know..
But there was another comment:
(If you're doing an automated build, though, you can set the output
filename from the command line -- that might be sufficient for what
you actually want.)
So have you considered using a batch file and the command line? Then you can use the benefits of batch lines with your compiling. Information is provided here about using the current file name in batch files.
I personally think that the batch file compilation is the way to go.

Related

Read contents of a file from within Inno Setup installer

I am using Inno Setup. I read from file with
LoadStringsFromFile(My_file, Lines)
but the file is outside installation file defined with
OutputBaseFilename={#MySetupExeName}
Can I open a file inside iss code, and this file to be in installation file (OutputBaseFilename)?
Use ExtractTemporaryFile:
[Files]
Source: myfile.txt; Flags: dontcopy
[Code]
...
ExtractTemporaryFile('myfile.txt');
LoadStringsFromFile(ExpandConstant('{tmp}\myfile.txt'), Lines);
...
Though as the contents is fixed, you can as well hard-code it.
Or read it from the file on compile-time, instead of having to extract the file on install-time. You can use preprocessor FileRead function for that. Though it's more complicated than the straightforward code above. We would have to know more about that you need the contents for and how it looks like to offer an efficient solution.

Why doesn't Inno Setup constant {userdesktop} work in OutputDir directive and how to fix it?

I created Inno Setup script, which works perfectly, but I wanted to change OutputDir to create the output file on my desktop. But instead of creating output file on desktop it was creating subfolder {userdesktop} at the same directory, where script is and output was inside.
I found solution so far, but I believe there should be better way. What am I missing?
; these attempts didn't work
[Setup]
OutputDir={userdesktop}
; some more attampts:
OutputDir=userdesktop
OutputDir=userdesktop:
OutputDir="{userdesktop}"
; this workaround worked for me
[Setup]
OutputDir=userdocs:..\Desktop
Constants like {userdesktop} are resolved on install time (on the target user's machine), not on compile time (on your development machine). So it makes no sense to use constants in compile-time only directive like OutputDir. And actually it's not possible to use them at all (as it's useless).
With the default user profile directory layout, use you can use the userdocs: prefix, as you did:
[Setup]
OutputDir=userdocs:..\Desktop
Though it's not a perfect solution, as the "Documents" folder can be moved by the user and then the userdocs:..\Desktop will not point to the desktop.
A more reliable solution is to use USERPROFILE environment variable using GetEnv preprocessor function:
[Setup]
OutputDir={#GetEnv('USERPROFILE')}\Desktop

Using INI file to fill setup section values on inno setup

I'm trying fill setup section values with {param} and {ini} like this:
VersionInfoProductName={param:NAME|My Product}
VersionInfoTextVersion={ini:ExpandConstant({src})\config.ini,setupValues,version|unknow}
But it is not working, in EXE properties is showing {param:NAME|My Product}
I also tried with GetIniString but same result.
How can I put ini values in Setup section?
You cannot use any of the constants you have used, because both directives you're trying to fill need to be filled at compilation time. You will need to use the preprocessor function equivalent, because only the preprocessor can fill the directive values before the compilation starts.
The preprocessor's equivalent for reading from INI files is the ReadIni function, which you can use the way which follows. Assuming you have a config.ini file stored in the same location as the script with this content:
[setupValues]
version=1.2.3.0
You can fill the value of the VersionInfoVersion directive this way. I have used this directive, since the value of the VersionInfoTextVersion directive is displayed only on Windows 98 below systems and I believe you're not running such an old system to ever verify this:
[Setup]
VersionInfoVersion={#ReadIni(SourcePath + "config.ini", "setupValues", "version", "")}
Note, that the SourcePath variable used in the above code is a predefined variable that can be evaluated from preprocessor. The result you can then verify by checking the setup binary file properties and you will see e.g. this:

Calling consecutive DLL's from {tmp} in Inno Setup

I want to use a DLL (lets say 'A.dll'), that I created in Delphi, within my Inno Setup script that uses a bunch of other DLLs ('B.dll', 'C.dll', ...). All these dll-files are included in the Files-section as follows:
[Files]
Source:"libs\*.dll"; Flags: dontcopy
In the code section I declare methods of the used DLL as described in the Online help and add the loadwithalteredsearchpath flag:
procedure MyMethod; external 'MyMethod#files:A.dll,B.dll,C.dll stdcall loadwithalteredsearchpath';
When the installer starts, all needed files are copied into the temporary directory the constant {#tmp} is pointing to. However, MyMethod starts its execution just fine (checked it with some Showmessages), but the whole thing breaks, when the method tries to use the other DLLs.
Next to the temporary folder from {#tmp} two other temporary directories are created during the setup (all with the 'IS-xxxxx.tmp' pattern), which contain 'setup.tmp' (which is not occurent in {#tmp}). When I now manually copy all the DLL's (besides A.dll) into both these other directories at the beginning of the setup, then everything works fine. But when I let it run only as defined in my script, then A.dll doesn't seem to find the other libraries.
Does anybody know, why this is happening and how I can fix this? This seems to be a problem with the PATH, but I thought that Inno Setup adds the tmp-dir into the PATH, so that the setup can find the DLL's (which it does, but strangely only for A.dll).
Thanks in advance for your help! :)
EDIT: The actual error I get, when I use one of the 'foreign' DLL's (B.dll, C.dll, ...) by calling one of their methods inside of A.dll during the Inno Setup:
Access violation at address 00408CC7 in module 'setup.tmp'. Read of adress 00000000.
EDIT 2: I think I realized why my problem is happening: With ExtractFilePath (first link) in my own A.dll I discovered, that the setup.exe is not executed within {tmp} but one of the other two temporary dirs that are creating at the beginning of the setup. It also appears, that not {tmp} but the current working dir (thus the dir, where inno is executed) is added to the library search path (second link). This would explain, why the other libraries (B.dll, C.dll, ...) can only be accessed when manually copying to this other temp dir. I suppose that A.dll is extracted and called from {tmp} without a problem, because it is referred as the "main-library" in the external command. I thought that with loadwithalteredsearchpath the other libraries could remain in the same directory, but that doesn't seem to work.
But how can I fix this now in an nifty way? I think I could copy the DLLs manually to the setup-path (by using ExtractFilePath(ParamStr(0)), after they have been extracted to {tmp} to solve the problem. But this seems to be a dirty workaround as using DLLs in Inno Setup is supposed to work differently.
How to get path where is temporary Inno setup file is located
External function calls with multiple dependent DLLs
Well I'm not sure if you only load the DLLs without registering them in the system registry. However your first EDIT shows an error triggered by attempts to access some stack of the registry, so I assume you are. In that case, I simply use a batch file (which fires commands in the CMD console) to register my DLLs as I would one by one:
#echo off
echo Registering DevExpress DLLs
%~dp0gacutil.exe /i %~dp0DevExpress.BonusSkins.v12.1.dll
%~dp0gacutil.exe /i %~dp0DevExpress.Charts.v12.1.Core.dll
So, I place this in the RUN section of the iss script:
[Run]
Filename:C:\myFolder\RegisterDevExpress.bat"
Hope this helps.

Inno-Setup checking file location prior to installation, then using it during installation

I need to check for the location of a file during program installation utilizing inno setup. I then need inno setup to use the location of that file in the "Filename" line to create a desktop ICON for program initialization. I have the code for the "Icons" option working fine with the exception of how to do the above.
Here is the line of code I am currently using;
Name: "{commondesktop}\SA - NH Bricscad V12"; Filename:"**c:\program files\septic assistant\new hampshire\support\**SA - NH Bricscad V12.exe"; IconFilename: "C:\Program Files\Septic Assistant\New Hampshire\Support\Bricscadlogo.ico"; Comment: "Septic Assistant the only Septic Design Program"
Hi-Lited section would be the path to the exe file that I need inno setup to search for.
Any assistance with this would be very much appreciated.
Bruce
Just use a {code:...} constant and corresponding [Code] function that returns the appropriate path for your [Icons] entry. You will probably also want to use a Check function to avoid installing the icon in the case that you cannot find the correct location.
Another option is to use a {reg:...} constant, assuming that the path you are trying to locate is specified somewhere in the registry (which is usually the case).
If the path is not already specified somewhere well-defined in the Registry when the other app is installed, and you don't have some other means to quickly identify where the other app is located (note that doing a global search of the user's HD is not a valid option), then you should add a page that prompts the user to enter the location themselves (which you can then verify that they have chosen the correct location). You can see examples of prompting the user for information and then doing something with that info in the CodeDlg.iss example included with Inno, and in the ISXKB wiki.

Resources