Powershell Set Variable for winforms objects

119 views Asked by At

I'm trying to define variables to winform object: $Textbox_serverDNS1,$Textbox_serverDNS2,$Textbox_serverDNS3

enter image description here

I'm trying to use this syntax, but it's now working:

for ($i=1; $i -le 3; $i++){
        Set-Variable -Name "TextBox_ServerDNS$($i)" -Value (New-Object -TypeName System.Windows.Forms.TextBox -Property @(Text = "10.10.10.$i")) -Scope Global
    }

any idea how can I define it in this way?

thanks,

2

There are 2 answers

1
Unknown Variable On

How about something like this?

add-type -assembly presentationframework
1..3 | foreach-object {
  set-variable "TextBox_ServerDNS$_" $(
    $box = [windows.controls.textbox]::new()
    $box.text = "10.10.10.$_"
    $box
  )
}

I would double check to make sure you're loading the correct types/assemblies you need as well.

6
mklement0 On

The only thing needed to fix your command is to replace -Property @(Text = "10.10.10.$i") with -Property @{ Text = "10.10.10.$i" }, i.e. you need to pass a hashtable (@{ ... }) with property name-value pairs rather than an array (@(...)).

  • The New-Object show the -Property parameter as IDictionary(-interface)-typed, meaning that a dictionary-like object - such as [hashtable] instance - must be passed.

However, you can streamline your approach as follows:

Add-Type -AssemblyName System.Windows.Forms

1..3 | ForEach-Object {
  Set-Variable -Scope Global -Name "TextBox_ServerDNS$_" -Value (
    [System.Windows.Forms.TextBox] @{ Text = "10.10.10.$_" }
  )
}

Note the convenient ability to cast the hashtable to the target type, which implicitly constructs an instance (assuming a parameter-less constructor) and initializes its properties based on the hashtable's entries.

Taking a step back:

  • Generally, it's best to avoid global variables, because they are session-global, i.e. they linger even after your script exits.

  • Instead of creating individual variables, it's preferable to construct a single array variable that stores the instances; the following example uses the $script: scope instead of the global one:

Add-Type -AssemblyName System.Windows.Forms

# You can use indexing to access the individual text boxes later, 
# e.g. $textBoxArray[0]
$script:textBoxArray = 
  1..3 | ForEach-Object { [System.Windows.Forms.TextBox] @{ Text = "10.10.10.$_" } }

Update:

  • It turns out that your true intent was to change the text of existing TextBox instances.

  • This requires the use of Get-Variable in order to indirectly retrieve variable values, as shown below.

1..3 | ForEach-Object {
  (Get-Variable -ValueOnly -Name "TextBox_ServerDNS$_").Text = "10.10.10.$_"
}