PowerShell: Script cannot set a parameter - powershell-2.0

For a script that should be compatible to powerShell 2, I have a param called $exeLoc, declared as follows:
Param(
[parameter()]
[alias("el")]
$exeLoc= '......\sw' )
I try to set that parameter, from relative to absolute in a function, as follows:
Function FromRelToAbs()
{
Push-Location $exeLoc
$Global:exeLoc = (Join-path $PWD -ChildPath '\Vis.exe' )
Pop-Location
}
However, after calling the function above, the value of $exeLoc does not change.
The above code works perfectly on powersell v3 AND in powershell v2 ISE. It does not work properly on a powershell v2 window ( not ISE )
Any ideas ?

I take it your script is something along these lines:
param($x = 2)
write-output "[script] Value of x is 2"
function blah {
$global:x = 5
write-output "[blah] Setting x as 5"
}
Write-Output "Calling function blah"
blah
Write-Output "[script] Value of x is $x"
You set the variable in the script; and within the script is a function that refers to the variable in the global scope and sets its value.
If I try the above on my machine (PowerShell v2) it does set the variable correctly. Maybe I understood your script wrong?

Related

In fish shell, how to set a variable with default fallback?

I'm looking for the equivalent of the following bash syntax, but for the fish shell:
local datafile="${_Z_DATA:-$HOME/.z}"
i.e define a local variable that will take the value of $_Z_DATA if this one is define, or else will take the value of $HOME/.z
As far as I know, there is no syntax for this; you need something like
set datafile "$_Z_DATA"
test -z "$datafile"; and set datafile "$HOME/.z"
or
if set -q _Z_DATA; and test -n _Z_DATA
set datafile "$_Z_DATA"
else
set datafile "$HOME/.z"
fi
Unlike bash, variables defined inside a function are automatically local to that function, so no equivalent to local is needed. (A previous version of this answer used the -l option to localize the variable, but that makes it local to whatever block set occurs in.)
I would write this as:
set -q _Z_DATA; or set _Z_DATA $HOME/.z
on fish 3.0+ you can write:
set -q _Z_DATA || set _Z_DATA $HOME/.z
If you do this a lot you could define a function:
function defaultset --no-scope-shadowing
set -q $argv[1] || set $argv[1] $argv[2..-1]
end
# example usage
defaultset _Z_DATA $HOME/.z
I'm not a fish expert at all, but I wrote a helper function for this:
function default
for val in $argv
if test "$val" != ""
echo $val
break
end
end
end
The function echoes the first value that is not empty. (It works with both numbers and strings, too.)
~> set baz baz
~> default $foo $bar $baz $bat
baz
~> set bar bar
~> default $foo $bar $baz $bat
bar
To use in your script, you can call the function using the parentheses syntax:
~> set myfoo (default $foo "default")
~> echo $myfoo
default
~> set foo "the real foo"
~> set myfoo (default $foo "default")
~> echo $myfoo
the real foo
Returning to your specific example:
set datafile (default "$Z_DATA" "$HOME/.z")

I have a Jenkins global variable in a string - how do I evaluate it?

I need to accept all kinds of global Jenkins variables as strings (basically as parameters to ansible like system - a template stored in \vars).
def proof = "\"${params.REPOSITORY_NAME}\""
echo proof
def before = "\"\${params.REPOSITORY_NAME}\""
echo before
def after = Eval.me(before)
echo after
The result is:
[Pipeline] echo
"asfd"
[Pipeline] echo
"${params.REPOSITORY_NAME}"
groovy.lang.MissingPropertyException: No such property: params for class: Script1
the first echo proves that the param value actually exists.
the second echo is the what the input actually looks like.
the third echo should have emitted asdf instead I get the exception.
Any ideas? I'm hours into this :-(
You may want to check:
groovy: Have a field name, need to set value and don't want to use switch
1st Variant
In case you have: xyz="REPOSITORY_NAME" and want the value of the parameter REPOSITORY_NAME you can simply use:
def xyz = "REPOSITORY_NAME"
echo params."$xyz" // will print the value of params.REPOSITORY_NAME
In case if your variable xyz must hold the full string including params. you could use the following solution
#NonCPS
def split(string) {
string.split(/\./)
}
def xyz = "params.REPOSITORY_NAME"
def splitString = split(xyz)
echo this."${splitString[0]}"."${splitString[1]}" // will print the value of params.REPOSITORY_NAME
2nd Variant
In case you want to specify an environment variable name as parameter you can use:
env.“${params.REPOSITORY_NAME}”
In plain groovy env[params.REPOSITORY_NAME] would work but in pipeline this one would not work inside the sandbox.
That way you first retrieve the value of REPOSITORY_NAME and than use it as key to a environment variable.
Using directly env.REPOSITORY_NAME will not be the same as it would try to use REPOSITORY_NAME itself as the key.
E.g. say you have a job named MyJob with the following script:
assert(params.MyParameter == "JOB_NAME")
echo env."${params.MyParameter}"
assert(env."${params.MyParameter}" == 'MyJob')
This will print the name of the job (MyJob) to the console assuming you did set the MyParameter parameter to JOB_NAME. Both asserts will pass.
Please don’t forget to open a node{} block first in case you want to retrieve the environment of that very node.
After trying all those solutions, found out that this works for my problem (which sounds VERY similar to the question asked - not exactly sure though):
${env[REPOSITORY_NAME]}

How to handle unexisting variables passed to a proc

I would like to create a procedure like this simple example:
proc name {args} {
foreach val $args {
puts $val
}
}
But I would like the procedure to handle variables that don't exist, something like the code shown below:
proc name {args} {
foreach val $args {
if [info exists $val] {
puts $val
}
}
}
The problem is that the code is not executed because as soon as I call the procedure with an unexisting variable it immediately stalls, prior to go into the code, saying that there is a variable that doesn't exist. Is it probable because the procedure checks argument existance before entering the body?.
I can make it work by changing args by several optional variables with predefined values, but that limits the procedure and makes it look bad.
Can I make a proc able to handle unexisting variables?
You can't pass a variable as an argument: arguments have to be values. You can pass a variable name as an argument and use that as a reference to the variable inside the procedure. Example:
proc name args {
foreach varname $args {
upvar 1 $varname var
if {[info exists var]} {
puts $var
}
}
}
(The call to upvar creates a link between the variable whose name is the value of the variable varname outside the procedure and the variable called var inside the procedure. This is one way to "pass a variable to a procedure".)
Then you can do this:
% set foo 1 ; set baz 3
% name foo bar baz
1
3
Note that if you try to invoke the procedure as
% name $bar
where bar is undefined, the interpreter tries (and fails) to evaluate it before calling the procedure. That might be what you are seeing.
Documentation:
upvar
If we look at the point where you are calling the command (procedures are commands; they're a subclass really) you'll see something like this in your code:
name $a $b $c
That's fine if all those variables exist, but if one doesn't, it will blow up even before name is called. In Tcl, $a means exactly “read the variable a and use its contents here”, unlike in some other languages where $ means “look out language, here comes a variable name!”
Because of this, we need to change the calling convention to be one that works with this:
name a b c
That's going to require the use of upvar. Like this:
proc name {args} {
foreach varName $args {
# Map the caller's named variable to the local name “v”
upvar 1 $varName v
# Now we can work with v in a simple way
if {[info exists v]} {
puts $v
}
}
}
You made a mistake here
if [info exists $val]
When info exists is used it should be checked against variable name, not the variable value.
Lets come to your actual question.
You can pass the arguments to the procedure as a key-value pair, then it is pretty simple.
proc user_info {args} {
#Converting the arguments into array
if {[catch {array set aArgs $args}]} {
puts "Please pass the arguments as key-value pair"
return 1
}
#Assume, we need to ensure these 3 arguments passed for sure.
set mandatoryArgs "-name -age -country"
foreach mArg $mandatoryArgs {
if {![info exists aArgs($mArg)]} {
puts "Missing mandatory argument '$mArg'"
return 1
}
}
}
user_info -name Dinesh

LuaJ does not supply command line arguments correctly

I tried the utility method provided by luaj to call a lua file with command line args (this one http://lua-users.org/wiki/SourceCodeFormatter)
Globals globals = JsePlatform.standardGlobals();
String script ="src/codeformatter.lua";
File f = new File(script);
LuaValue chunk = globals.loadfile(f.getCanonicalPath());
List<String> argList = Arrays.asList("--file","test.lua");
JsePlatform.luaMain(chunk, argList.toArray(new String[argList.size()]));
However i always get attempt to call nil where the code tries to access the arg table ( while i < table.getn(arg) do) - i tried other examples and they all result in the same error - luaj does not seem to set the "arg" table correctly - even a simply print arg[1] will not work.
LuaJ does not support table.getn anymore because it got removed in lua 5.1 - replace every occurances of table.getn with #varname - and init the args array with ocal args={...} at the top made it work.
Still, the code formatter does not really do what i expected it todo
There are two issues:
calls to table.getn(arg) should be replaced with #arg
the chunk's environment is not set up properly by luaj 3.0.1 so arg isn't set
However, as a workaround, you can capture the inputs using the varargs "..." syntax by adding a line at the top of codeformatter.lua such as
arg = {...}
Here is a code snippet to illustrate:
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load(
"arg = {...};" +
"print(#arg, arg[1], arg[2])");
JsePlatform.luaMain(chunk, new String[] {"--file","test.lua"});
Produces output:
2 --file test.lua

How to Add hookups to Powershell script

I have a powershell script called PostPro.ps1.I would like to provide a hookups to this script so
that if there is need one can add functionality before and after execution of PostPro.ps1 script.
Thanks in advance for your help!
Ramani
another way with parameters :
postpro.ps1:
[CmdletBinding()]
Param(
[ScriptBlock]$before,
[ScriptBlock]$after
)
if($before -ne $null){
Invoke-Command $before
}
write-host "hello"
if($after -ne $null){
Invoke-Command $after
}
then one can provide script to execute :
$b={write-host "before"}
$a={write-host 'after' }
PS>.\postpro.ps1 -before $b -after $a
before
hello
after
One way to do this would be to use modules. If you put all of your extension functions in modules in a certain folder with a certain name format, and then each module needs a runBefore and a runAfter function.
In your PostPro.ps1 script you can load the modules like this:
$modules = ls $(Join-Path $hookDir "postPro-extension-*.psm1") |
% { import-Module $_.FullName -AsCustomObject }
This will load all of the files in $hookDir that have a name that looks like postPro-extension-doSomething.psm1. Each module will be stored in a object that will give you access to each modules functions. To run the functions you can just call them on each object as show below.
You can go like this before the main part of the script
$modules | % { $_.runBefore }
and this after the main part of the script
$module | % { $_.runAfter }

Resources