2012-02-06 26 views
7

Tôi đang cố gắng để tự động tạo ra một loạt các tab trong PowerShell ISEPowerShell ISE cách tự động tạo tab mới với đóng cửa ScriptBlock?

Tôi đã bắt đầu với một chức năng như

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

tuy nhiên khi tôi chạy nó như vậy

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

hello world không được hiển thị, không giống như đoạn sau

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

Điều gì đang xảy ra ở đây và cách khắc phục sự cố?

Trả lời

1

Vùng chứa "Tab" được đặt bằng không gian chạy (hoặc powershell execution environment) trong ISE. Vì bạn đang tạo Tab mới (tức là môi trường thực thi quyền hạn) biến v không được xác định trong môi trường thực thi đó. Scriptblock được đánh giá trong môi trường thực thi mới và xuất ra giá trị của v (không có gì). Thật dễ dàng để xem các độ phân giải biến khác nhau như thế nào trong trường hợp của Test-Scriptblock từ trường hợp Start-NewTab nếu bạn cố gắng lấy biến trong scriptblock bằng cách đề cập một cách rõ ràng phạm vi mà biến sẽ được tìm thấy.

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. 

Một cách giải quyết cho vấn đề của bạn là xác định biến của bạn trong scriptblock:

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

Edit: hơn Một điều, tiêu đề của bạn đề cập đến 'đóng cửa'. Scriptblocks trong Powershell không phải là đóng cửa, tuy nhiên bạn có thể tạo ra một đóng cửa từ một scriptblock. Điều này sẽ không giúp bạn với vấn đề bạn mô tả, mặc dù.

Edit2: Một workaround:

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

Làm thế nào để trợ giúp này, nếu tôi có thể tạo ra các dữ liệu cần thiết trong scriptblock, tôi sẽ không cần phải sử dụng một biến –

+0

Tôi không chắc chắn những gì hạn chế cho vấn đề cụ thể của bạn là, tuy nhiên tôi đã cập nhật bài đăng của mình với một cách giải quyết khác. –

0

Hoặc đơn giản là tạo ra scriptblock đầu tiên.

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

Nhưng bạn phải ghi nhớ phạm vi.

+0

điều này giúp ích như thế nào? –

+0

Chức năng của anh ta là hợp lệ, tất cả những gì anh ta cần làm là vượt qua đúng đối tượng. Tất cả tôi đã cho thấy rằng nếu anh ta vượt qua các giá trị chính xác, Start-NewTab hoạt động. Nhưng tôi nghĩ rằng vấn đề thực sự ở đây là tạo ra các scriptblock ban đầu từ các biến trong phiên PowerShell hiện tại. –

+0

@ScottWeinstein Tạo khối tập lệnh đầu tiên. Chắc chắn trông giống như một vấn đề phạm vi. Biến v là null bên trong hàm khi nó đã được định nghĩa bên ngoài của kịch bản lệnh. –

0

Tôi biết đây là một câu hỏi cũ, tuy nhiên gần đây tôi đã tìm thấy một công việc mới xung quanh cho vấn đề này. Nó có thể hữu ích cho ai đó.

Sử dụng một biến môi trường:

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 } 
Các vấn đề liên quan