PowerShell Close Capture Function

It seems that PowerShell locks don't capture function definitions:

PS C:\> function x() { Write-Host 'original x' } PS C:\> function x-caller-generator() { return { Write-host 'Calling x!'; x }.GetNewClosure() } PS C:\> $y = x-caller-generator PS C:\> & $y Calling x! original x PS C:\> function x() { Write-Host 'new x' } PS C:\> & $y Calling x! new x 

Is there a way to capture a function definition?

What I'm actually experiencing is that I create a closure, but when my closure is executed, the function somehow goes beyond. (This kind of weirdness makes the psake module for creating scripts.) Something like this:

 PS C:\> function closure-maker () { >> function x() { Write-Host 'x!' } >> >> return { Write-host 'Calling x'; x }.GetNewClosure() >> } >> PS C:\> $y = closure-maker PS C:\> & $y Calling x The term 'x' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:3 char:39 + return { Write-host 'Calling x'; x <<<< }.GetNewClosure() + CategoryInfo : ObjectNotFound: (x:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException 

Note. Using PowerShell 2.0, but is interested in 3.0 answers if there is anything new.

+4
source share
2 answers

Ok, I found something that works for simple functions, at least. We can use Get-Item to get an object describing the function, and then pull out the original script. Like this:

 function x-caller-generator() { $xFunc = [ScriptBlock]::Create((Get-Item function:x).Definition) return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() } 

If a function is never overridden (for example, in my example, when my function is not available), we can avoid removing the definition and simply use the function object directly:

 function closure-maker () { function x() { Write-Host 'x!' } $xFunc = Get-Item function:x return { Write-host 'Calling x'; & $xFunc }.GetNewClosure() } 

This second method will not work if the function is overridden (at least in the same area as the original function) before closing. The object is apparently dynamic; It keeps track of the current definition.

I seriously doubt that this will work with a function that refers to other user-defined functions that may also not be available, but my use case did not require this.

Output Example:

Creating a script block

 PS C:\> function x() { Write-Host 'original x' } PS C:\> function x-caller-generator() { $xFunc = [ScriptBlock]::Create((Get-Item function:x).Definition); return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() } PS C:\> $y = x-caller-generator PS C:\> & $y Calling x! original x PS C:\> function x() { Write-Host 'new x' } PS C:\> & $y Calling x! original x 

Functional Object Use

 PS C:\> function closure-maker () { >> function x() { Write-Host 'x!' } >> >> $xFunc = Get-Item function:x >> return { Write-host 'Calling x'; & $xFunc }.GetNewClosure() >> } >> PS C:\> $y = closure-maker PS C:\> & $y Calling x x! 

Trying to use an object with the first example does not work :

 PS C:\> function x() { Write-Host 'original x' } PS C:\> function x-caller-generator() { $xFunc = Get-Item function:x; return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() } PS C:\> $y = x-caller-generator PS C:\> & $y Calling x! original x PS C:\> function x() { Write-Host 'new x' } PS C:\> & $y Calling x! new x 
+2
source

A small correction will allow you to use the first example:

 clear function x() { Write-Host 'original x' } function x-caller-generator() { $xFunc = $function:x; # instead of Get-Item return { Write-host 'Calling x!'; & $xFunc }.GetNewClosure() } $y = x-caller-generator & $y function x() { Write-Host 'new x' } & $y 

Output:

 Calling x! original x Calling x! original x 

PowerShell has too many similar looks that actually behave differently. You can get the function object using the $ function prefix. You might think that it works the same as Get-Item, but it doesnโ€™t ...

0
source

Source: https://habr.com/ru/post/1482678/


All Articles