Powershell: unexpected return value from function, use of $args to access parameters -
ok, have coded quite while in different, not getting powershells concept of function return?....
i new powershell, sure missing basic.
i have function below:
function plgetkeyvalue ([string] $filename, [string] $sectionname, [string] $key) { if ($psboundparameters.count -lt 2 -or $psboundparameters.count -gt 3 ) { "invalid call {0} in {1}" -f $myinvocation.mycommand.name, $myinvocation.mycommand.modulename return } # declaration $lfilecontents = "" $lsections = "" $ldatastart = "" $lstart = -1 $lend = -1 $lfoundsection = "" $lnextsection = "" $lresults = "" $lretvalue = "" # handle optional parameter. if ( $psboundparameters.count -eq 2 ) { $psboundparameters.add('key', $sectionname) $psboundparameters.remove('sectionname') $key = $sectionname $sectionname = $null } # read file in $lfilecontents = get-content $filename | select-string -pattern .* # sections. $lsections = $lfilecontents -match '\[' $lsections = $lsections -notmatch '#' # start of data. $ldatastart = $lfilecontents | select-string -pattern "^#", "^$" -notmatch ` | select-object -first 1 # have section. if ( $psboundparameters.containskey( 'sectionname' ) ) { # find section. $lfoundsection = $lsections | select-string -pattern "$lsectionname\b" # if none found out. if ( -not $lfoundsection) { return $lretvalue } # starting point key search line following # found section. $lstart = $lfoundsection[0].linenumber # loop through sections , find 1 after found one. $lnextsection = $lsections | foreach-object { # if hit it, break. if ($_.linenumber -gt $lstart) { break; } } # set ending line search end of section # or end of file. ever have. if ($lnextsection) { $lend = $lnextsection[0].linenumber } else { $lend = $lfilecontents[-1] } } else { # no section. $lstart = $ldatastart.linenumber # set ending line search end of section # or end of file. ever have. if ($lsections) { $lend = $lsections[0].linenumber } else { $lend = $lfilecontents[-1] } } # extract lines starting key. $lresults = $lfilecontents[$lstart..$lend] -match "$key\b" # got results. # split value off. return $lretvalue = $lresults[0] | select -expandproperty "line" }
the process of creating function has sparked several questions have researched , become confused with
1) documentation indicates $args should used determine arguments. never seems populate me? using version 4? alternative used $psboundparameters. advisable?
2) based on lot of reading , head scratching, have found return values functions rturn uncaptured output pipeline. can someone, please clarify uncaptured?
as example, function below return string in variable $lretvalue. currently, returning true. based on believe have uncaptured? executing captured in variable. missing?
the calling routine calling code in following form:
$filename = "s:\ps\home\globalconfig\jobs.cfg" $key = "help" $section = "section" $r = plgetkeyvalue $filename $key write-host "r is: $r"
the output shows follows:
ps c:> s:\ps\home\job\test.ps1 r is: true
any assistance appreciated.
terminology note: arbitrarily, i'll distinguish between parameters , arguments below:
- parameters placeholders defined part of function declaration,
- distinct arguments values bound placeholders in given invocation.
conceptual information:
1) documentation indicates $args should used determine arguments.
$args
fallback mechanism examining unbound arguments in non-advanced (non-cmdlet) functions.
$args
populated:
only if function not advanced function (a function marked advanced function presence of
param(...)
parameter-declaration statement - opposed declaring parameters insidefunction somefunc(...)
) - if decorated[cmdletbinding()]
attribute).even contains unbound arguments (those not mapped declared parameters).
in other words: if declare function without parameters @ $args
contain all arguments passed.
conversely, in advanced function there mustn't unbound arguments, , invoking advanced function arguments cannot bound parameters fails (generates error).
since defining advanced functions advisable in general, because best integrated powershell infrastructure whole, it's best make without $args
altogether.
instead, use combination of multiple parameter sets and/or array parameters cover possible valid input argument scenarios.
$psboundarguments
contains arguments bound declared parameters, , not needed, because variable names corresponding parameters names (e.g., $sectionname
) can used directly. (it has specialized uses, such passing bound parameters on cmdlet/function via splat @psboundarguments
).
2) based on lot of reading , head scratching, have found return values functions return uncaptured output pipeline. can someone, please clarify "uncaptured"?
generally, powershell statement or expression generates output sent success stream (loosely comparable stdout
in unix shells) by default, unless output captured (e.g., assigning variable) or redirected (e.g., sending output file).
thus, in reversal of how programming languages behave, must take action if not want statement produce output.
if you're not interested in statement's output (as opposed capturing / redirecting later use), can redirect $null
(the equivalent of /dev/null
), pipe cmdlet out-null
, or assign dummy variable $null
($null = ...
).
therefore, in manner of speaking, can call output is sent success stream uncaptured.
that, unrelated return
statement:
the return
statement not work same way in other languages; primary purpose in powershell control-flow mechanism - exit function or script block - rather mechanism output data (even though can also used that: argument, another way send output success stream).
diagnosing specific problem:
there many ways in function made better powershell citizen[1] , immediate problem this:
$psboundparameters.remove('sectionname')
returns boolean value sent output stream, because neither suppress, capture nor redirect it. in case, since $sectionname
parameter is bound, have entry in $psboundparameters
, $psboundparameters.remove('sectionname')
returns $true
.
to suppress unwanted output, use this:
$null = $psboundparameters.remove('sectionname')
generally speaking, unless know statement not generate output, it's better safe , prepend $null =
(or use equivalent mechanism suppress output).
especially direct method calls on objects, it's not clear whether value - turns output (is sent success stream) - returned.
[1] following topics provide further information:
- use of parameters, including how inspect them help -full / -detailed ...
:
help about_parameters
- defining simple functions , parameters:
help about_functions
,
can progress advanced functions:
help about_functions_advanced
, parameter definitions:
help about_functions_advanced_parameters
Comments
Post a Comment