首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Powershell GUI自动生成带有函数的按钮

Powershell GUI自动生成带有函数的按钮
EN

Stack Overflow用户
提问于 2021-01-21 05:22:42
回答 2查看 298关注 0票数 0

TLDR:如何创建一个生成的变量,然后在Add中调用该变量_单击。我确信我创建的每个对象/按钮都需要某种序列化。

我正在建立一个小工具,从csv读取创建一个按钮,和功能。

csv看起来像这样

代码语言:javascript
复制
Name  Type  Link  Script
Powershell App C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe Empty
FixXYZ Fix Empty -ScriptStuffHere-

然后,该工具将创建一个名称为(正在进行过滤应用程序和修复的工作)的按钮,当您单击该按钮时,如果这是一个应用程序就可以start ($link)如果这是一个修复,它将运行该脚本。

我的问题是,我让它制作按钮并给它们命名,按钮的名称保持不变,但函数不会。

完整代码:

代码语言:javascript
复制
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()

#=======================================================

$Form                            = New-Object system.Windows.Forms.Form
$Form.text                       = "Form"
$Form.TopMost                    = $false
$Form.ClientSize                 = New-Object System.Drawing.Point(760,400)
$Form.minimumSize                = New-Object System.Drawing.Size(760,400) 
$Form.maximumSize                = New-Object System.Drawing.Size(760,400) 

$GetCSV = import-csv "C:\File.csv"
$Details = $GetCSV.Name

$DeviceList = $GetCSV

$Count = $DeviceList.Lines.Count
$ObjectNumber = -1
Write-Host "Total Entries:" $Count


$x = 0 #up down
$z = 0 #left right


$Names = @($DeviceList.Lines)
$Names | ForEach-Object{
$ObjectNumber += 1
Write-Host "Object:" $ObjectNumber 

$x += 0
$z += 120

if($z -eq 720){
$x += 120
$z = 0
Write-Host "New Row"}



Write-Host "x" $x
Write-Host "z" $z
$ButtonLabel = ($GetCSV[$ObjectNumber]).Name

set-Variable -Name "var$ObjectNumber" -Value ($GetCSV[$ObjectNumber] | Select Name, Type, Link, Script, File, FileSource)

Write-Host "Name: " (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Name
Write-Host "Type: " (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Type
Write-Host "Link: "(Get-Variable -Name "var$ObjectNumber" -ValueOnly).Link
Write-Host "Script: "(Get-Variable -Name "var$ObjectNumber" -ValueOnly).Script
Write-Host "File: "(Get-Variable -Name "var$ObjectNumber" -ValueOnly).File
Write-Host =========================

         
$_                         = New-Object system.Windows.Forms.Button
$_.text                    = $ButtonLabel
$_.width                   = 100
$_.height                  = 100
$_.location                = New-Object System.Drawing.Point($z,$x)
$_.Font                    = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$_.Add_Click({              Start (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Link})

$Form.Controls.Add($_)

}

[void]$Form.ShowDialog()

我很确定我的问题来自

$_.Add_Click({Start (Get-Variable -Name "var$ObjectNumber" -ValueOnly).Link})

我知道问题出在$ObjectNumber上,因为每次通过ForEach时,这个数字都会变为+1,所以当我单击一个按钮时,它会将"var$OjbectNumber“作为它的最后一个数字。单击该按钮可以工作,但所有按钮都会打开last entries链接。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-26 05:36:16

答案是使用一个未使用的属性来抛出我想要的回调变量。因此,在本例中,我有一个包含程序的文件夹,将创建按钮,并将$Button.Text (其名称)设置为.exe的名称,然后它会将$Button.Tag设置为文件路径,因此当我执行button.Add操作时_单击,我只是调用Button.Tag,因为它将具有我的Exe的路径。

代码语言:javascript
复制
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '580,400'
$Form.Text                       = "Test"
$Form.TopMost                    = $false
$Form.FormBorderStyle            = 'Fixed3D'
$Form.MaximizeBox                = $false
$Form.minimumSize                = New-Object System.Drawing.Size(580,400) 
$Form.maximumSize                = New-Object System.Drawing.Size(580,400) 

#Place Holder Form Junk Above




#Reset these on Run
$Global:x             = 10 #Reset up down
$Global:z             = 10 #Reset left right
$Global:ObjectNumber = -1 #Reset Object Count






Function Make-Button([string] $ToolName, [string] $ToolPath, [string] $SetZ, [string] $SetX){
$Button                         = New-Object system.Windows.Forms.Button
$Button.text                    = $ToolName
$Button.width                   = 120
$Button.height                  = 120
$Button.location                = New-Object System.Drawing.Point($SetZ,$SetX)
$Button.Font                    = New-Object System.Drawing.Font('Franklin Gothic',10)
$Button.FlatStyle           = [System.Windows.Forms.FlatStyle]::Flat
$Button.FlatAppearance.BorderSize  = 0
$Button.ForeColor           = [System.Drawing.ColorTranslator]::FromHtml("#ffffff")
$Button.BackColor           = [System.Drawing.ColorTranslator]::FromHtml("#515582")

$Button.tag = $ToolPath #<- this is where the answer was. Throwing my desired callback into an unused property of the the Button. in this case, i used _.Tag
$Button.Add_Click{start $this.tag}

$Form.Controls.AddRange(@($Button))

Write-Host "$ToolName"
Write-Host "$ToolPath"
Write-Host "$SetZ"
Write-Host "$SetX"

}

function Get-Position{
switch ($Global:ObjectNumber) {
-1{$Global:ObjectNumber += 1
Write-Host "Object:" $Global:ObjectNumber 

$Global:x = 0
$Global:z += 0}


Default{$Global:ObjectNumber += 1
Write-Host "Object:" $Global:ObjectNumber 

$Global:x += 0
$Global:z += 140}
}#end switch

if($Global:z -eq 570){ #Make New Row
$Global:x += 140
$Global:z = 10
Write-Host "New Row"
}
}


$Tools = Get-ChildItem "C:\WINDOWS\system32" -Filter *.exe
$Count = ( $Tools | Measure-Object ).Count;
Write-Host "Entries:" $Count





$Names = @($Tools) #Put Tools in Array
$Names | ForEach-Object{

                        Get-Position
                        Make-Button ($_.Name).replace(".exe","") ($_.FullName) ($z) ($x)

}











#End Form
$Test.Add_Shown(            {$Test.Activate()})
$Test.ShowDialog() 
[void]$Form.ShowDialog()
票数 0
EN

Stack Overflow用户

发布于 2021-01-21 15:01:21

继续我的评论...

一个小的重构,用来显示这些东西的位置

代码语言:javascript
复制
Clear-Host 

Add-Type -AssemblyName System.Windows.Forms,
                       PresentationFramework

[System.Windows.Forms.Application]::EnableVisualStyles()

$Form             = New-Object system.Windows.Forms.Form
$Form.text        = 'Form'
$Form.TopMost     = $false
$Form.ClientSize  = New-Object System.Drawing.Point(760,400)
$Form.minimumSize = New-Object System.Drawing.Size(760,400) 
$Form.maximumSize = New-Object System.Drawing.Size(760,400) 

$GetCSV       = Import-Csv -LiteralPath 'D:\Scripts\File.csv'
$Details      = $GetCSV.Name
$DeviceList   = $GetCSV
$Count        = $DeviceList.Count
$ObjectNumber = -1
 "Total Entries: $Count`n`n"

$ObjDown  = 0
$ObjRight = 0

$DeviceList.Name | 
ForEach-Object{
    $ObjectNumber += 1
    "`nObject: $ObjectNumber"

    $x        = 0
    $ObjRight = 120

    if($ObjRight -eq 720)
    {
        $x        = 120
        $ObjRight = 0
        'New Row'
    }


    "x $x"
    "z $ObjRight"

    $ButtonLabel = ($GetCSV[$ObjectNumber]).Name

    set-Variable -Name $("var$ObjectNumber") -Value ($GetCSV[$ObjectNumber] | 
    Select Name, Type, Link, Script, File, FileSource)

    ("Name:   $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Name)")
    ("Type:   $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Type)")
    ("Link:   $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Link)")
    ("Script: $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).Script)")
    ("File:   $((Get-Variable -Name $("var$ObjectNumber") -ValueOnly).File)")
         
    $PSitem          = New-Object system.Windows.Forms.Button
    $PSitem.text     = $ButtonLabel
    $PSitem.width    = 100
    $PSitem.height   = 100
    $PSitem.location = New-Object System.Drawing.Point($ObjRight,$x)
    $PSitem.Font     = New-Object System.Drawing.Font('Microsoft Sans Serif',10)

    $PSitem.Add_Click({
        $(Get-Variable -Name $("var$ObjectNumber") -ValueOnly)
    })
    $Form.Controls.Add($PSitem)
}

#[void]$Form.ShowDialog()

这是我给出的一个例子,作为对另一篇文章的回答,它动态地创建UX/UI元素并分配一个表单事件,尽管没有使用外部文件,但它的概念是相同的。

如何使用PowerShell?创建多个按钮

添加工具提示和窗体事件,如下所示...

代码语言:javascript
复制
$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = New-Object System.Drawing.Point(381,316)
$Form.text                       = "Auto Button UI"
$Form.TopMost                    = $false
$Form.BackColor                  = [System.Drawing.ColorTranslator]::FromHtml("#c9f6fe")

$i = 0
Get-Variable -Name 'Button*' | 
Remove-Variable

$objTooltip = New-Object System.Windows.Forms.ToolTip 
$objTooltip.InitialDelay = 100 

1..3 | 
foreach{
    $CurrentButton          = $null
    $CurrentButton          = New-Object System.Windows.Forms.Button
    $CurrentButton.Location = "$(50+100*$i), 275"
    $CurrentButton.Text     = $PSItem
    $CurrentButton.Font     = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
    
    New-Variable "Button$PSitem" $CurrentButton

    $objTooltip.SetToolTip(
        $CurrentButton, 
        "Execute action assigned to $($CurrentButton.Text)"
    )

    $CurrentButton.add_click(
    {
        [System.Windows.Forms.MessageBox]::
        Show(
            "$($CurrentButton.Text)", $($CurrentButton.Text), [System.Windows.Forms.MessageBoxButtons]::
            OKCancel, [System.Windows.Forms.MessageBoxIcon]::Information
        )
    })

    $i++
    $form.Controls.Add($CurrentButton)
}

[void]$Form.ShowDialog()

然而,尽管它将事件添加到每个按钮元素,但消息文本是最后传递的一个。除非在链接的示例中显式调用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65817873

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档