动态地将信息分配给" Add_Click" powershell

时间:2016-01-06 21:36:41

标签: powershell

我想动态地将信息分配给" Add_Click"在powershell中的GUI按钮上的事件。

所以概述 - 我正在制作一个GUI工具,它可以加载一些用于定制"修复"对于人们的PC。每个按钮都是从脚本加载的,每个脚本都包含用于信息的变量,例如按钮名称,按钮图标,以及执行脚本要执行的任何操作的函数。

因此,根据下面的示例,我发现问题在于我分配Add_Click事件。我很抱歉不确定如何更好地解释,但它似乎没有扩展$ script变量,它会将add_click保存为变量,这样当我运行程序时,所有按钮都使用最后存储的内容在变量$ script中(所以所有按钮看起来都不一样,但运行相同的脚本)。

我希望能够做的是让每个按钮使用Add_Click来运行在" Foreach"中分配Add_Click时存储在$ script中的任何脚本。循环。

示例脚本:

#Button Container (Array to store all the Buttons)
$ComputerActionButtons = @()

#Get all the script files that we will load as buttons
$buttonsFileArray = Get-ChildItem  "$dir\Addin\ " | Select -ExpandProperty Name

#Load Buttons
$ButtonTempCount = 1
Foreach ($script in $buttonsFileArray){
    . $dir\Addin\$script
    Write-Host "Loading Button: $ButtonName"

    # Generate button
    $TempButton = New-Object System.Windows.Forms.Button 
    $TempButton.Location = New-Object System.Drawing.Size(140,20) 
    $TempButton.Size = New-Object System.Drawing.Size(100,100) 
    $TempButton.Text = "$ButtonName"
    $TempButton.Image = $ButtonIcon
    $TempButton.TextImageRelation = "ImageAboveText"
    $TempButton.Add_Click({& $dir\Addin\$script}) 
    $ComputerActionButtons += $TempButton
}

#Add Buttons to panel
$CAButtonLoc = 20
Foreach ($button in $ComputerActionButtons){
    $button.Location = New-Object System.Drawing.Size(50,$CAButtonLoc)
    $ComputerActionsPanel.Controls.Add($button)
    $CAButtonLoc = $CAButtonLoc + 120
}

我一直在研究变量,发现你可以做一个New-Variable和Get-Variable命令来动态设置和获取变量名,但由于原始问题,使用它似乎没有帮助。

我希望我已经解释得这么好,如果我能提供更多信息,请告诉我。

谢谢,

亚当

2 个答案:

答案 0 :(得分:3)

您需要在分配时在$script值上创建一个闭包,而不是在运行时依赖$script的值。

幸运的是,所有ScriptBlock都支持GetNewClosure() method

foreach($i in 1..3){
    $blocks += {echo $i}.GetNewClosure()
}
$blocks |Foreach-Object {$_.Invoke()}

产生:

1
2
3

相反
foreach($i in 1..3){
    $blocks += {echo $i}
}
$blocks |Foreach-Object {$_.Invoke()}

产生:

3
3
3

GetNewClosure()做的是它“捕获”当时ScriptBlock中引用的变量并将其绑定到scriptblock的本地范围。

这样原始的$i变量(或$script就此而言)被“隐藏”在与$i 具有相同值的$i变量下方过去有 - 即在GetNewClosure()被称为

答案 1 :(得分:2)

不使用创建新动态模块的GetNewClosure,而是将本地范围变量捕获到它并将ScriptBlock绑定到该模块,因此实际上您将无法访问未在全局范围内定义的任何函数,您可以在按钮本身中存储任何按钮特定数据。 Control基类具有Tag属性,您可以在其中存储所需的任何数据。

$TempButton.Tag=@{Script=$script}
$TempButton.Add_Click({param($Sender) & "$dir\Addin\$($Sender.Tag.Script)"})