Can I directly import these parameters to my function with their correct types with only value with respectively?
$appparams = @{
sname = "RandomAppName" # type: string
sdata = [byte]12 # type: Byte
sgroup = $null # type: NULL
}
CASE: not sending as respectively + not correct types
$arglist = ($appparams.GetEnumerator() | Sort-Object Name | % { "$($_.Value)" }) -join ','
Invoke-Function .... $arglist -> Invoke-Function .... 12,,RandomAppName
Expected: sending only value with respectively and without any interpolation
Invoke-Function .... $arglist -> Invoke-Function .... "RandomAppName",12,$null
It looks like you're trying to pass the values of your hashtable entries as positional arguments to Invoke-Function
.
This contrasts with the usual hashtable-based splatting that uses named arguments, where the key of each entry implies the target parameter, and the value the argument.
In other words:
If Invoke-Function
declared parameters named -sname
, -sdata
, and -sgroup
with matching data types, you could use Invoke-Function @appParams
to pass your hashtable as-is (except for using @
instead of $
, for splatting).
Since the parameter binding would then based on names, the fact that a [hashtable]
(@{ ... }
) instance's entries are inherently unordered would then not a problem, and no sorting is needed.
If you get to control the definition of Invoke-Function
and it takes a known set of arguments (as opposed to an open-ended list of arguments not known in advance), it is best to make it declare parameters and use hashtable-based splatting, as described.
If you cannot modify the target command and must pass arguments positionally:
First, as mclayton points out, you need an ordered hashtable ([ordered]
) if the definition order of the entries (values) must be maintained (see below for an alternative based on sorting by keys, as you've tried).
Then you can use array-based splatting to positionally pass your hashtable's values:
# *Sample function* that simply echoes its positional arguments
# and their types.
# This serves as a *stand-in* for *your* function of that name.
function Invoke-Function { $args | ForEach-Object { $isNull = $null -eq $_; [pscustomobject] @{ Value = if ($isNull) { '$null' } else { $_ }; Type = if (-not $isNull) { $_.GetType() } } } }
# The ordered hashtable whose values are to be passed as positional arguments.
$appParams = [ordered] @{
sdata = [byte]12 # type: Byte
sgroup = $null # type: NULL
sname = "RandomAppName" # type: string
}
# Get the ordered hashtable's values, as an *array*.
[array] $appParamValues = $appParams.Values
# Pass the values as separate, positional arguments.
Invoke-Function @appParamValues
Note:
If you want to pass the array of values as an array, i.e. as a single argument, simply replace @
with $
, i.e. pass the array as-is:
# Pass the values as a *single argument* that is an *array*.
Invoke-Function $appParamValues
# *If* your function expects that single argument to be passed
# as a *named* argument to parameter -ArgumentList
Invoke-Function -ArgumentList $appParamValues
If you don't get to control the creation of the hashtable and must indeed use sorting by key, define $appParameterValues
as follows:
$appParamValues =
$appParams.Keys | Sort-Object | ForEach-Object { $appParams[$_] }
Output:
Value Type
----- ----
RandomAppName System.String
12 System.Byte
$null
As for what you tried:
($appparams.GetEnumerator() | Sort-Object Name | % { "$($_.Value)" }) -join ','
This:
stringifies all values due to use of string interpolation ("..."
)
due to -join ','
creates a single string value that is the ,
-separated list of all stringified values.
This results both in loss of the original data types and loss of separate values, and would be seen by any target command as a single string argument, as described.