NSIS - Installer: Compare Kit Version with Header file define variable and update if wrong define variable value - scripting

I'm new to NSIS installer scripting. I have created a NSIS script to replace our WISE installer script. I want to write a logic to compare Kit version(Folder name say A1.2.3 where A denotes Alhpa kit) with !define APP_Version(on header) file during compile time and if define variable is wrong, I want to update Header file with correct value. Here is the logic I came up with but I don't know how to update the update the header file.
Section
System::Call "kernel32::GetCurrentDirectory(i ${NSIS_MAX_STRLEN}, t .r0)"
${WordFind} "$0" "\" "-1" $R0
!if "$R0" != "${APP_CLASSKIT}${APP_VERSION}"
MessageBox MB_OK "No Match: $R0"
!undef verifykit
!define APP_VERSION "$R0"
!else
MessageBox MB_OK "Match: ${APP_CLASSKIT}${APP_VERSION}"
!undef verifykit
!define APP_VERSION "${APP_CLASSKIT}${APP_VERSION}"
!endif
SectionEnd

You can't mix and match run-time and compile-time instructions like that. If you want to detect this on the machine you are compiling on you can only use the instructions starting with !.
If you just want to detect the problem:
!macro PrepareExample
!system 'mkdir ".\A1.2.3"'
!macroend
!insertmacro PrepareExample ; For Stackoverflow
!define APP_CLASSKIT A
!define APP_VERSION 1.2.3
!if ! /FileExists ".\${APP_CLASSKIT}${APP_VERSION}\*"
!error "Incorrect kit version, ${APP_CLASSKIT}${APP_VERSION} not found!"
!endif
Section
SetOutPath $InstDir
File /r ".\${APP_CLASSKIT}${APP_VERSION}"
SectionEnd
The compile-time part of the compiler is not really suited to search for folders with a specific pattern. It is much better to invoke a batch/powershell/wsh script and let that create a .nsh file you can include:
!macro PrepareExample
!system 'mkdir ".\A1.2.3"'
!delfile 'findkit.bat'
!appendfile 'findkit.bat' '#echo off$\r$\n'
!appendfile 'findkit.bat' 'echo.TODO: Use FOR or some other batch command to find the correct kit folder.$\r$\n'
!appendfile 'findkit.bat' 'for /D %%A in (??.*) do ($\r$\n'
!appendfile 'findkit.bat' ' echo.This batch file just fakes it$\r$\n'
!appendfile 'findkit.bat' ' echo !define APP_CLASSKIT A >> "%~1"$\r$\n'
!appendfile 'findkit.bat' ' echo !define APP_VERSION 1.2.3 >> "%~1"$\r$\n'
!appendfile 'findkit.bat' ')$\r$\n'
!macroend
!insertmacro PrepareExample ; For Stackoverflow
!tempfile KitNsh
!system '"findkit.bat" "${KitNsh}"'
!include "${KitNsh}"
!delfile "${KitNsh}"
!ifndef APP_CLASSKIT | APP_VERSION
!error "No kit detected"
!endif
!echo "Using kit ${APP_CLASSKIT}${APP_VERSION}"
Section
...
SectionEnd

Related

How to modify sed awk command to work with relative path

Context
I had a SO question successfully answered at https://stackoverflow.com/a/59244265/80353
I have successfully used the command that was given.
cap()(cd /tmp;rm -f *.vtt;youtube-dl --skip-download --write-auto-sub "$1";\
sed '1,/^$/d' *.vtt|sed 's/<[^>]*>//g'|awk -F. 'NR%8==1{printf"%s ",$1}NR%8==3'\
|tee -a "$2")
What does this command do?
This command will download captions for a youtube video as a .vtt file from $1 parameter
then print out the simplified version of the .vtt file into another file that's stated as parameter $2
This works as advertised.
How to call the command
In the terminal I will run the above command once and then run cap $youtube_url $full_path_to_output_file
What changes I would like
Currently, the $2 parameter must be a full path. Also currently, if the $2 parameter doesn't exist, an actual file will be created. What I would like is this behavior remains even for relative path. So hopefully for relative path, this behavior of creating a new empty file still works.
Update
I see that comments are such that there's nothing wrong with the command.
However, I did try running
cap $youtube_url $relative_path_to_a_text_file and it definitely did not work for me in macOS
Perhaps I am missing something else?
Update 2
This is a video of me running the awk sed command . First I did it with just a relative path. No output file shows up in the current working directory. The second shows me typing the full path and it works.
https://www.loom.com/share/1c179506fa5b48b4a3d62c81a9d2a411
I hope this clarifies the question i am raising and the commenters would kindly update their comments based on this video.
EDIT: Adding a solution after OP's comment which do checks inside OP's function itself, warning not tested it though.
cap()(
user_path=$(echo "$path_details" | awk 'match($0,/.*\//){print substr($0,RSTART,RLENGTH)}')
path_details="$2"
PWD=`pwd`
cd "$PWD"
user_path=$(echo "$path_details" | awk 'match($0,/.*\//){print substr($0,RSTART,RLENGTH)}')
if [[ -d "$user_path" ]]
then
echo "Present path $user_path."
##Call your program here....##
cd /tmp;rm -f *.vtt;youtube-dl --skip-download --write-auto-sub "$1";\
sed '1,/^$/d' *.vtt|sed 's/<[^>]*>//g'|awk -F. 'NR%8==1{printf"%s ",$1}NR%8==3'\
|tee -a "$2"
else
echo "NOT present path $user_path."
##Can exit from here. if needed.##
fi
)
I believe OP wants to check directory of relative path passed as 2nd argument, is present or not, if this is the case then one could try following.
cat file.ksh
path_details="$2"
PWD=`pwd`
##Why I am going to your path is, in case you are running this from cron, so in that case you can mention complete path here, rather than pwd as mentioned above.
cd "$PWD"
user_path=$(echo "$path_details" | awk 'match($0,/.*\//){print substr($0,RSTART,RLENGTH)}')
if [[ -d "$user_path" ]]
then
echo "Present path $user_path."
##Call your program here....##
else
echo "NOT present path $user_path."
##Can exit from here. if needed.##
fi
Explanation: Adding detailed explanation for above code.
cat file.ksh ##For OP reference to show content I am using cat script_name here.
path_details="$2" ##Creating variable path_details whose value is $2(2nd argument passed to script)
PWD=`pwd` ##Creating variable PWD whose value is pwd(current working directory).
##Why I am going to your path is, in case you are running this from cron, so in that case you can mention complete path here, rather than pwd as mentioned above.
cd "$PWD" ##Going to current directory, why I did is you can set PWD above variable value as per your need and navigate to that path, this will help in case of script is running from Cron.
user_path=$(echo "$path_details" | awk 'match($0,/.*\//){print substr($0,RSTART,RLENGTH)}') ##Now getting path details from passed 2nd argument for script.
if [[ -d "$user_path" ]] ##Checking if user_path(path value is existing on system)
then
echo "Present path $user_path."
##Call your program here....## ##If path existing then call your program.
else ##If path NOT existing then exit from program or print message up to you :)
echo "NOT present path $user_path."
##Can exit from here. if needed.##
fi ##Closing if condition here.

CMake cannot find environment variables within WSL

Cmake cannot find an environment variable defined in /etc/profile from within WSL.
I've tried putting the variable in other file such as /etc/environment but could not get it to echo in WSL. Finally using /etc/profile I get an echo.
/etc/environment
TEST="/some/path"
echo $TEST
>>
/etc/profile
TEST="/some/path"
echo $TEST
>>/some/path
My CMakeLists.txt has the following lines:
set(TEST $ENV{TEST})
message(STATUS "Output: ${TEST}")
When building, it outputs
>>Output:
This question had a similar issue : Here. Nonetheless I've already tried using bash.exe -i. Also tried setting the next line in my CMakeLists.txt
set(ENV{BASH_ENV}"~/.bashrc")

Graphviz multiple files format conversion

I want to convert several files (>100) from .dot format (generated by Doxygen) to .png format, using Graphviz.
Following page describes the file conversion for only one file:
Graphviz: How to go from .dot to a graph?
dot -Tpng input.dot > output.png
Now, I want to proceed with a massive conversion proccess, which involves a lot of files inside a directory.
Most of documentation is for Linux OS, like the following:
https://github.com/rakhimov/cppdep/wiki/How-to-view-or-work-with-Graphviz-Dot-files
( as example:
To run dot on files in directories and sub-directories recursively:
$ find -type f -name "*.dot" directory_path | xargs dot -Tpdf -O )
but I really need to do it on Windows OS.
I have been trying with the following command:
forfiles /c "dot -Tpng #file > #fname.png"
however, in this case, Windows cmd shows the error message:
"There is no layout engine support for "-tpng"
Use one of: circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi"
for each one of the file conversion attemps.
How it can be done?
Thanks for your time.
Try this, it worked for me:
forfiles /m "*.dot" /c "cmd /c dot -Tpng #file > #fname.png"
or, if the extension is ".gv"
forfiles /m "*.gv" /c "cmd /c dot -Tpng #file > #fname.png"

"Echo is OFF" text always inserted into batch file when SET variable is written to a batch file IF the file is made by another batch program

I am trying to create a batch file using another batch program using:
#echo {code here}>>batch-program.bat, but whenever I try to write code to write the contents of a SET variable to a text file, the batch program does not write the code into the other batch file, but instead writes "Echo is OFF."
Code is here:
#echo off
#echo #echo off>>apt.bat
#echo color 2A>>apt.bat
#echo echo example-batch>>apt.bat
#echo cd C:/Users/Default/apt/assets>>apt.bat
#echo mkdir cmdInput>>apt.bat
#echo cd C:/Users/Default/apt/assets/cmdInput>>apt.bat
#echo set /p cmdInput= cmd->>apt.bat
#echo %cmdInput%>>used-cmdInput.txt>>apt.bat
#echo pause>>apt.bat
This should have created a batch file named apt.bat, and written into the batch file:
#echo off
echo color 2A
echo example-batch
cd C:/Users/Default/apt/assets
mkdir cmdInput
cd C:/Users/Default/apt/assets/cmdInput
set /p cmdInput= cmd-
%cmdInput%>>used-cmdInput.txt
pause
but the 9th line (%cmdInput%>>used-cmdInput.txt)
is instead converted into the text line "Echo is OFF".
Have I done anything wrong, or is it just a really weird bug?
EDIT: I found another problem in the program, that because mkdir cmdInput is always run when apt.bat is run, so it displays a error message because of apt.bat trying to create the directory cmdInput though it already exists. apt/assets. So I have changed the code a bit, so that the directory cmdInput is created in the first "creation" batch file (the program that was used to create apt.bat). mkdir cmdInput has been removed from apt.bat.
You need to escape > with ^ but you need to escape % with %
#echo %%cmdInput%%^>^>used-cmdInput.txt>>apt.bat
unless you want to output the contents of cmdinput where you need
#echo %cmdInput%^>^>used-cmdInput.txt>>apt.bat
You can add 2>nul to the end of a md command to suppress the error message generated if the directory already exists.
You should use backslashes \ in directorynames, not forward slashes /. In winbat, the forward slash is often used for command switches. Sometimes forward slashes will work for directorynames, but backslashes always work.
You just have to "escape" the percent-signs with another % and other special chars like > with a caret) to prevent evaluation of your variable %cmdInput% (which probably is empty - therefore the Echo is off).
Also a single #echo off is sufficient. No need to add a # to every line.
#echo off
echo #echo off>>apt.bat
echo color 2A>>apt.bat
echo echo example-batch>>apt.bat
echo cd C:/Users/Default/apt/assets>>apt.bat
echo mkdir cmdInput>>apt.bat
echo cd C:/Users/Default/apt/assets/cmdInput>>apt.bat
echo set /p cmdInput= cmd->>apt.bat
echo %%cmdInput%%^>^>used-cmdInput.txt>>apt.bat
echo pause>>apt.bat
A more elegant way is to use only a single redirection (cmdhas to open the file for writing just once):
#echo off
(
echo #echo off
echo color 2A
echo echo example-batch
echo cd C:/Users/Default/apt/assets
echo mkdir cmdInput
echo cd C:/Users/Default/apt/assets/cmdInput
echo set /p cmdInput= cmd-
echo %%cmdInput%%^>^>used-cmdInput.txt
echo pause
)>apt.bat

How do you reference a shell script packaged in your app bundle?

Given two scripts
foo.sh
bar.sh
copied under /Contents/Resources in an .app bundle, where foo.sh
#!/bin/bash
. ./bar.sh
echo $1
Do get an error of
No such file or directory
on the line where the script tries to source bar.sh
Is there a way to relatively reference bar.sh?
Is there another way to bundle a set of bash scripts in a .app?
What you can do is:
get the full path & directory where the actual running script (your foo.sh) is stored. see https://stackoverflow.com/a/246128/3701456
call or source the second script (your bar.sh) with directory from 1. (or relative to that directory)
Simple Example:
$cat script2
#! /usr/bin/env bash
echo "Hello World, this is script2"
$cat script1
#! /usr/bin/env bash
echo "Hello World from script 1"
echo "Full script path: $BASH_SOURCE"
echo "extracted directory: $(dirname $BASH_SOURCE)"
echo "running script 2"
$(dirname $BASH_SOURCE)/script2 && echo "running script 2 successful" || echo "error running script 2"
echo "sourcing script 2"
source $(dirname $BASH_SOURCE)/script2 && echo "sourcing script 2 successful" || echo "error sourcing script 2"
Test:
$ls /tmp/test
script1 script2
$pwd
/home/michael
$/tmp/test/script1
Hello World from script 1
Full script path: /tmp/test/script1
extracted directory: /tmp/test
running script 2
Hello World, this is script2
running script 2 successful
sourcing script 2
Hello World, this is script2
sourcing script 2 successful
See link above for more in detail discussion ...
Old question but to address the last part (reflecting the current Apple guidelines): yes, you should definitely place all executables (including scripts) in the MacOS sub-folder of your bundle:
MacOS - (Required) Contains the application’s standalone executable code. Typically, this directory contains only one binary file with your application’s main entry point and statically linked code. However, you may put other standalone executables (such as command-line tools) in this directory as well.
(Source: Anatomy of a macOS Application Bundle.)
Breaking these rules will prevent you from successfully signing your app bundle for Gatekeer (and, of course, macOS Notarization).
The first part was adequately handled by the other response.