2016-09-28 5 views
1

Используя пример Microsoft Technet здесь и вставили нижеНевозможно присвоить значение переменной из Powershell формы

https://technet.microsoft.com/en-us/library/ff730941.aspx?f=255&MSPPError=-2147217396

Я не могу получить его на самом деле назначить пользовательский ввод переменной $x

Я попытался удалить пустоту из этой строки в конце [void] $objForm.ShowDialog(), но, как представляется, всегда возвращает Отменить текст

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "Data Entry Form" 
$objForm.Size = New-Object System.Drawing.Size(300,200) 
$objForm.StartPosition = "CenterScreen" 

$objForm.KeyPreview = $True 
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
    {$x=$objTextBox.Text;$objForm.Close()}}) 
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
    {$objForm.Close()}}) 

$OKButton = New-Object System.Windows.Forms.Button 
$OKButton.Location = New-Object System.Drawing.Size(75,120) 
$OKButton.Size = New-Object System.Drawing.Size(75,23) 
$OKButton.Text = "OK" 
$OKButton.Add_Click({$x=$objTextBox.Text;$objForm.Close()}) 
$objForm.Controls.Add($OKButton) 

$CancelButton = New-Object System.Windows.Forms.Button 
$CancelButton.Location = New-Object System.Drawing.Size(150,120) 
$CancelButton.Size = New-Object System.Drawing.Size(75,23) 
$CancelButton.Text = "Cancel" 
$CancelButton.Add_Click({$objForm.Close()}) 
$objForm.Controls.Add($CancelButton) 

$objLabel = New-Object System.Windows.Forms.Label 
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Please enter the information in the space below:" 
$objForm.Controls.Add($objLabel) 

$objTextBox = New-Object System.Windows.Forms.TextBox 
$objTextBox.Location = New-Object System.Drawing.Size(10,40) 
$objTextBox.Size = New-Object System.Drawing.Size(260,20) 
$objForm.Controls.Add($objTextBox) 

$objForm.Topmost = $True 

$objForm.Add_Shown({$objForm.Activate()}) 
[void] $objForm.ShowDialog() 

$x 
+0

Я только что понял, что код на этой странице очень похож и работает, но я не понимаю, почему первый пример Technet этого не делает. Возможно, потому что это PS 1.0? https://msdn.microsoft.com/en-us/powershell/scripting/getting-started/cookbooks/creating-a-custom-input-box – benji1304

+0

Выполняет ли изменение '$ x =' в обработчике события '$ global: x = 'исправлять вещи? –

+0

Я попробую. Дальнейшее чтение указывает, что это обычная проблема и ее причина, потому что исходный код устарел и не работает 3.0. https://blogs.technet.microsoft.com/heyscriptingguy/2014/08/02/weekend-scripter-fixing-powershell-gui-examples/ – benji1304

ответ

0

Этот код отлично работал в PowerShell 1 и 2, но не работал в PowerShell 3. PowerShell 3 предлагал небольшой набор улучшений синтаксиса и обычных новых командлетов, но на менее заметной заметке он был переписан поверх Dynamic Language Runtime, естественный выбор для языка сценариев.

Переход к DLR изменил scoping rules таким образом, что я не думаю, что он хорошо документирован и по сей день. В частности, в блоке сценария (например, тот, который используется для создания делегата) присваивание переменной создает новую переменную в области блока. Это имеет смысл с точки зрения модульности, но не так очевидно на языке сценариев. В частности, рассмотрим следующие:

$x = 2 
&{ 
    Write-Host $x; 
    $x = 3; Write-Host $x; 
    Remove-Variable "x"; Write-Host $x 
    $x = 3; 
} 
Write-Host $x 

Печатается:

2 
3 
2 
2 

В блоке, x принимает значение от родительской области, но когда мы относим его, мы на самом деле создает новый переменная в частной области. Когда мы удаляем эту переменную, любые ссылки на x снова получаются из родительской области. Назначение x не влияет на значение в родительской области, как видно из Write-Host вне блока.

Это объясняет, почему назначение переменной в делегате «не работает»: вы фактически назначаете новую переменную внутри делегата, значение которой теряется, когда делегат заканчивается. Для назначения переменной в родительской области необходим явный определитель ($script:x или $global:x).

Смежные вопросы