Skip to content

Instantly share code, notes, and snippets.

@nohwnd
Last active March 23, 2017 17:28
Show Gist options
  • Save nohwnd/0f615f897b1f510beb08ce0cefe48342 to your computer and use it in GitHub Desktop.
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
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