【问题标题】:Creating a list box in PowerShell在 PowerShell 中创建列表框
【发布时间】:2015-04-17 18:52:17
【问题描述】:

我正在尝试编写一个包含列表框的 PowerShell 脚本。为了确保我对所需的概念有所了解,我在 TechNet 上查找了教程并尝试复制提供的代码。

http://technet.microsoft.com/en-us/library/ff730949.aspx

如果我正确地遵循演练和脚本,脚本似乎旨在显示一个对话框,然后将所选项目输出到 CLI。我复制了对话框,但无法将选择写入 CLI。我什至修改了最后一行,显式调用 Write-Output 来显示 $x 的值。

除了实际为 $x 写出任何值外,该脚本的所有内容似乎都按预期工作。由于echo "$x" 可能是所有代码中最简单的一行,我只能假设问题实际上是把数据写入 到 $x。

下面是从我的 PowerShell ISE 窗口中剪切和粘贴的内容,而这又是从上述 TechNet 文章中剪切和粘贴的内容:

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

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

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
    {$x=$objListBox.SelectedItem;$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=$objListBox.SelectedItem;$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 select a computer:"
$objForm.Controls.Add($objLabel) 

$objListBox = New-Object System.Windows.Forms.ListBox 
$objListBox.Location = New-Object System.Drawing.Size(10,40) 
$objListBox.Size = New-Object System.Drawing.Size(260,20) 
$objListBox.Height = 80

[void] $objListBox.Items.Add("atl-dc-001")
[void] $objListBox.Items.Add("atl-dc-002")
[void] $objListBox.Items.Add("atl-dc-003")
[void] $objListBox.Items.Add("atl-dc-004")
[void] $objListBox.Items.Add("atl-dc-005")
[void] $objListBox.Items.Add("atl-dc-006")
[void] $objListBox.Items.Add("atl-dc-007")

$objForm.Controls.Add($objListBox) 

$objForm.Topmost = $True

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

echo "$x"

当上面没有按预期工作时,我决定按照教程一步一步地自己重新编写脚本。我对其进行了一些修改,以更好地适应我的组织偏好并在此过程中添加注释。但是,现在连对话框本身都坏了。

# Load Windows Forms & Drawing classes.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# Create base form.
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select a Computer"
$objForm.Size = New-Object System.Drawing.Size(300,200)
$objForm.StartPosition = "CenterScreen"

# Configure keyboard intercepts for ESC & ENTER.
$objForm.KeyPreview = $true
$objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Enter")
    {
        $x = $objListBox.SelectedItem
        $objForm.Close()
    }
})
$objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Escape")
    {
        $objForm.Close()
    }
})

# Create OK button.
$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 = $objListBox.SelectedItem
    $objForm.Close()
})
$objForm.Controls.Add($OKButton)

# Create Cancel button.
$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)

# Add form prompt text.
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Text = "Please select a computer:"
$objForm.Controls.Add($objLabel)

# Add list box.
$objListBox = New-Object System.Windows.Forms.ListBox
$objListBox.Location = New-Object System.Drawing.Size(10,40)
$objListBox.Size = New-Object System.Drawing.Size(260,20)
$objListBox.Height = 80

# Populate list.
[void] $objListBox.Items.Add("Option1")
[void] $objListBox.Items.Add("Option2")
[void] $objListBox.Items.Add("Option3")
[void] $objListBox.Items.Add("Option4")
[void] $objListBox.Items.Add("Option5")
[void] $objListBox.Items.Add("Option6")
[void] $objListBox.Items.Add("Option7")

# Force list box to display on top of other windows.
$objForm.TopMost = $true

# Display list box.
$objForm.Add_Shown({
    $objForm.Activate()
})
[void] $objForm.ShowDialog()

# Show result.
$x

第二个代码块导致:

我做错了什么,在这里?

注意:我在 Windows 7 上运行 PowerShell 3.0

【问题讨论】:

    标签: powershell


    【解决方案1】:

    获得列表框功能的一种简单方法是使用Out-GridView。例如:

    'one','two','three','four' | Out-GridView -OutputMode Single
    

    用户可以选择一个项目,它将在管道中返回。

    您也可以使用-OutputMode Multiple 进行多选。

    另一个例子:

    get-process | Out-GridView -OutputMode Multiple
    

    这将返回选定的对象:

    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
        396      24     5008       8964   113     8,88   3156 AuthManSvr
    

    【讨论】:

      【解决方案2】:

      将 OK 按钮单击处理程序修改为:

      $OKButton.Add_Click({$global:x=$objListBox.SelectedItem;$objForm.Close()})
      

      注意global: 范围说明符用于$x 变量。 PowerShell 使用动态作用域并对变量采用“写时复制”方法。也就是说,假设 $x 是在全局范围内定义的,在函数中修改 $x 只会修改变量的本地副本。如果您的意图是修改 $x 的全局值,则必须使用全局说明符,例如$global:x = ....

      【讨论】:

      • 这听起来可能超出了脚本的范围。如何在该函数之外使用 $x,同时将其包含在脚本中?另外,我做了什么破坏了第二个脚本中的对话框显示?
      • 好的,我想我想出了我的评论问题的第一部分。我将$x 更改为$script:x,这似乎奏效了。不过,我的第二个脚本有什么问题?
      • 没关系。找到了。我错过了$objForm.Controls.Add($objListBox)
      • 最后一个问题:由于这个脚本来源于TechNet的一篇文章,并且同一系列中也有类似的脚本以类似的方式定义$x,所以看起来这个应该 i> 工作过。 PowerShell 中是否发生了某些更改(例如:从 1.0 到 2.0,或到 3.0)导致脚本最初编写时无效?
      • 原始代码在 1.0 和 2.0 中工作。它从 3.0 开始中断。如果您查看 WMF 3.0 发行说明,则有一个名为 "Script blocks executed as delegates run in their own scope" 的重大更改记录在案,描述了该更改。
      猜你喜欢
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-24
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2017-08-13
      相关资源
      最近更新 更多