Inno Setup - Get info on file in installer - inno-setup

How do you get information (last modification timestamp, file size) about a file which is included in the installer? It's easy to reference a file on disk, by using its path. But how do you reference a file in the installer when it doesn't have a path?
When the installer initialises, I would like to check if any of the files to be installed are already on the disk. For those files that are already on the disk (same last modification timestamp and same file size), I would like to display a window for the user to be able to select which ones they want to overwrite.

The following preprocessor code will generate a Pascal Scripting function that returns timestamp string for given relative file path:
#define SourcePath "C:\myappfiles"
function GetSourceFileDateTimeString(FileName: string): string;
begin
#define FileEntry(FileName, SourcePath) \
Local[0] = GetFileDateTimeString(SourcePath, "yyyy/mm/dd hh:nn:ss", "-", ":"),\
" if SameText(FileName, '" + FileName + "') then " + \
"Result := '" + Local[0] + "'" + NewLine + \
" else" + NewLine
#define ProcessFile(Root, Path, FindResult, FindHandle) \
FindResult \
? \
Local[0] = FindGetFileName(FindHandle), \
Local[1] = (Len(Path) > 0 ? Path + "\" : "") + Local[0], \
Local[2] = Root + "\" + Local[1], \
(Local[0] != "." && Local[0] != ".." \
? (DirExists(Local[2]) \
? ProcessFolder(Root, Local[1]) \
: FileEntry(Local[1], Local[2])) \
: "") + \
ProcessFile(Root, Path, FindNext(FindHandle), FindHandle) \
: \
""
#define ProcessFolder(Root, Path) \
Local[0] = FindFirst(Root + "\" + Path + "\*", faAnyFile), \
ProcessFile(Root, Path, Local[0], Local[0])
#emit ProcessFolder(SourcePath, "")
RaiseException(Format('Unexpected file "%s"', [FileName]));
end;
The generated script will be like:
function GetSourceFileDateTimeString(FileName: string): string;
begin
if SameText(FileName, 'sub1\file1.exe') then Result := '2022-02-16 18:18:11'
else
if SameText(FileName, 'sub2\file2.exe') then Result := '2022-02-16 18:18:11'
else
if SameText(FileName, 'file3.exe') then Result := '2022-02-19 09:50:14'
else
if SameText(FileName, 'file4.exe') then Result := '2022-02-19 09:50:14'
else
RaiseException(Format('Unexpected file "%s"', [FileName]));
end;
(See Inno Setup: How do I see the output (translation) of the Inno Setup Preprocessor?)

Related

How to pass string with spaces pyspark arguments in spark-on-k8s-operator

One of the pyspark arg is sql query (string with spaces).
I tried to pass it as - \"select * from table\" and "select * from table"
But it's not treated it as a whole string and select * bash command is getting executed which is corrupting the SQL.
Example: Above query got converted as - \"select' folder1 file1.zip from 'table\"
Driver Logs:
PYSPARK_ARGS=
+ '[' -n 'process --query \"select * from table\"' ']'
+ PYSPARK_ARGS='process --query \"select * from table\"'
+ R_ARGS=
+ '[' -n '' ']'
+ '[' 3 == 2 ']'
+ '[' 3 == 3 ']'
++ python3 -V
+ pyv3='Python 3.7.3'
+ export PYTHON_VERSION=3.7.3
+ PYTHON_VERSION=3.7.3
+ export PYSPARK_PYTHON=python3
+ PYSPARK_PYTHON=python3
+ export PYSPARK_DRIVER_PYTHON=python3
+ PYSPARK_DRIVER_PYTHON=python3
+ case "$SPARK_K8S_CMD" in
+ CMD=("$SPARK_HOME/bin/spark-submit" --conf "spark.driver.bindAddress=$SPARK_DRIVER_BIND_ADDRESS" --deploy-mode client "$#" $PYSPARK_PRIMARY $PYSPARK_ARGS)
+ exec /usr/bin/tini -s -- /opt/spark/bin/spark-submit --conf spark.driver.bindAddress=xx.xx.xx.xx --deploy-mode client --class org.apache.spark.deploy.PythonRunner file:/usr/local/bin/process_sql.py process
--query '\"select' folder1 file1.zip from 'table\"'
Is there a way to safely pass string argument with spaces, single or double quotes?

How to pad version components with zeroes for OutputBaseFilename in Inno Setup

I have Inno Setup 6.1.2 setup script where the version main.sub.batch is formed like this:
#define AppVerText() \
GetVersionComponents('..\app\bin\Release\app.exe', \
Local[0], Local[1], Local[2], Local[3]), \
Str(Local[0]) + "." + Str(Local[1]) + "." + Str(Local[2])
Later in the setup part, I use it for the name of setup package:
[Setup]
OutputBaseFilename=app.{#AppVerText}.x64
The resulting filename will be app.1.0.2.x64.exe, which is mighty fine. To make it perfect, I'd like to end up with form app.1.00.002.x64.exe with zero-padded components.
I did not find anything like PadLeft in documentation. Unfortunately I also fail to understand how to use my own Pascal function in this context. Can I define a function in Code section for this?
A quick and dirty solution to pad the numbers in the Inno Setup preprocessor:
#define AppVerText() \
GetVersionComponents('..\app\bin\Release\app.exe', \
Local[0], Local[1], Local[2], Local[3]), \
Str(Local[0]) + "." + \
(Local[1] < 10 ? "0" : "") + Str(Local[1]) + "." + \
(Local[2] < 100 ? "0" : "") + (Local[2] < 10 ? "0" : "") + Str(Local[2])
If you want a generic function for the padding, use this:
#define PadStr(S, C, L) Len(S) < L ? C + PadStr(S, C, L - 1) : S
Use it like:
#define AppVerText() \
GetVersionComponents('MyProg.exe', \
Local[0], Local[1], Local[2], Local[3]), \
Str(Local[0]) + "." + PadStr(Str(Local[1]), "0", 2) + "." + \
PadStr(Str(Local[1]), "0", 3)
Pascal Script Code (like this one) won't help here, as it runs on the install-time, while you need this on the compile-time. So the preprocessor is the only way.

Automate obtaining the SHA256 for a file to download with Inno Setup 6.1?

The documentation for DownloadTemporaryFile says this about the RequiredSHA256OfFile parameter:
If RequiredSHA256OfFile is set it will compare this to the SHA-256 of the downloaded file and raise an exception if the hashes don't match.
An exception will be raised if there was an error. Otherwise, returns the number of bytes downloaded. Returns 0 if RequiredSHA256OfFile is set and the file was already downloaded.
From the answer here I have determined that the correct commandline method to obtain the checksum is:
CertUtil -hashfile MSAHelpDocumentationSetup.exe SHA256
This is how I add adding this particular file to my script:
AddFileForDownload('{#HelpDocSetupURL}', 'HelpDocSetup.exe');
Which expands to:
procedure AddFileForDownload(Url, FileName: string);
begin
DownloadPage.Add(Url, FileName, '');
FilesToDownload := FilesToDownload + ' ' + ExtractFileName(FileName) + #13#10;
Log('File to download: ' + Url);
end;
Is there way to automate:
Obtaining the checksum for my file.
Caching that checksum into a string.
Using that checksum value when building the script.
By automating this task it will provide two benefits:
Minimize user error in copy /pasting the checksum value.
Keep the checksum update to date without user interaction.
Is this feasible in Inno Setup with Pascal Script?
Pascal Script won't help you. You need the value at the compile time. So using a preprocessor. You can indeed execute the certutil. But imo, in this case, it's easier to use PowerShell and its Get-FileHash cmdlet:
#define GetSHA256OfFile(FileName) \
Local[0] = AddBackslash(GetEnv("TEMP")) + "sha256.txt", \
Local[1] = \
"-ExecutionPolicy Unrestricted -Command """ + \
"Set-Content -Path '" + Local[0] + "' -NoNewline -Value " + \
"(Get-FileHash('" + FileName + "')).Hash" + \
"""", \
Exec("powershell.exe", Local[1], SourcePath, , SW_HIDE), \
Local[2] = FileOpen(Local[0]), \
Local[3] = FileRead(Local[2]), \
FileClose(Local[2]), \
DeleteFileNow(Local[0]), \
LowerCase(Local[3])
And then you can use it like:
AddFileForDownload(
'{#HelpDocSetupURL}', 'HelpDocSetup.exe', '{#GetSHA256OfFile("HelpDocSetup.exe")}');
You of course need to add the third parameter to your AddFileForDownload function and pass it to TDownloadWizardPage.Add. You also may need to add a path to the file, so that the preprocessor can find it.

Trying to create Redshift table in python using psycopg2.sql

I'm trying to create this table in redshift via python using psycopg2:
sql = "CREATE TABLE if not exists " + "<schema>.<tablename> " + \
"( vendorid varchar(4), pickup_datetime TIMESTAMP, " + \
"dropoff_datetime TIMESTAMP, store_and_fwd_flag varchar(1), " + \
"ratecode int, pickup_longitude float(4), pickup_latitude float(4)," + \
"dropoff_logitude float(4), dropoff_latitude float(4), " + \
"passenger_count int, trip_distance float(40), fare_amount float(4), " + \
"extra float(4), mta_tax float(4), tip_amount float(4), " + \
"tolls_amount float(4), ehail_fee float(4), improvement_surcharge float(4), " + \
"total_amount float(4), payment_type varchar(4), trip_type varchar(4)) " + \
"DISTSTYLE EVEN SORTKEY (passenger_count, pickup_datetime);"
Schema.tablename to be entered via command line so I need a variable to hold sys.arg[0]...but how do I construct that using OR should I use psycopg2.sql??
If I've understood correctly, you want to run your python script on a command line and pass a couple of arguments that include the schema and table name of the Redshift table.
You can use the argparse library to parse the command line arguments into variables and then concatenate them into the sql string:
import argparse
...
# ---------------------------------------------------------------------------------#
# Parse arguments
# ---------------------------------------------------------------------------------#
parser = argparse.ArgumentParser()
parser.add_argument("schema")
parser.add_argument("table")
args = parser.parse_args()
schema_name = args.schema
table_name = args.table
...
sql = "CREATE TABLE if not exists " + schema_name + "." + table_name + " " +\
"( vendorid varchar(4), pickup_datetime TIMESTAMP, " + \
"dropoff_datetime TIMESTAMP, store_and_fwd_flag varchar(1), " + \
"ratecode int, pickup_longitude float(4), pickup_latitude float(4)," + \
"dropoff_logitude float(4), dropoff_latitude float(4), " + \
"passenger_count int, trip_distance float(40), fare_amount float(4), " + \
"extra float(4), mta_tax float(4), tip_amount float(4), " + \
"tolls_amount float(4), ehail_fee float(4), improvement_surcharge float(4), " + \
"total_amount float(4), payment_type varchar(4), trip_type varchar(4)) " + \
"DISTSTYLE EVEN SORTKEY (passenger_count, pickup_datetime);"
...
You can call your script on the command line like so:
python my_script.py myschema mytable

inno setup exec sqlcmd command problems with files path with spaces

i am trying to execute 2 scripts using inno setup.
The problem i think is the path of the file that contains spaces.
The scripts are working because i already tried the hardcoded path with no spaces and it does work.
there is this post where this problem is discribed and a solution is added but i have tried and it doesnt work.
this is the topic Inno Setup, spaces and double quote in [Run]
in order not to use hardcoded paths i am using inno setup constants, so on the output folder i have a setup.exe and and folder called testfolder with the 2 scripts, one is for creating a database, and the other is to create the tables.
in inno setup did this
connExe:=ExpandConstant('{tmp}')+'\sqlcmd.exe';
pathFx1:=ExpandConstant('{src}')+'\testfolder\teste.sql';
pathFx2:=ExpandConstant('{src}')+'\testfolder\idontimedb.des';
Exec(connExe,' -S DEV3\IDONICSYS4 -U sa -P idsysadmin -i \""'+connFx1+'\""', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
MsgBox(IntToStr(ResultCode), mbError, mb_Ok);
Exec(connExe,' -S DEV3\IDONICSYS4 -d MSSQLTIPS -U sa -P idsysadmin -i \""'+connFx2+'\""', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
MsgBox(IntToStr(ResultCode), mbError, mb_Ok);
when i run both messages boxs show code 2,but i am still unable to find what does this code means.
I think my problem is with the backslash and the quotation marks position , but i have already tried different combination and it doesnt work..
Thanks for the help.
the full path of the files are:
C:\Users\hsilva\Documents\Inno setupo scripts\Setup\Output\testfolder\teste.sql \create database
C:\Users\hsilva\Documents\Inno setupo scripts\Setup\Output\testfolder\idontimedb.des \create tables
C:\Users\hsilva\Documents\Inno setupo scripts\Setup\Output\setup.exe \executable
thanks in advance...
UPDATE - 27/10/2014
so as user LTama sugested(thanks once again TLama) i have checked the files that were needed for running the scripts.. and the files needed were commented,i made a few changes and now it is giving me code 1.What does it mean?
i use the code found in this site http://0x3f.org/blog/howto-execute-sql-scripts-in-inno-setup/ and made a few changes.
in the files section i have got this:
Source: "C:\Users\hsilva\Documents\InnoSetup\sqlcmd.exe"; Flags: dontcopy ;
Source: "C:\Users\hsilva\Documents\InnoSetup\sqlcmd.rll"; Flags: dontcopy ;
Do i need to have these 2 files, because when installing sql server 2008 r2, these files are installed , and available?
in the code section i have got this:
procedure DeinitializeSetup();
var
connExe:String;
connFx1:String;
begin
ExtractTemporaryFile('sqlcmd.exe');
ExtractTemporaryFile('sqlcmd.rll');
connExe:=ExpandConstant('{tmp}')+'\sqlcmd.exe';
connFx1:=ExpandConstant('{src}')+'\folder\teste.sql';
Exec(connExe,' -S DEV3\IDONICSYS4 -U sa -P idsysadmin -i \""'+connFx1+'\""', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
MsgBox(IntToStr(ResultCode), mbError, mb_Ok);
end;
end;
this is execute in the end of setup, i ommited some of the checks like checking if the instance exists..
here what i think..
1. Does the command work outside of Inno Setup Script?
Use LOG(); to test the string pass to exe in a command window.
Extract the teste.sql to {tmp}
Source: "C:\Users\hsilva\Documents\InnoSetup\teste.sql"; Flags: dontcopy ;
function CustomForm_NextButtonClick(Page: TWizardPage): Boolean;
var
connExe:String;
connFx1:String;
connTxt:String;
ResultCode: Integer;
begin
// need to sql server in dropdown list
// sqlcmd -L > text.txt
ExtractTemporaryFile('sqlcmd.rll');
ExtractTemporaryFile('sqlcmd.exe');
connExe:=ExpandConstant('{tmp}')+'\sqlcmd.exe';
connTxt := ' -S ' + lstSqlServer.text + ' -U '+ txtUsername.Text + ' -P ' + txtPassword.Text + ' -Q "CREATE DATABASE ' + txtDatabase.Text + '"' + ' -o ' +
// use log to view and test the string in a command window
Log('The Value is connTxt: ' + connTxt );
if Exec(connExe, connTxt, '' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
//MsgBox(IntToStr(ResultCode), mbError, mb_Ok);
ExtractTemporaryFile('onestep2012.sql');
connFx1:=ExpandConstant('{tmp}\OneStep2012.sql');
connTxt := ' -S ' + lstSqlServer.text + ' -U '+ txtUsername.Text + ' -P ' + txtPassword.Text + ' -d ' + txtDatabase.Text + ' -i ' + connFx1 + ' -o ' + ExpandConstant('{tmp}\log.log');
Log('The Value is connTxt: ' + connTxt );
if Exec(connExe, connTxt, '' , SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
MsgBox( 'The '+ txtDatabase.Text + ' OneStep Database is ready for use' , mbInformation, mb_Ok);
result := True;
end;
end;
end;

Resources