Last active
March 23, 2017 17:28
-
-
Save nohwnd/0f615f897b1f510beb08ce0cefe48342 to your computer and use it in GitHub Desktop.
Invoke code in caller scope by manipulating the session state, like in Pester
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Set-ScriptBlockScope | |
{ | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory = $true)] | |
[scriptblock] | |
$ScriptBlock, | |
[Parameter(Mandatory = $true, ParameterSetName = 'FromSessionState')] | |
[System.Management.Automation.SessionState] | |
$SessionState) | |
$flags = [System.Reflection.BindingFlags]'Instance,NonPublic' | |
$SessionStateInternal = $SessionState.GetType().GetProperty('Internal', $flags).GetValue($SessionState, $null) | |
$SessionStateInternal | Add-Member -Value "caller" -MemberType NoteProperty -Name "ScopeName" -Force | |
[scriptblock].GetProperty('SessionStateInternal', $flags).SetValue($ScriptBlock, $SessionStateInternal, $null) | |
} | |
function Get-ScriptBlockScope | |
{ | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory = $true)] | |
[scriptblock] | |
$ScriptBlock) | |
$flags = [System.Reflection.BindingFlags]'Instance,NonPublic' | |
[scriptblock].GetProperty('SessionStateInternal', $flags).GetValue($ScriptBlock) | select ScopeName | |
} | |
function InCallerScope { | |
[cmdletbinding()] | |
param($sb) | |
Set-ScriptBlockScope -ScriptBlock $sb -SessionState ( $PSCmdlet.SessionState ) | |
&$sb | |
} | |
remove-item 'function:\mine' -ea 0 | |
remove-item 'alias:\gg' -ea 0 | |
# make one extra scope so we can see that the alias is not defined in script scope | |
&{ | |
function ext { 'external' } | |
$sb = { | |
function mine () { "just define it" } | |
set-alias -Name gg -Value ext -Scope 2 | |
} | |
InCallerScope $sb | |
Get-ScriptBlockScope -ScriptBlock $sb | |
mine # <- not defined, but if the code executed directly in the caller scope it would be executed | |
gg | |
(Get-Alias gg -Scope 0 | Out-String) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment