2012-02-06 9 views
7

sto cercando di automatizzare la creazione di un gruppo di schede in PowerShell ISEPowerShell ISE come automatizzare la creazione di nuove schede con chiusure ScriptBlock?

ho iniziato con una funzione come

function Start-NewTab($name, [ScriptBlock]$scriptBlock) 
{ 
    $tab = $psISE.PowerShellTabs.Add() 
    $tab.DisplayName = $name 
    sleep 2 
    $tab.Invoke($scriptBlock) 
} 

tuttavia quando l'eseguo in questo modo

$v = "hello world" 
Start-NewTab "Test" { $v } 

hello world non è mostrato, a differenza del seguente fraction

function Test-ScriptBlock([ScriptBlock]$sb) { & $sb } 
Test-ScriptBlock { $v } 

Cosa sta succedendo qui e come lo risolvo?

risposta

1

Un contenitore "Tab" è equiparato a uno spazio di esecuzione (o powershell execution environment) nell'ISE. Poiché si sta creando una nuova scheda (vale a dire un ambiente di esecuzione powershell), la variabile v non è definita in tale ambiente di esecuzione. Lo scriptblock viene valutato nel nuovo ambiente di esecuzione e restituisce il valore di v (niente).

È facile vedere come le risoluzioni delle variabili differiscono nel caso di Test-Scriptblock dal caso di Start-NewTab se si tenta di ottenere la variabile nel scriptblock citando esplicitamente l'ambito in cui la variabile deve essere trovata.

PS>Test-ScriptBlock { get-variable v -scope 0} 
Get-Variable : Cannot find a variable with name 'v'. 
PS>Test-ScriptBlock { get-variable v -scope 1} 
Get-Variable : Cannot find a variable with name 'v'. 
PS>Test-ScriptBlock { get-variable v -scope 2} # Variable found in grandparent scope (global in the same execution environment) 
Name       Value                               
----       -----                               
v        hello world 

PS>Start-NewTab "Test" { get-variable v -scope 0 } # global scope of new execution environment 
Get-Variable : Cannot find a variable with name 'v'. 
PS>Start-NewTab "Test" { get-variable v -scope 1 } # proof that scope 0 = global scope 
Get-Variable : The scope number '1' exceeds the number of active scopes. 

Una soluzione per il vostro problema è quello di definire la variabile nel scriptblock:

Start-NewTab "Test" { $v = "hello world";$v } 

Edit: più una cosa, il titolo parla di 'chiusura'. Scriptblocks in Powershell non sono chiusure, tuttavia è possibile creare una chiusura da un blocco di script. Questo non ti aiuterà con il problema che descrivi, però.

Edit2: Un'altra soluzione:

$v = "hello world" 
Invoke-Expression "`$script = { '$v' }" 
Start-NewTab "test" $script 
+0

Come funziona questo aiuto, se ho potuto creare i dati necessari nel scriptblock, non avrei bisogno di usare una variabile –

+0

io non sono sicuro di quello che la le restrizioni per il tuo problema particolare sono, tuttavia, ho aggiornato il mio post con un'altra soluzione alternativa. –

0

O semplicemente creare lo scriptblock prima.

$v={"Hello world"}                          
start-newtab "test" $v 

Ma bisogna tenere a mente l'ambito.

+0

come aiuta? –

+0

La sua funzione è valida, tutto ciò che deve fare è passare l'oggetto giusto. Tutto quello che stavo mostrando è che se passa i valori corretti, Start-NewTab funziona. Ma penso che il vero problema qui sia la creazione dello scriptblock inizialmente dalle variabili nella sessione corrente di PowerShell. –

+0

@ScottWeinstein La creazione del blocco di script prima funziona. Sicuramente sembra un problema di ambito. La variabile v è nullo all'interno della funzione quando è stata definita al di fuori dello scriptblock. –

0

So che questa è una vecchia domanda, tuttavia ho trovato di recente una soluzione per questo problema. Potrebbe essere utile a qualcuno.

Usa una variabile di ambiente:

function Start-NewTab($name, [ScriptBlock]$scriptBlock) 
{ 
    $tab = $psISE.PowerShellTabs.Add() 
    $tab.DisplayName = $name 
    sleep 2 
    $tab.Invoke($scriptBlock) 
} 

$env:v = "hello world" 
Start-NewTab "Test" { $env:v } 
Problemi correlati