Hi,
I want to be able to capture $_ from another scope, something like this:
function foo
{
$something = ((get-variable -name "_" -scope 1).value).exception.message
write-host $something
}
how would I do this properly?
I want to use it in these kind of situations:
foo #write-host prints empty line
try{
throw
}catch{
foo #write-host prints $_.exception.message from this catch block
}
the goal is to avoid assigning $_ to some other variable or passing it as a parameter every time I want to call “foo” in a catch block.
I’ve also tried using $Error[0], however it being global produces unwanted results when calling foo not in a catch block.
I have also tried using $ExecutionContext.SessionState.PSVariable.Get(“_”) in “foo”, but since I don’t know how to refer to specific scope or how it works in general I was not able to produce desired results when testing.
You should use a parameter in your “foo” function to collect the error message. There is also -ErrorVariable, but with what you posted you don’t want to use anything globally, you want to pass what you need into the function:
function Get-Error {
param (
$Error
)
"Do something with error: {0}" -f $_.Exception.Message
}
try {
Get-ChildItem -Path C:\ -Reccccurse -ErrorAction Stop
}
catch {
Get-Error -Error $_
}
I agree with Rob that passing it as an argument is much better in this situation, but to answer your question directly you could do this:
function foo {
(Get-PSCallstack)[1].GetFrameVariables().'_'.Value
}
This gets a CallStackFrame for the current and previous steps in the execution stack and retrieves the first one that isn’t the current frame. It then gets the automatic variables for that frame using the GetFrameVariables method, and retrieves the value for $_.
There aren’t a whole lot of good reasons to do this though, it’s significantly more readable to pass the variable you want as a parameter.
Thanks for comments, I’ll stick with the parameter.