Get parent name Get parent name powershell powershell

Get parent name


You need to set the .Name property for the button controls if you want to get their names inside the MouseEnter script:

Add-Type -AssemblyName System.Windows.Forms$A = @{    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }    Button01 = [System.Windows.Forms.Button] @{ Top = 0  ; Name = 'Button01'}    Button02 = [System.Windows.Forms.Button] @{ Top = 30 ; Name = 'Button02'}    Button03 = [System.Windows.Forms.Button] @{ Top = 60 ; Name = 'Button03'}}$Script = { Write-host $this.Name }1..3 | ForEach-Object {    $A["Button0$_"].Add_MouseEnter($Script)    $A.Main.Controls.Add($A["Button0$_"])}[void]$A.Main.ShowDialog()$A.Main.Dispose()


Edit

Creating and naming the buttons inside the ForEach-Object loop could save you typing the name for each button:

Add-Type -AssemblyName System.Windows.Forms$A = @{    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }}$Script = { Write-host $this.Name }1..3 | ForEach-Object {    $A["Button0$_"] = [System.Windows.Forms.Button] @{ Top = ($_ -1) * 30 ; Name = "Button0$_"}    $A["Button0$_"].Add_MouseEnter($Script)    $A.Main.Controls.Add($A["Button0$_"])}[void]$A.Main.ShowDialog()$A.Main.Dispose()


As Theo points out in his answer, you need to name your button objects by assigning to their .Name property.

To avoid naming your buttons twice - once as a property name in your hashtable, and again via the .Name property - you can create the buttons as an array, which simplifies the solution overall:

$A = @{    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }    # Create an *array* of buttons    Buttons = [System.Windows.Forms.Button] @{ Top = 0; Name = 'Button1' },              [System.Windows.Forms.Button] @{ Top = 30; Name = 'Button2' },              [System.Windows.Forms.Button] @{ Top = 60; Name = 'Button3' }}# Print the name of the button being moused over.$Script = { $this.Name | Out-Host }# Attach the event-handler script block to each button.$A.Buttons | % {    $_.Add_MouseEnter($Script)}# Add the buttons to the form.$A.Main.Controls.AddRange($A.Buttons)$null = $A.Main.ShowDialog()

If you want to avoid assigning to the .Name property, you can use the following approach:

Use PowerShell's ETS (Extended Type System) to add the key of the hashtable entry in which each button is stored as a custom property (a NoteProperty instance member), using Add-Member, which the event-handler script can query:

Add-Type -AssemblyName System.Windows.Forms$A = @{    Main = [System.Windows.Forms.Form] @{ StartPosition = 'CenterParent' }    Button01 = [System.Windows.Forms.Button] @{ Top = 0 }    Button02 = [System.Windows.Forms.Button] @{ Top = 30 }    Button03 = [System.Windows.Forms.Button] @{ Top = 60 }}$Script = {    # Access the custom .CustomParent property added to each button instance below.    Write-Host $this.CustomParent}1..3 | % {    $key = "Button0$_"    $btn = $A[$key]    # Add a .CustomParent NoteProperty member to the button object    # storing the key of the hashtable entry in which that button is stored.    $btn | Add-Member -NotePropertyMembers @{ CustomParent = $key }    $btn.Add_MouseEnter($Script)    $A.Main.Controls.Add($btn)}[void]$A.Main.ShowDialog()

As for why PowerShell doesn't - and shouldn't - provide an automatic (built in) variable such as $GetParentName to support this scenario:

There are two unrelated worlds involved in this scenario:

  • PowerShell variables

  • The .NET types from the System.Windows.Forms namespace (WinForms)

WinForms is language-agnostic - any .NET language can use it; all it knows about is how instance of its types are nested at runtime and how to raise appropriate .NET events, typically in response to user events.

The source object of an event, as reported by WinForms, is surfaced as $this in a PowerShell script block acting as a .NET event delegate invoked directly by WinForms.

WinForms (rightfully) has no knowledge of what data structure or variable on the PowerShell side the event-originating object is stored in.

Even on the PowerShell side this is completely at your discretion - you could have chosen individual variables, for instance, or an array, as shown above, so there is no general pattern here that an automatic variable could support.

In the case at hand, PowerShell itself has no way of knowing that your $Script block happens to be indirectly associated with a button instance incidentally stored in a hashtable entry.