Share via

Simple PowershelL scope problem is VS2012

Boyd Mills 21 Reputation points
2023-05-02T14:36:23.74+00:00

SIMPLISTIC example with an added feature:

$Updated = "NO"

#region iS THE SYSTEM UPDATED?
Add-Type -Assembly PresentationFramework
[xml]$xaml = @"
<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen"
    SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray"> 
    <StackPanel x:Name='StackPanel'> 
        <TextBox     x:Name='textbox' Text='Has the machine been completely Updated?' IsReadOnly="True" />      
        <RadioButton x:Name="Item1" Content = 'YES' Foreground='Green'/>
        <RadioButton x:Name="Item2" Content = 'NO'  Foreground='RED'/>
    </StackPanel>
</Window>
"@

$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load( $reader )

$zzz = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") 

ForEach ($z in $zzz) 
{
    Set-Variable -Name ($z.Name) -Value $Window.FindName($z.Name)
}
[System.Windows.RoutedEventHandler]$Script:CheckedEventHandler = 
{
    Write-Host "changed"
    if ( $_.source.Content.Equals( "YES" ) )
    {
       $Updated = "YES"
    }
    else
    {
       $Updated = "NO"
    }
    Write-Host $Updated
}
$StackPanel.AddHandler([System.Windows.Controls.RadioButton]::CheckedEvent, $CheckedEventHandler)

$Window.Showdialog() | Out-Null
Write-Host $Updated

if ( $Updated.Equals("NO") )
{
   Write-Host "Exiting"
   Exit
}

Write-Host "Carry On"

Extracted from textbook examples

What is added <$Updated>

Within the scope of the dialog box, the value is toggled by the use of the radio buttons and displayed by a <Write-Host> diagnostic.

But when the dialog box exits, the <$Updated> value reverts to the original i.e. unchanged value.

I presume the dialog box creates a local or scope version of the variable different from the global variable.

So how do I get the dialog box to reference the Global Variable? Or return the local version as a string, but I would prefer the former approach.

Windows for business | Windows Server | User experience | PowerShell
Developer technologies | Visual Studio | Other
Developer technologies | Visual Studio | Other

A family of Microsoft suites of integrated development tools for building applications for Windows, the web, mobile devices and many other platforms. Miscellaneous topics that do not fit into specific categories.

0 comments No comments

1 answer

Sort by: Most helpful
  1. Rich Matheisen 48,116 Reputation points
    2023-05-02T15:30:34.4366667+00:00

    If you're using VS Code (I can't speak for Visual Studio because I rarely use it) and set a breakpoint on line 33 of your script ($Updated = "YES") and whan you examine "Variables" pane, you'll find there are two $Updated variables. One with a Script scope and the other with a Global scope.

    Use an explicit scope when declaring and referencing that variable:

    $Script:Updated = "NO"
    
    #region iS THE SYSTEM UPDATED?
    Add-Type -Assembly PresentationFramework
    [xml]$xaml = @"
    <Window 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="Window" Title="Initial Window" WindowStartupLocation = "CenterScreen"
        SizeToContent = "WidthAndHeight" ShowInTaskbar = "True" Background = "lightgray"> 
        <StackPanel x:Name='StackPanel'> 
            <TextBox     x:Name='textbox' Text='Has the machine been completely Updated?' IsReadOnly="True" />      
            <RadioButton x:Name="Item1" Content = 'YES' Foreground='Green'/>
            <RadioButton x:Name="Item2" Content = 'NO'  Foreground='RED'/>
        </StackPanel>
    </Window>
    "@
    
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
    $Window=[Windows.Markup.XamlReader]::Load( $reader )
    
    $zzz = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") 
    
    ForEach ($z in $zzz) 
    {
        Set-Variable -Name ($z.Name) -Value $Window.FindName($z.Name)
    }
    [System.Windows.RoutedEventHandler]$Script:CheckedEventHandler = 
    {
        Write-Host "changed"
        if ( $_.source.Content.Equals( "YES" ) )
        {
           $Script:Updated = "YES"
        }
        else
        {
           $Script:Updated = "NO"
        }
        Write-Host $Script:Updated
    }
    $StackPanel.AddHandler([System.Windows.Controls.RadioButton]::CheckedEvent, $CheckedEventHandler)
    
    $Window.Showdialog() | Out-Null
    Write-Host $Script:Updated
    
    if ( $Script:Updated.Equals("NO") )
    {
       Write-Host "Exiting"
       Exit
    }
    
    Write-Host "Carry On"
    

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.