我可以一次创建/声明多个相同类型的PowerShell对象吗?

时间:2019-02-28 21:23:41

标签: powershell

我有一个PowerShell(5.1版)表单,其中包含System.Windows.Forms个对象的各种集合,所有对象都命名为通用名称,例如$label1$label2等,以及{{1 }},$textBox1

目前,我正在按照表单中显示的内容来创建它们,就像这样:

$textBox2

我已经根据此方案创建和命名了几十个这些对象,我真的很想通过在一行上创建所有这些对象来节省一些行(例如,所有{{1 }}放在一行上,然后将所有Add-Type -AssemblyName System.Windows.Forms $Form = New-Object system.Windows.Forms.Form $Form | ForEach-Object { $_.Size = New-Object System.Drawing.Size(800,550) $_.StartPosition = 'CenterScreen' $_.Text = "Example Form Name" $_.Topmost = $true } $label1 = New-Object System.Windows.Forms.Label $label1 | ForEach-Object { $_.Location = '10,10' $_.Size = '156,20' $_.Text = 'Dummy text part 1' } $textBox1 = New-Object System.Windows.Forms.TextBox $textBox1 | ForEach-Object { $_.Location = '166,8' $_.Size = '100,20' } $label2 = New-Object System.Windows.Forms.Label $label2 | ForEach-Object { $_.Location = '267, 10' $_.Size = '85,20' $_.Text = 'Dummy text part 2' } $textBox2 = New-Object System.Windows.Forms.TextBox $textBox2 | ForEach-Object { $_.Location = '352,8' $_.Size = '100,20' } #A lot more lines of similar code go here $Form.Controls.Add($label1) $Form.Controls.Add($textBox1) $Form.Controls.Add($label2) $Form.Controls.Add($textBox2) $result = $Form.ShowDialog() 放在一行上,或者至少使用一种方法/函数。

我尝试过:

label

而不是在上面完整的演示表单中单独声明每个textBox,但是PowerShell似乎不能这样工作;它只会创建$label1, $label2, $label3 = New-Object System.Windows.Forms.Label (这本身很奇怪;我希望它仅能创建$label才能在其中的一个上工作),然后PowerShell ISE会在属性声明后抛出错误开启$label1$label3

The property 'Location' cannot be found on this object. Verify that the property exists and can be set. 
At <filepath>.ps1:43 char:5
+     $_.Location = '267, 10'
+     ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

...等等。

有没有办法一次性创建多个具有递增后缀的相同类型的对象,而不是在各自的行中声明它们,还是我坚持写这些它们现在是如何获得的?

2 个答案:

答案 0 :(得分:6)

多重赋值将赋值右侧的数组元素分配给左侧的变量。 New-Object本身不允许一次创建多个对象。您可以编写一个循环或生成标签数组的函数,然后使用多重分配将该数组的元素分配给变量。

$label1, $label2, $label3 = 1..3 | ForEach-Object {
    New-Object Windows.Forms.Label
}

function New-Label {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$false)]
        [int]$Count = 1
    )

    for ($i=0; $i -lt $count; $i++) {
        New-Object Windows.Forms.Label
    }
}

$label1, $label2, $label3 = New-Label 3

但是,我认为一种更好的方法是编写一个函数,用给定的参数创建一个标签对象,然后将该函数的输出分配给一个变量。

function New-Label {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [string]$Location,
        [Parameter(Mandatory=$true)]
        [string]$Size,
        [Parameter(Mandatory=$false)]
        [string]$Text = ''
    )

    $o = New-Object Windows.Forms.Label
    $o.Location = $Location
    $o.Size     = $Size
    $o.Text     = $Text

    return $o
}

$label1 = New-Label -Location '10,10' -Size '156,20' -Text 'Dummy text part 1'
$label2 = New-Label -Location '267,10' -Size '85,20' -Text 'Dummy text part 2'
$label3 = ...

您也可以直接将标签添加到表单中,而不是先将它们分配给变量:

$Form.Controls.Add((New-Label '10,10' '156,20' 'Dummy text part 1'))
$Form.Controls.Add((New-Label '267,10' '85,20' 'Dummy text part 2'))
$Form.Controls.Add((New-Label ...))

请注意,将matrjoshking(嵌套)到方法调用中时,需要在函数调用周围对表达式进行分组。因此有两组括号。

当然,New-Label可以进一步改进,例如通过使用整数数组代替$Location$Size的字符串。或者通过设置另一个参数来设置$Top$Left$Width$Height的各个值,然后根据所使用的参数集分配值。参数也应验证。依此类推,等等。

答案 1 :(得分:1)

这个...

$label1, $label2, $label3 = New-Object System.Windows.Forms.Label

...创建一个新的Label并将其分配给$label1。没有为$label2$label3分配任何内容,因为右侧没有更多的值可以分配给它们。如果该语法确实分配了所有三个变量,它们将(可能)全部包含相同的Label实例,无论如何都不适用于您的用例。

相反,要实例化三个Label实例并将它们分配给三个变量,您需要这样做...

$label1, $label2, $label3 = (New-Object System.Windows.Forms.Label), (New-Object System.Windows.Forms.Label), (New-Object System.Windows.Forms.Label)

...可以简化为...

$label1, $label2, $label3 = 1..3 | ForEach-Object -Process { New-Object System.Windows.Forms.Label }

...可以简化为...

$label1, $label2, $label3 = 1..3 | % { New-Object System.Windows.Forms.Label }