1

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
mklement0
  • 382,024
  • 64
  • 607
  • 775
Ichigo Kurosaki
  • 135
  • 1
  • 6
  • 2
    [about splatting](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_splatting): `Invoke-Function @appparams` – iRon Aug 15 '23 at 18:03
  • 2
    As an aside, if "as respectively" means "in the same order", you can use an ```OrderedDictionary``` instead of a ```hashtable``` - e.g. ```$appparams = [ordered] @{ ... }``` - which will maintain the order of entries during enumeration. I think you probably want to look at splatting per @iRon's comment to solve your actual problem though... – mclayton Aug 15 '23 at 18:08
  • No, Invoke-Function :S because its my custom function, I edited my post to avoid confusion. @iRon – Ichigo Kurosaki Aug 15 '23 at 21:37

1 Answers1

1

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • By the way, I think [ordered] for PSv3+, I wonder if there is an alternative solution for powershell v2? – Ichigo Kurosaki Aug 15 '23 at 21:50
  • @IchigoKurosaki, in v2 you can use the .NET type underlying `[ordered]` explicitly (which is more cumbersome, because there's no literal syntax): [`System.Collections.Specialized.OrderedDictionary`](https://learn.microsoft.com/en-US/dotnet/api/System.Collections.Specialized.OrderedDictionary) – mklement0 Aug 15 '23 at 21:53
  • 1
    @IchigoKurosaki, "*I think it was a great question for me*", it would be better if it was a great question for others too. For that, I would expect some background of this foreign "custom function". It does have the PowerShell Verb-Noun naming, yet it apparently can't be threathed as such. What is this "custom fuction?" What is the use case. Why can't you use the normal [splatting](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_splatting)? With this infomation you might even receive more complete answers or stable solutions than ***you*** imaging. – iRon Aug 16 '23 at 05:46