Shane Lu
Shane Lu

Reputation: 1104

How to get the parameter name in a powershell function

I would like to implement a function to output some debugging information. I want the function, namely "Write-Foo", to work in the following way:

Write-Foo $SomeThing
# the output will be "SomeThing: (the value of Something)"

Is it possible to implement this function? I don't know how to get the name of the parameter of the function.

Thanks

Upvotes: 0

Views: 719

Answers (5)

mjolinor
mjolinor

Reputation: 68303

Another possibility (this assumes what you want to display is the name of the variable that was passed as an argument, not the name of the parameter it was passed to).

function Write-Foo($varName)
{
  $var = 
  ($MyInvocation.line -replace '\s*write-foo\s*\$','').trim()

  '{0}: {1}' -f $var,$varName
}

$something =  'Hello'

write-foo $something
something: Hello

It's easier if you pass the name without the $

function Write-Foo($varName)
{
  $var = Get-Variable $varName 
  '{0}: {1}' -f $var.Name,$var.Value 
}

$something =  'Hello'

write-foo something
something: Hello

I'll also second @Ansgar Weicher's suggestion of writing that to the Debug stream so you don't pollute the pipeline with it.

Upvotes: 1

Duncan
Duncan

Reputation: 95692

You can access the function's parameters through $MyInvocation.BoundParameters, so this may be what you want:

function Write-Foo($varName) {
    foreach ($key in $MyInvocation.BoundParameters.Keys) {
        Write-Verbose ("{0}: {1}" -f ($key, $MyInvocation.BoundParameters[$key])) -Verbose
    }
}
Write-Foo "Hello"

and the output looks like this:

VERBOSE: varName: Hello

If you want to be able to control when the debug information appears you can turn this into a cmdlet:

function Write-Foo {
[CmdletBinding()]
Param ($varName)
    foreach ($key in $MyInvocation.BoundParameters.Keys) {
        Write-Verbose ("{0}: {1}" -f ($key, $MyInvocation.BoundParameters[$key]))
    }
}
Write-Foo "Hello"
Write-Foo "This will debug" -Verbose

and the first call produces no output while the second will show you:

VERBOSE: Verbose: True
VERBOSE: varName: This will debug

Naturally you can choose how exactly to output the debug information. Probably either Write-Debug (which usually prompts for each line of output) or Write-Verbose (which is usually suppressed) is appropriate here.

Upvotes: 1

Raf
Raf

Reputation: 10107

Another take:

function Write-Foo($varName)
{
    $v = Get-Variable $varName
    Write-Host ($v.Name + ": " + $v.Value)
}

Result:

PS C:\> $Something = "nothing"            
PS C:\> Write-Foo SomeThing               
Something: nothing

Upvotes: 2

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200323

You could define a function like this:

function Write-Foo($msg) {
  Write-Host ("SomeThing: {0}" -f $msg)
}

or (if you want the output to be available for further processing) like this:

function Write-Foo($msg) {
  "SomeThing: {0}" -f $msg
}

However, since you said you want to output debugging information, using the already existing Write-Debug cmdlet might be a better approach:

PS C:\> Write-Debug 'foo'
PS C:\> $DebugPreference
SilentlyContinue
PS C:\> $DebugPreference = 'Continue'
PS C:\> Write-Debug 'foo'
DEBUG: foo

Upvotes: 1

dan-gph
dan-gph

Reputation: 16909

This is close to what you want:

function Write-Foo($varName)
{
    $varVal = $ExecutionContext.InvokeCommand.ExpandString("`$variable:$varName")
    Write-Host "$($varName): $varVal"
}

Trying it out:

PS> $SomeThing = 'hello'
PS> Write-Foo SomeThing
SomeThing: hello

Upvotes: 2

Related Questions