Change variables via command line NSIS installer - command-line

I would like to change variables within NSIS through command line arguments. I see in the documentation you can change global variables, but not created ones within the NSIS script.
For example: if I had
Var example
StrCpy $example "C:\Program Files (x86)\Installer"
Is it possible to change the example variable string through command line arguments?

OutFile "MySetup.exe"
Name "MySetup"
RequestExecutionLevel user
!include FileFunc.nsh
!include LogicLib.nsh
Var MyVar
Function .onInit
StrCpy $MyVar "Default value"
${GetParameters} $0
ClearErrors
${GetOptions} $0 "/MyVar=" $1 ; Get suffix after "/MyVar=" switch
${IfNot} ${Errors}
StrCpy $MyVar $1
${EndIf}
FunctionEnd
Section
MessageBox mb_OK MyVar:$MyVar
SectionEnd
and execute as "MySetup.exe" /MyVar="Hello world"

Related

Are environment variables preserved through qx in a perl script

I have some legacy perl script, which sets environment variable
$ENV{"ENV_VAR_NAME"} = $envVar;
and then uses qx() to execute another shell command
$command = "$xyz";
$result = qx($command);
Will the modified ENV_VAR_NAME be available when
qx executes the new command.
Yes.
perlvar says about %ENV:
Setting a value in ENV changes the environment for any child processes you subsequently fork() off.
And qx does indeed spawn a child process, which can therefore access your modified environment variables.
This can be easily tested:
print "1: ", qx(echo \$X); # Prints "1: "
$ENV{X} = 42;
print "2: ", qx(echo \$X); # Prints "2: 42"

Calling another function in fish shell

I received this excellent answer on how to convert a zsh function to a fish function. Now I have another question. How do I call that function from another function, passing on the argument?
I have tried this:
function ogf
echo "Cloning, your editor will open when clone has completed..."
source (env TARGET_DIRECTORY=~/students EDITOR=$EDITOR clone_git_file -ts $argv[1] | psub)
end
function wogf
env EDITOR=webstorm ogf "$argv[1]"
end
but I get "env: ogf: No such file or directory".
The goal is only to change the EDITOR environment variable for this one execution, and then call ogf.
The env command can only run other external commands. It cannot call shell builtins or functions; regardless whether the shell is fish, bash, or something else. The solution is to define the function being called with the --no-scope-shadowing flag and use set -l in the calling function:
function ogf --no-scope-shadowing
echo "Cloning, your editor will open when clone has completed..."
source (env TARGET_DIRECTORY=~/students EDITOR=$EDITOR clone_git_file -ts $argv[1] | psub)
end
function wogf
set -l EDITOR webstorm
ogf $argv
end
Another option would be to write your function to use its own arguments, as follows:
function ogf
echo "Cloning, your editor will open when clone has completed..."
source (env TARGET_DIRECTORY=~/students EDITOR=$argv[2] clone_git_file -ts $argv[1] | psub)
end
function wogf
ogf $argv[1] 'webstorm'
end
Maybe this is a simpler example on how to call another function while passing arguments:
function foo
bar "hello" "world"
end
function bar
echo $argv[1]
echo $argv[2]
end
Then calling foo will print:
$ foo
hello
world

Perl: import shell variable

In shell, I had sourced .cshrc file which contains some defined variables like user name.
I need to pass these variables to a certain Perl script.
For example in shell terminal, I typed
>echo $user
The output is >esaad
Then in Perl, to read $user variable, I tried:
system("echo $user")
Also tried this command:
my $userName = system( echo $ENV{user} );
but Perl asked for $user initialization as Perl variable not Shell one.
How I could read this variable?
You can:
print $ENV{'user'}
the reason your system call doesn't work is that system open a new shell that doesn't source .cshrc
read this answer for more information
Either use Perl built-in system variable $ENV:
print $ENV{'user'}
Or use backslash to escape the variable $user. Perl will interpret for $user variable defined inside the Perl program without the backslash. With backslash, "echo $user" is passed as system call.
system("echo \$user")

NSIS check state of Windows Service

I am writing NSIS script and i need to check service state (Running/Stopped/Paused/No exist) and to make some actions then.
But i can`t use any user libs such as nsSCM.
I found a script
sc QUERY ServiceNameHere | FIND "RUNNING"
but i can`t find how to check the return result in NSIS script.
Please help.
If you can use plug-ins:
Using the Simple Service Plugin, you can do this:
SimpleSC::GetServiceStatus "MyService"
Pop $0 ; returns an errorcode (!=0) otherwise success (0)
Pop $1 ; return the status of the service (see below)
If successful, the service status will have one of the following numeric values:
STOPPED
START_PENDING
STOP_PENDING
RUNNING
CONTINUE_PENDING
PAUSE_PENDING
PAUSED
If you can NOT use plug-ins:
Note that I added /C to FIND.exe to output the line count instead of the entire line. Also, be careful modifying the quotes. It took some trial and error to get that right.
StrCpy $R0 '"$SYSDIR\cmd.exe" /c "sc QUERY MyServiceName | FIND /C "RUNNING""'
nsExec::ExecToStack '$R0'
Pop $R1 # contains return code
Pop $R2 # contains output
${If} $R1 == "0"
# command success
${If} $R2 == "1"
# it's running
${Else}
# it's not running
${EndIf}
${Else}
# command failed
${EndIf}
Be sure to include the logic library, as NSIS requires this for conditional statement macros:
# Included files
!include LogicLib.nsh
There are several NSIS plugins and helper functions that deal with NT services: NSIS Service Lib, NSIS Simple Service Plugin and NsSCM. The wiki has a overview of all your options.
Using sc.exe is problematic since the output might be localized, net.exe is probably better (And it also exits on < WinXP) here is my take on that solution:
!include LogicLib.nsh
StrCpy $1 "Event Log" ;Put your service name here
ExpandEnvStrings $0 "%comspec%"
nsExec::ExecToStack '"$0" /k "net start | FIND /C /I "$1""'
Pop $0
Pop $1
StrCpy $1 $1 1
${If} "$0$1" == "01"
MessageBox mb_ok "Running"
${Else}
MessageBox mb_ok "Not Running"
${EndIf}
I check if a service is running by using its DISPLAY name (not the service name), because it tends to be more precise (e.g. service name is JETTY while the DISPLAY name uses my product name - I avoid the risk of counting a JETTY service installed by another product).
So based on Kyle's solution I use:
var running
!macro CheckMyService
StrCpy $running "0"
StrCpy $cmd '"$SYSDIR\cmd.exe" /c "net start | FIND /C "MyServiceDisplayName""'
nsExec::ExecToStack '$cmd'
Pop $R1 # contains return code
Pop $R2 # contains output
StrCpy $n $R2 1
${If} $R1 == "0"
${If} $n == "1"
StrCpy $running "1"
${EndIf}
${EndIf}
DetailPrint "runnning(1=yes): $running"
!macroend

Handling Perl command line arguments with spaces from a bash script?

This has been driving me nuts for hours now.
Consider the following test script in perl:
(hello.pl)
#!/usr/bin/perl
print "----------------------------------\n";
$numArgs = $#ARGV + 1;
print "thanks, you gave me $numArgs command-line arguments:\n";
foreach $argnum (0 .. $#ARGV) {
print "$ARGV[$argnum]\n";
}
Ok, it simply prints out the command line arguments given to the script.
For instance:
$ ./hello.pl apple pie
----------------------------------
thanks, you gave me 2 command-line arguments:
apple
pie
I can give the script a single argument with a space by surrounding the words with double quotes:
$ ./hello.pl "apple pie"
----------------------------------
thanks, you gave me 1 command-line arguments:
apple pie
Now I want to use this script in a shell script. I've set up the shell script like this:
#!/bin/bash
PARAM="apple pie"
COMMAND="./hello.pl \"$PARAM\""
echo "(command is $COMMAND)"
$COMMAND
I am calling the hello.pl with the same params and escaped quotes.
This script returns:
$ ./test.sh
(command is ./hello.pl "apple pie")
----------------------------------
thanks, you gave me 2 command-line arguments:
"apple
pie"
Even though the $COMMAND variable echoes the command exactly like the way I ran the perl script from the command line the second time, this time it does not want to see the apple pie as a single argument.
Why not?
This looks like the problem described in the Bash FAQ as: I'm trying to put a command in a variable, but the complex cases always fail!
The answer to that FAQ suggests a number of possible solutions - I hope that's of use.
The issue of the 2 command-line arguments
"apple
pie"
is due to shell expansion with the IFS shell variable being set to have a space as value.
printf '%q\n' "$IFS" # show value of IFS variable
You may use xargs & sh -c '...code...' to mimic / re-enable ordinary parameter parsing.
PARAM="'apple pie'"
printf '%s' "$PARAM" | xargs sh -c './hello.pl "$#"' argv0
Another option may be to write a few lines of C (like in shebang.c)!
http://www.semicomplete.com/blog/geekery/shebang-fix.html
You should try eval $COMMAND instead of simply $COMMAND.