Private/GetWinPSInCore.ps1

function GetWinPSInCore {
    [CmdletBinding()]
    [Alias('shim')]
    Param (
        [Parameter(
            Mandatory=$True,
            Position=0
        )]
        [Alias("sb")]
        [scriptblock]$ScriptBlock,

        [Parameter(Mandatory=$False)]
        [switch]$MirrorCurrentEnv = $True,

        [Parameter(Mandatory=$False)]
        [switch]$NoWinRM
    )

    if ($PSVersionTable.PSEdition -ne "Core" -or $PSVersionTable.Platform -ne "Win32NT") {
        Write-Error "The '$($MyInvocation.MyCommand.Name)' function is only meant to be used in PowerShell Core on Windows! Halting!"
        $global:FunctionResult = "1"
        return
    }

    if ($MirrorCurrentEnv) {
        [System.Collections.ArrayList]$SetEnvStringArray = @()

        $VariablesNotToForward = @()

        $Variables = Get-Variable
        if ($PSBoundParameters['VariablesToForward'] -and $VariablesToForward -notcontains '*') {
            $Variables = foreach ($VarObj in $Variables) {
                if ($VariablesToForward -contains $VarObj.Name) {
                    $VarObj
                }
            }
        }
        $SetVarsPrep = foreach ($VarObj in $Variables) {
            if ($VariablesNotToForward -notcontains $VarObj.Name) {
                try {
                    $VarValueAsJSON = $VarObj.Value | ConvertTo-Json -Compress
                }
                catch {
                    #Write-Warning "Unable to pass the variable '$($VarObj.Name)'..."
                }

                if ($VarValueAsJSON) {
                    if ([char[]]$VarObj.Name -contains '(' -or [char[]]$VarObj.Name -contains ' ') {
                        $VarStringArr = @(
                            'try {'
                            $(' ${' + $VarObj.Name + '}' + ' = ' + 'ConvertFrom-Json ' + "@'`n$VarValueAsJSON`n'@")
                            '}'
                            'catch {'
                            " Write-Verbose 'Unable to forward variable $($VarObj.Name)'"
                            '}'
                        )
                    }
                    else {
                        $VarStringArr = @(
                            'try {'
                            $(' $' + $VarObj.Name + ' = ' + 'ConvertFrom-Json ' + "@'`n$VarValueAsJSON`n'@")
                            '}'
                            'catch {'
                            " Write-Verbose 'Unable to forward variable $($VarObj.Name)'"
                            '}'
                        )
                    }
                    $VarStringArr -join "`n"
                }
            }
        }
        $SetVarsString = $SetVarsPrep -join "`n"

        $null = $SetEnvStringArray.Add($SetVarsString)

        # Set Environment Variables
        $EnvVariables = Get-ChildItem Env:\
        if ($PSBoundParameters['EnvironmentVariablesToForward'] -and $EnvironmentVariablesToForward -notcontains '*') {
            $EnvVariables = foreach ($VarObj in $EnvVariables) {
                if ($EnvironmentVariablesToForward -contains $VarObj.Name) {
                    $VarObj
                }
            }
        }
        $SetEnvVarsPrep = foreach ($VarObj in $EnvVariables) {
            if ([char[]]$VarObj.Name -contains '(' -or [char[]]$VarObj.Name -contains ' ') {
                $EnvStringArr = @(
                    'try {'
                    $(' ${env:' + $VarObj.Name + '} = ' + "@'`n$($VarObj.Value)`n'@")
                    '}'
                    'catch {'
                    " Write-Verbose 'Unable to forward environment variable $($VarObj.Name)'"
                    '}'
                )
            }
            else {
                $EnvStringArr = @(
                    'try {'
                    $(' $env:' + $VarObj.Name + ' = ' + "@'`n$($VarObj.Value)`n'@")
                    '}'
                    'catch {'
                    " Write-Verbose 'Unable to forward environment variable $($VarObj.Name)'"
                    '}'
                )
            }
            $EnvStringArr -join "`n"
        }
        $SetEnvVarsString = $SetEnvVarsPrep -join "`n"

        $null = $SetEnvStringArray.Add($SetEnvVarsString)

        # Set Modules
        $Modules = Get-Module
        if ($PSBoundParameters['ModulesToForward'] -and $ModulesToForward -notcontains '*') {
            $Modules = foreach ($ModObj in $Modules) {
                if ($ModulesToForward -contains $ModObj.Name) {
                    $ModObj
                }
            }
        }

        $ModulesNotToForward = @('MiniLab')

        $SetModulesPrep = foreach ($ModObj in $Modules) {
            if ($ModulesNotToForward -notcontains $ModObj.Name) {
                $ModuleManifestFullPath = $(Get-ChildItem -Path $ModObj.ModuleBase -Recurse -File | Where-Object {
                    $_.Name -eq "$($ModObj.Name).psd1"
                }).FullName

                $ModStringArray = @(
                    '$tempfile = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName())'
                    "if (![bool]('$($ModObj.Name)' -match '\.WinModule')) {"
                    ' try {'
                    " Import-Module '$($ModObj.Name)' -ErrorAction Stop -WarningAction SilentlyContinue 2>`$tempfile"
                    ' }'
                    ' catch {'
                    ' try {'
                    " Import-Module '$ModuleManifestFullPath' -ErrorAction Stop -WarningAction SilentlyContinue 2>`$tempfile"
                    ' }'
                    ' catch {'
                    " Write-Verbose 'Unable to Import-Module $($ModObj.Name)'"
                    ' }'
                    ' }'
                    '}'
                    'if (Test-Path $tempfile) {'
                    ' Remove-Item $tempfile -Force'
                    '}'
                )
                $ModStringArray -join "`n"
            }
        }
        $SetModulesString = $SetModulesPrep -join "`n"

        $null = $SetEnvStringArray.Add($SetModulesString)
    
        # Set Functions
        $Functions = Get-ChildItem Function:\ | Where-Object {![System.String]::IsNullOrWhiteSpace($_.Name)}
        if ($PSBoundParameters['FunctionsToForward'] -and $FunctionsToForward -notcontains '*') {
            $Functions = foreach ($FuncObj in $Functions) {
                if ($FunctionsToForward -contains $FuncObj.Name) {
                    $FuncObj
                }
            }
        }
        $SetFunctionsPrep = foreach ($FuncObj in $Functions) {
            $FunctionText = Invoke-Expression $('@(${Function:' + $FuncObj.Name + '}.Ast.Extent.Text)')
            if ($($FunctionText -split "`n").Count -gt 1) {
                if ($($FunctionText -split "`n")[0] -match "^function ") {
                    if ($($FunctionText -split "`n") -match "^'@") {
                        Write-Warning "Unable to forward function $($FuncObj.Name) due to heredoc string: '@"
                    }
                    else {
                        'Invoke-Expression ' + "@'`n$FunctionText`n'@"
                    }
                }
            }
            elseif ($($FunctionText -split "`n").Count -eq 1) {
                if ($FunctionText -match "^function ") {
                    'Invoke-Expression ' + "@'`n$FunctionText`n'@"
                }
            }
        }
        $SetFunctionsString = $SetFunctionsPrep -join "`n"

        $null = $SetEnvStringArray.Add($SetFunctionsString)
    }

    # Make sure we have Windows PowerShell PSModule Paths
    $PSCorePSModulePath = $env:PSModulePath
    [System.Collections.Arraylist][array]$PSCorePSModulePathArray = $env:PSModulePath -split ';'
    $WinPSPSModulePaths = @(
        'C:\Program Files\WindowsPowerShell\Modules'
        "$HOME\Documents\WindowsPowerShell\Modules"
        'C:\Windows\System32\WindowsPowerShell\v1.0\Modules'
        'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\Modules'
    )
    foreach ($ModPath in $WinPSPSModulePaths) {
        if ($PSCorePSModulePathArray -notcontains $ModPath) {
            $null = $PSCorePSModulePathArray.Add($ModPath)
        }
    }
    $FinalModPathString = $PSCorePSModulePathArray -join ';'

    # Create Initialization Scripts as needed...
    $InitSBAsStringA = "`$env:PSModulePath = '$FinalModPathString'`n"
    
    if ($SetEnvStringArray.Count -gt 0) {
        # Writing $SetEnvStringArray to a file helps us avoid the byte limit associated with the
        # -args parameter of powershell.exe.
        # See: http://systemcentersynergy.com/max-script-block-size-when-passing-to-powershell-exe-or-invoke-command/
        $SetEnvStringArrayPath = "$HOME\SetEnvStringArray.xml"
        $SetEnvStringArray | Export-CliXml -Path $SetEnvStringArrayPath -Force

        $InitSBAsStringB = @(
            "`$args = Import-CliXml '$SetEnvStringArrayPath'"
            ''
            '$args | foreach {'
            ' if (![string]::IsNullOrWhiteSpace($_)) {'
            ' Invoke-Expression $_'
            ' }'
            '}'
            ''    
        )
    }

    if ($InitSBAsStringB) {
        # NOTE: $InitSBAsStringB coming before $InitSBAsStringA is important regarding $env:PSModulePath
        $FinalSBAsString = $InitSBAsStringB + $InitSBAsStringA + $ScriptBlock.ToString()
    }
    else {
        $FinalSBAsString = $InitSBAsStringA + $ScriptBlock.ToString()
    }

    try {
        $FinalSB = [scriptblock]::Create($($FinalSBAsString -join "`n"))
    }
    catch {
        Write-Error "Problem creating scriptblock `$FinalSB! Halting!"
        $global:FunctionResult = "1"
        return
    }
    

    # Output
    if ($NoWinRM) {
        powershell.exe -NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -Command $FinalSB
    }
    else {
        # Check to see if there's a PSSession open from the WindowsCompatibility Module
        <#
        if (!$global:WinPSSession) {
            $CurrentUser = $($(whoami) -split '\\')[-1]
            if ([bool]$(Get-PSSession -Name "win-$CurrentUser" -ErrorAction SilentlyContinue)) {
                $global:WinPSSession = Get-PSSession -Name "win-$CurrentUser"
            }
        }
        #>


        $WinPSSessionName = NewUniqueString -PossibleNewUniqueString "WinPSSession" -ArrayOfStrings $(Get-PSSession).Name
        $NewPSSessionSplatParams = @{
            ConfigurationName   = 'Microsoft.PowerShell'
            Name                = $WinPSSessionName
            EnableNetworkAccess = $True
        }
        $WinPSSession = New-PSSession @NewPSSessionSplatParams
        
        if (!$WinPSSession) {
            Write-Error "There was a problem creating the New-PSSession named 'WinPSSession'! Halting!"
            $global:FunctionResult = "1"
            return
        }
        else {
            Write-Host "A new PSSession called 'WinPSSession' has been created along with a Global Variable referencing it called `$global:WinPSSession." -ForegroundColor Green
        }
        Invoke-Command -Session $global:WinPSSession -ScriptBlock $FinalSB -HideComputerName
    }

    # Cleanup
    if ($SetEnvStringArrayPath) {
        if (Test-Path $SetEnvStringArrayPath) {
            #Remove-Item $SetEnvStringArrayPath -Force
        }
    }

    $WinPSSession | Remove-PSSession
}