Get the path specified in the source of file section - inno-setup

Is there any way by which we can get the path of the source file in [file] section be made available in [code] section. I need to have the full path as been given in the source. I need to check it with the content of a file and if the path is present in the file, then only i need to copy that particular file. I am using Check: in the file section and need to have the whole path of file made available in code section for comparison.

To get the chosen install folder from pascal script, you can use either ExpandConstant('{app}') or WizardDirValue(). Note that I don't think the returned path contains a trailing backslash.
This would simply check a file existence:
function IsMyFilePresent: Boolean;
begin
Result:=FileExists(ExpandConstant('{app}\filename.ext'));
end;
If it's an ini file, you can use this code to retrieve the data of certain keys inside it:
(example using WizardDirValue())
inifile:=WizardDirValue()+'\filename.ext';
MyString:=GetIniString('SectionName', 'KeyName', 'DefaultValue', inifile);

Probably the CurrentFileName() function that:
Returns the destination name of the [Files] entry that is currently being processed.
You can probably work out the source from this. I'm not sure how it handles wildcards though (but I suspect it just returns "blah/*"

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.

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

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.

Read file contents to variable in grub.cfg file

Q1. Wanted to know how do you read the contents of a file to a variable at boot time in grub.cfg?
Q2. Could that be extended to read an .ini type file where you can read the values for various name entries?
[section]
nothisone=whatever
thisone=this is what I want to get
TIA!!
In order to do exactly what you are asking for, you would probably need to write your own GRUB module.
However, you should be able to achieve what you're after either using the configfile command, or with some clever application of the environment block feature.
Use "source" command to include another config file but unlike "configfile" which will change context.
Source is like an online macro while configfile likes a function - environment changes in configfile will not be preserved but source is expanding whatever in the source file and put in the main block, environment variable can be changed in this way.
https://www.gnu.org/software/grub/manual/grub/grub.html#source
https://www.gnu.org/software/grub/manual/grub/grub.html#configfile

inno-setup update file in all subdirectories where it exists

I'm trying to create an installer that will update a single csv file, that exists in various locations depending on which of our applications a user has installed.
Our applications install inside a folder with our Company Name in Program Files.
So, Company > App1, Company > App2, Company > App3, etc. When the csv file exists, it is directly inside the App folder.
I've tried:
[Files]
Source: "file.csv"; DestDir: "{pf}\Company\*";
With various flags and functions to no avail
flag: onlyifdestfileexists
Skips everything because it doesn't exist
Check: FileExists('file.csv')
Does nothing at all
Check: FileExistsWildcard('file.csv')
Which calls a function using FindFirst() tries to create a new directory called * to install the file in, rather than overwriting the file in the directory where it was found, as does
[Files]
Source: "file.csv"; DestDir: "{pf}\Company\"; Check: FileExistsWildcard('*\file.csv')
The problem seems to have to do with the wildcard * not doing anything when used with DestDir. Instead of searching through all subfolders, it just looks for a subfolder named "*". The recursesubdirs flag of course works for iterating over subdirectories for Source, but there is no equivalent for DestDir.
Wildcards like that are not supported in DestDir.
If you know the names of all possible subdirectories up front (which presumably is the case as these are your own applications) then the simplest way to do this is to include multiple [Files] entries, one for each possible application. You can then use the onlyifdestfileexists flag. Note that when using the same Source path on multiple entries, only one copy of the file will be stored inside the installer, so it won't bloat the size.
If your applications support being installed into different locations (as most do) then you'll need to modify this slightly; instead of hard-coding the DestDir you'll need to have each entry look something like this:
Source: file.csv; DestDir: {code:FindAppPath|App1}; Flags: onlyifdestfileexists
with corresponding [Code] function:
function FindAppPath(AppName: String): String;
In this function, use RegQueryStringValue or other methods to look up the currently installed location of the application being searched for (via AppName, which can either be an arbitrary string of your choosing or could be part of the registry path being looked up; alternately you could write separate functions for each application if that's easier). If a given application is not installed, then return '', which will then skip installing the file due to the onlyifdestfileexists flag. Note that you will still need one entry per application, so you will need to know in advance the maximum number of possibly installed applications.
(An alternate means of skipping installation if you didn't wish to use this flag is to define a Check function eg. Check: IsAppInstalled('App1') or Check: IsApp1Installed.)
If you don't know (or don't want to rely on knowing) the maximum possible number of installed applications up front, then the only solution is to fall back to pure [Code]. You will need to have a single [Files] entry like so:
Source: file.csv; DestDir: {tmp}; AfterInstall: CopyToApplications
And then implement the CopyToApplications procedure to locate the paths to all the possible installations (again, probably via RegQueryStringValue) and then for each one:
FileCopy(ExpandConstant('{tmp}\file.csv'), AddBackslash(PathToApp) + 'file.csv');
You may also want to look at the CodeDlg example script and use CreateOutputProgressPage to provide feedback to the user while this process is going on, although it may not be necessarily if the file size is small enough.
Note that in all cases you probably want to disable uninstallation support (since each app's own individual uninstaller will take care of it); make sure you have Uninstallable=no in the [Setup] section.

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