在powershell函数

时间:2017-09-19 21:50:46

标签: function powershell variables scope

我一直在研究这个在概念上看起来很简单的剧本,但是我真的很难看到一些似乎没有像我期望的那样工作的东西。基本思想是脚本将读取一组用户名,并为用户提供一个复选框,他们可以检查他们希望系统创建的每个帐户。在这个站点的帮助下,我能够获得一个能够动态创建变量和复选框对象的函数,但现在我在访问它们的值时遇到了问题。我只需要为每个名称拉一个布尔值,无论是否选中该框。这是完整的代码:

$form = New-Object System.Windows.Forms.Form
$flowlayoutpanel = New-Object System.Windows.Forms.FlowLayoutPanel
$buttonOK = New-Object System.Windows.Forms.Button


$usernames = "andrew", "beth", "charlie", "dave", "james", "george"
$totalvalues = ($usernames.count)

$formsize = 85 + (30 * $totalvalues)
$flowlayoutsize = 10 + (30 * $totalvalues)
$buttonplacement = 40 + (30 * $totalvalues)

$form_Load = {
    foreach($user in $usernames){
        $DynamicCheckBox = New-Variable -Name ("checkbox" + $user)
        $DynamicCheckBox = New-object System.Windows.Forms.CheckBox

        $DynamicCheckBox.Margin = '10, 8, 0, 0'
        $DynamicCheckBox.Name = 'checkbox' + $_
        $DynamicCheckBox.Size = '200, 22'
        $DynamicCheckBox.Text = "" + $user
        $DynamicCheckBox.TextAlign = 'MiddleLeft'
        $flowlayoutpanel.Controls.Add($DynamicCheckBox)
    }       
}

$form.Controls.Add($flowlayoutpanel)
$form.Controls.Add($buttonOK)
$form.AcceptButton = $buttonOK
$form.AutoScaleDimensions = '8, 17'
$form.AutoScaleMode = 'Font'
$form.ClientSize = "500 , $formsize"
$form.FormBorderStyle = 'FixedDialog'
$form.Margin = '5, 5, 5, 5'
$form.MaximizeBox = $False
$form.MinimizeBox = $False
$form.Name = 'form1'
$form.StartPosition = 'CenterScreen'
$form.Text = 'Form'
$form.add_Load($form_Load)

$flowlayoutpanel.BorderStyle = 'FixedSingle'
$flowlayoutpanel.Location = '48, 13'
$flowlayoutpanel.Margin = '4, 4, 4, 4'
$flowlayoutpanel.Name = 'flowlayoutpanel1'
$flowlayoutpanel.Size = "400, $flowlayoutsize"
$flowlayoutpanel.TabIndex = 1

$buttonOK.Anchor = 'Bottom, Right'
$buttonOK.DialogResult = 'OK'
$buttonOK.Location = "383, $buttonplacement"
$buttonOK.Margin = '4, 4, 4, 4'
$buttonOK.Name = 'buttonOK'
$buttonOK.Size = '100, 30'
$buttonOK.TabIndex = 0
$buttonOK.Text = '&OK'


$form.ShowDialog()

    foreach($user in $usernames){
        $DynamicCheckBoxValue = Get-Variable -Name ('$checkbox' + $user) -Scope Script
        write-host $DynamicCheckBoxValue

    }  

write-host $checkbox.Checked

我已尝试使用第15行中创建的变量的范围设置,但如果我将范围更改为脚本,我认为它应该是,我会收到一系列奇怪的错误。 Powershell告诉我变量已经存在(虽然这可能是因为它们仍然在我的ISE会话中?)。如果我告诉它强行覆盖任何可能修复该错误的错误,但无论哪种方式我都会收到错误,告诉我该变量不存在,即使刚好在powershell抱怨已经的变量< / em>存在。

Get-Variable : Cannot find a variable with the name '$checkboxgeorge'.
At C:\Users\sheep\Untitled1.ps1:62 char:33
+ ...      $DynamicCheckBoxValue = Get-Variable -Name ('$checkbox' + $user)
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: ($checkboxgeorge:String) [Get-Variable], ItemNotFoundException
    + FullyQualifiedErrorId : VariableNotFound,Microsoft.PowerShell.Commands.GetVariableCommand

我不确定这里发生了什么,而且我正在摆弄范围,因为似乎就像罪魁祸首一样。如果有人在这里知道修复是什么,你也可以告诉我为什么会这样吗?

3 个答案:

答案 0 :(得分:1)

即使我提交了这个答案,我强烈建议您阅读TesselatingHeckler here中的答案,并在评论部分向您提供。

此外,虽然动态变量是一个东西,但在你的情况下,这是一个被证明是无用的层,并且当这可以更加简单时添加复杂的逻辑。

比您的方案的动态变量更好的解决方案。

例如,不是创建用户名数组,而是使用哈希表,该哈希表仍会存储您的用户名,但会有一个&#34;值&#34;您可以用来存储bolean的字段,很快,当您有更复杂的东西时,您可以在值字段中存储完整的对象。

$usernames = 
            @{
            'andrew'='';
            'beth'='';
            'charlie'='';
            'dave'='';
            'james'=''
            'george'=''
            }

现在你有了哈希表,你可以使用

设置你的值
#Settings some value - in your case, that would be done through the form
$usernames.andrew = 0 
$usernames.dave = 1

你甚至可以动态地&#34;动态地&#34;

$User = Read-Host  # Asking which user here
$usernames.Item($User) = 1 # setting user "checkbox value" to 1 here

例如,在最后一个示例中,用户名存储在$User中,然后该用户的值设置为&#39; 1&#39; 。

它可以为您提供所需的一切,而无需设置动态变量的开销。

一个简单的陈述,显示谁检查了他们的复选框。 因为所有内容都在$ Usernames哈希表中,所以很容易操作,存储到csv文件等等......而无需任何额外的工作。

# Display users checked status their checkboxes
$usernames | ft Name, @{n='IsChecked';e={$_.Value -eq 1}}

答案 1 :(得分:0)

下面的行没有对变量$ DynamicCheckBox进行任何更改。

$DynamicCheckBox = New-Variable -Name ("checkbox" + $user)

我修改了脚本以找出检查了哪些用户。希望这会有所帮助。

<强> 代码: -

    $form = New-Object System.Windows.Forms.Form
    $flowlayoutpanel = New-Object System.Windows.Forms.FlowLayoutPanel
    $buttonOK = New-Object System.Windows.Forms.Button


    $usernames = "andrew", "beth", "charlie", "dave", "james", "george"
    $totalvalues = ($usernames.count)

    $formsize = 85 + (30 * $totalvalues)
    $flowlayoutsize = 10 + (30 * $totalvalues)
    $buttonplacement = 40 + (30 * $totalvalues)

    $script:CheckBoxArray = @()

    $form_Load = {

       foreach($user in $usernames){

            $DynamicCheckBox = New-object System.Windows.Forms.CheckBox

            $DynamicCheckBox.Margin = '10, 8, 0, 0'
            $DynamicCheckBox.Name = $user
            $DynamicCheckBox.Size = '200, 22'
            $DynamicCheckBox.Text = "" + $user
            $DynamicCheckBox.TextAlign = 'MiddleLeft'
            $flowlayoutpanel.Controls.Add($DynamicCheckBox)
            $script:CheckBoxArray += $DynamicCheckBox
        }       
    }

    $form.Controls.Add($flowlayoutpanel)
    $form.Controls.Add($buttonOK)
    $form.AcceptButton = $buttonOK
    $form.AutoScaleDimensions = '8, 17'
    $form.AutoScaleMode = 'Font'
    $form.ClientSize = "500 , $formsize"
    $form.FormBorderStyle = 'FixedDialog'
    $form.Margin = '5, 5, 5, 5'
    $form.MaximizeBox = $False
    $form.MinimizeBox = $False
    $form.Name = 'form1'
    $form.StartPosition = 'CenterScreen'
    $form.Text = 'Form'
    $form.add_Load($($form_Load))

    $flowlayoutpanel.BorderStyle = 'FixedSingle'
    $flowlayoutpanel.Location = '48, 13'
    $flowlayoutpanel.Margin = '4, 4, 4, 4'
    $flowlayoutpanel.Name = 'flowlayoutpanel1'
    $flowlayoutpanel.AccessibleName = 'flowlayoutpanel1'
    $flowlayoutpanel.Size = "400, $flowlayoutsize"
    $flowlayoutpanel.TabIndex = 1

    $buttonOK.Anchor = 'Bottom, Right'
    $buttonOK.DialogResult = 'OK'
    $buttonOK.Location = "383, $buttonplacement"
    $buttonOK.Margin = '4, 4, 4, 4'
    $buttonOK.Name = 'buttonOK'
    $buttonOK.Size = '100, 30'
    $buttonOK.TabIndex = 0
    $buttonOK.Text = '&OK'


    $form.ShowDialog()

        foreach($cbox in $CheckBoxArray){
            $cbox.Name + " is " + $cbox.CheckState

        }  

    Remove-Variable checkbox*

<强> 输入: -

enter image description here

<强> 输出: -

enter image description here

答案 2 :(得分:-1)

这可能会让你朝着正确的方向前进。

使用Get-Variable时,您必须排除$。所以使用: Get-Variable -Name ("checkbox" + $user) -Scope Script