Inno Setup Iterate over [Files] section in Pascal code - loops

In an Inno Setup script, I need to copy a number of files to multiple user-defined locations. In order to do this, I'd like to iterate over the sources in the [Files] section, and FileCopy() them multiple times depending on the user-defined settings and properties of the files.
Is it possible to access the sources in the [Files] section using a script?

No, you cannot iterate the [Files] section.
But you can use preprocessor to generate both the [Files] section and the Pascal Script from one list of files.
You are not very specific about your goals, so I'm showing only a rough concept.
; Define array of files to work with
#dim Files[2]
#define Files[0] "MyProg.exe"
#define Files[1] "MyProg.chm"
#define I
; Iterate the file array, generating one entry in Run section for each file
[Files]
#sub FileEntry
Source: "{#Files[I]}"; DestDir: "{app}"
#endsub
#for {I = 0; I < DimOf(Files); I++} FileEntry
[Code]
procedure CopyFiles;
begin
// Iterate the file array, generating two FileCopy calls for each file
#sub FileCopy
FileCopy('{#Files[I]}', 'd:\destination1\{#Files[I]}', True);
FileCopy('{#Files[I]}', 'd:\destination2\{#Files[I]}', True);
#endsub
#for {I = 0; I < DimOf(Files); I++} FileCopy
end;
// Just for debugging purposes, outputs the preprocessed script
// so you can verify if the code generation went right
#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")
If you compile the script, you can see in the preprocessed file Preprocessed.iss that it generates this:
[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "{app}"
[Code]
procedure CopyFiles;
begin
FileCopy('MyProg.exe', 'd:\destination1\MyProg.exe', True);
FileCopy('MyProg.exe', 'd:\destination2\MyProg.exe', True);
FileCopy('MyProg.chm', 'd:\destination1\MyProg.chm', True);
FileCopy('MyProg.chm', 'd:\destination2\MyProg.chm', True);
end;
Actually you may not need to use the FileCopy for this specific purpose. You can just have the preprocessor generate multiple [Files] section entries for the same file:
; Iterate the file array, generating one entry in Run section for each file
[Files]
#sub FileEntry
Source: "{#Files[I]}"; DestDir: "{app}"
Source: "{#Files[I]}"; DestDir: "d:\destination1"
Source: "{#Files[I]}"; DestDir: "d:\destination2"
#endsub
Generates:
[Files]
Source: "MyProg.exe"; DestDir: "{app}"
Source: "MyProg.exe"; DestDir: "d:\destination1"
Source: "MyProg.exe"; DestDir: "d:\destination2"
Source: "MyProg.chm"; DestDir: "{app}"
Source: "MyProg.chm"; DestDir: "d:\destination1"
Source: "MyProg.chm"; DestDir: "d:\destination2"
Inno Setup will identify identical source files and will pack them only once.
You can use Check parameter to make some entries conditional.
See also this question, which is actually similar:
Access file list via script in InnoSetup

Related

bitbake/wic error when making squashfs file systems

When I specify the squashfs file system type in the wic kickstart file (.wks file):
part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=ext4 --label bootfs --uuid 69AE36A5-1C24-412C-89F4-5E8D9123376C --fixed-size 32M
part --source bootimg-partition --ondisk mmcblk0 --fstype=ext4 --label bootfs_2 --uuid AD4023AC-6F63-4598-A32B-7B7864BA6796 --fixed-size 32M
part / --source rootfs --ondisk mmcblk0 --fstype=squashfs --uuid 3C51A271-215E-49B7-824F-4CF56F8BEE0D --fixed-size 176M
part --source rootfs --ondisk mmcblk0 --fstype=squashfs --uuid 8B9C88D2-3CC6-4B2E-A8A0-20AEF87D06DA --fixed-size 176M
part --ondisk mmcblk0 --fstype=ext4 --label fdb --uuid 6D7EEEDA-CD5E-4A8F-94DC-8670DDF887FA --fixed-size 8M
bootloader --ptable gpt
bitbake ends with the following error:
DEBUG: Python function extend_recipe_sysroot finished
DEBUG: Executing shell function do_image_wic
INFO: Creating image(s)...
ERROR: A native program mksquashfs required to build the image was not found (see details above).
Please make sure wic-tools have squashfs-tools-native in its DEPENDS, build it with 'bitbake wic-tools' and try again.
How do I specify the dependency ?
The dependency can be put in the machine configuration file with the WKS_FILE_DEPENDS variable. For example:
[...]
WKS_FILE = "my_wic_conf.wks"
WKS_FILE_DEPENDS += "squashfs-tools-native"

Executing a batch file during installation [duplicate]

Currently my batch file is in [Run] section. I need my batch file to execute before the [Files] section. Is there a way to do this in Inno Setup? Currently the [Run] section always execute after [Files] section.
[Run]
Filename: "C:\Users\Scripts\Install\Install.bat"; Parameters: {code:GetDatabaseName}
[Files]
Source: "C:\Users\MyApp\*"; DestDir: "\\MyServer\MyApp"; Flags: recursesubdirs createallsubdirs
If it needs to be done at the beginning of the setup, use Exec() in the PrepareToInstall() or CurStepChanged(ssInstall) event functions.
These are both after the user has said "go ahead, install" but before anything else.
PrepareToInstall() also allows you to cancel the install with a nice warning.
If the file needs to be extracted from the setup first, then you can preceed it with ExtractTemporaryFile()
Continuing Deanna's great answer, code example:
[code]
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: integer;
begin
Exec(ExpandConstant('{app}\serviceDeployment\unInstallService.bat'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
end;
this code always returns an empty string, which tells the setup to continue.
In case you want to stop setup (in some error cases) you need to return a non empty string and it will be displayed to the user (and setup will be stopped).
In order to return an error string add this line in PrepareToInstall's:
Result := 'Your Error Description';
You can use the InitializeSetup event + some pascal scripting.
See; How to run a file before setup with Inno Setup
Not mentioned in that example; to get the file from the installer you would use ExtractTemporaryFile('your.bat') then Exec(ExpandConstant('{tmp}\your.bat ... to run it.

Creating multiple packages with dpkg-buildpackage

I have a source tree structure like -
/src
/moduleA
/moduleB
/common
where moduleA and moduleB need packaged separately but share the common code.
Is it possible to create 2 separate binary packages using dpkg-buildpackage?
Thanks!
It is possible. In order to do it, you should modify the control file.
When you use dh_make -s, you have something like :
Source: yourpackage
Section: unknown
Priority: optional
Maintainer: toto <toto#unknown>
Build-Depends: debhelper (>= 8.0.0), autotools-dev
Standards-Version: 3.9.4
Homepage: <insert the upstream URL, if relevant>
#Vcs-Git: git://git.debian.org/collab-maint/libsnow.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/libsnow.git;a=summary
Package: yourpackage
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
<insert long description, indented with spaces>
All you have to do is to add a paragraph like that :
Package: yourpackagebis
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
<insert long description, indented with spaces>
(I should warn you, you can only use lowercase characters for the package's name). Once you've done that, you have to specify which file will go where. You have to create four new files : yourpackage.dirs, yourpackage.install, yourpackagebis.dirs, and yourpackagebis.install. In yourpackage.dirs, you have to specify what are the directories you need to create (one per line). In yourpackage.install, you have to tell dpkg-buildpackage what files should be put in the package yourpackage, and where. It must be in the following format (one per line):
moduleA/foo usr/bin
(assuming your makefile is in src/. It can be something else than usr/bin).
yourpackagebis.dirs and yourpackagebis.install works the same way for the package yourpackagebis.

VC++ 2012: How to include version info from version.inc (maintained separately) into the .rc file

Summary: Having the version details defined in the separately maintained version.inc via preprocessor macros... How to include the macro values into the resource version definition block?
My version.inc file is stored in UTF-8 (i.e. pure ASCII in the case). Its full content is the following (the APS_ prefix here is related to the real name of the application, not to the .aps file generated by the resource compiler):
#define APS_MAJORNUMBER 4
#define APS_MINORNUMBER 5
#define APS_BUILDNUMBER 0
#define APS_MODIFICATIONNUMBER 0
#define APS_BUILDEXT "wx"
#define APS_DATEYEAR 2012
#define APS_DATEMONTH 10
#define APS_DATEDAY 4
The Visual Studio 2012 C++ seems to be more picky about the resource script file (app.rc) than the Visual Studio 2010 was. The first thing I have noticed is that when editing it manually, I have to keep the UTF-16 encoding. Can you confirm that? Is there any documentation on that?
Say the version block in the app.rc looks like this:
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040504b0"
BEGIN
VALUE "CompanyName", "TODO: <Company name>"
VALUE "FileDescription", "TODO: <File description>"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "app.exe"
VALUE "LegalCopyright", "Copyright (C) 2012"
VALUE "OriginalFilename", "app.exe"
VALUE "ProductName", "TODO: <Product name>"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x405, 1200
END
END
In the earlier versions of Visual Studio (2005 and 2010), I was able to have the related version.rc2 like this:
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "version.inc"
#define STR(value) #value
#define STRINGIZE(value) STR(value)
#define APS_FULLVERSION_STR \
STRINGIZE(APS_MAJORNUMBER) "." \
STRINGIZE(APS_MINORNUMBER) "." \
STRINGIZE(APS_BUILDNUMBER) "." \
STRINGIZE(APS_MODIFICATIONNUMBER)
VS_VERSION_INFO VERSIONINFO
FILEVERSION APS_MAJORNUMBER,APS_MINORNUMBER,APS_BUILDNUMBER,APS_MODIFICATIONNUMBER
PRODUCTVERSION APS_MAJORNUMBER,APS_MINORNUMBER,APS_BUILDNUMBER,APS_MODIFICATIONNUMBER
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x29L
#else
FILEFLAGS 0x28L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "Comments", "A fairly useful tool named APS"
VALUE "CompanyName", "The company name"
VALUE "FileDescription", "app"
VALUE "FileVersion", APS_FULLVERSION_STR
VALUE "InternalName", "aps"
VALUE "LegalCopyright", "Copyright © 1993-" STRINGIZE(APS_DATEYEAR)
VALUE "OriginalFilename", "app.exe"
VALUE "PrivateBuild", ""
VALUE "ProductName", "APS of the version 4"
VALUE "ProductVersion", APS_FULLVERSION_STR
VALUE "SpecialBuild", APS_BUILDEXT
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
Then the version.rc2 was included into the app.rc via editing the app.rc manually. However, I cannot repeat the process with the Visual Studio 2012 project and resource file. I may be doing some mistake invisible to me. Should that approach work also in Visual Studio 2012?
Thanks for you time and experience,
Petr
Here is the way to do it via Visual Studio 2012 (C++, IDE). Firstly, it seems that all the files (app.rc, version.rc2 with the version section to be included into app.rc, and also the version.inc with the values maintained separately [included into version.rc2]) must be stored in UTF-16 -- unlike in the earlier versions of Visual Studio. Then I was able to repeat the same approach also in Visual Studio 2012.
However, you do not need to edit the app.rc file manually. You can use the following steps using the IDE:
Open the project (App) and switch to the Resource View tab.
Unfold the App project, unfold its app.rc, and unfold the Version folder. You can see the VS_VERSION_INFO item.
Mark the VS_VERSION_INFO item and pres Delete key on the keyboard. The item and its upper Version folder disappear.
Mouse right-click the app.rc folder, and select the Resource Includes.... The dialog with the same name and with three input panes appear.
Focus on the bottom pane named Compile-time directives:, and write the #include "version.rc2" there. (The file must not have the .rc extension, but the .rc2 is fine and recommended elsewhere in the MSDN doc.)
Press OK, and save all files (to save also the modified app.rc).
The result of the steps is that you will not see the Version folder and the VS_VERSION_INFO item in the resource tree (see Resource View tab); however, the above mentioned constructed Version section (stored inside the version.rc2) is compiled into the application resources.
Technically, the following parts of the app.rc file can be found after the steps:
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
...
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Any constructive comments to enhance the topic are welcome and will be +1-ed :)
Have a nice time,
Petr

Inno Setup: copy file to multiple destinations defined by user

During installation process user has ability to install number of some service instances (Service1- ServiceN). All the differences between these services - content of configuration files(actually there is only one executable in /Product_Root/run wich is called with different command-line params).Configuration files situated in ProductRoot/ServiceX/conf.
Folders structure looks like :
/Product_Root
----/bin
----/doc
----/Service1
---------/conf
----/Service2
---------/conf
...
----/ServiceN
---------/conf
In ProductRoot/ServiceX/conf is situated, for example, service.properties file with these contents:
#...
ServiceRoot = <%ROOT_DIRECTORY%>
ListenPort = <%PORT%>
#...
Also in /Product_Root/bin scripts for each service startup should be present:
For example :
/Product_Root/bin/Service1.run.cmd
/Product_Root/bin/Service2.run.cmd
...
/Product_Root/bin/ServiceN.run.cmd
...
Script file structure is:
service.exe ../<%SERVICE_NAME%>/conf/service.properties
All values (like <%SERVICE_NAME%>,<%PORT%> etc.) are set by user during setup process for each Service.
Amount of services is also set by user and may vary between 1 (by default) and 20-30.
In case of single service - there is no problem.
Files being copied, directories created using
[Files]
Source: {#FilesPath}\bin\*.*; DestDir: {app}\{#FileLocationPrefix}\bin; Flags: ignoreversion restartreplace
Source: {#АilesPath}\conf\*.*; DestDir: {app}\{#FileLocationPrefix}\{code:GetServiceName}\conf; Flags: ignoreversion recursesubdirs createallsubdirs restartreplace;
[Dirs]
Name: {app}\{#FileLocationPrefix}{code:GetServiceName}\conf
After in ssPostInstall step wildcards replace performed in copied files.
Question.
is it possible using Inno Setup + ISTool to do the same in case of number of services?
E.g. something like that :
[Files]
#for (i = 0; i < ServiceCount(); ++i)
Source: {#АilesPath}\conf\*.*; DestDir: {app}\{#FileLocationPrefix}\{code:GetServiceName| i}\conf; Flags: ignoreversion recursesubdirs createallsubdirs
where i — is actually configuration number.
I.e. is it possible to use information received from user during installation process in [File], [Dirs] etc. sections for multiple copying of the same files in different directories?
For copying single file in number of files with different names set by user during install process?
Or I just going in the wrong direction?
So, currently I've done this in such way. Comments are welcome.
For creating and copying all files:
#define MaxFEInstances 20
...
#sub CreateConf
Source: {#FilesPath}\conf\*.*; DestDir: {app}\{#FileLocationPrefix}{code:GetServiceName|{#counter}}\conf; Flags: ignoreversion recursesubdirs createallsubdirs restartreplace; Check: InstanceSetupRequired({#counter}); Components: main
#endsub
#for {counter = 0; counter < MaxInstances; ++counter} CreateConf
enter code here
...
function InstanceSetupRequired(InstanceNum: Integer): Boolean;
begin
Result := InstanceNum < Instances;
end;
For separate files it looks pretty same.

Resources