locked
PowerShell Countdown Timer. WPF appearance and trouble updating text RRS feed

  • Question

  • The script below is a countdown timer with an abort option.  The first issue is that it doesn’t look the same when run inside PS v4 ISE as from when it is run at the PS v4 prompt.  The XAML was written using Visual Studio.  The second issue is that I can't figure out how to make the timer decrement.

    $iSeconds = 120
    Add-Type –assemblyName PresentationFramework
    Add-Type –assemblyName PresentationCore
    Add-Type –assemblyName WindowsBase
    
    Function Close-Form{
        #$timer.Enabled = $false
        #$timer.Dispose()
        $Window.Close() 
    }
    
    #XML for menu
    [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="Countdown" WindowStartupLocation = "CenterScreen" ResizeMode="NoResize"
        Width = "214" Height = "155" ShowInTaskbar = "True" Background = "LightBlue" WindowStyle="ThreeDBorderWindow">
        <StackPanel Margin="0,0,0,7" HorizontalAlignment="Right" Width="208" >
            <StackPanel.Effect>
                <DropShadowEffect/>
            </StackPanel.Effect>
            <Label Content='Time remaining before Lock' VerticalAlignment="Center" HorizontalAlignment="Center" />
            <TextBox x:Name="TimeBox" IsReadOnly = "False" Height = "30"
        		TextWrapping="Wrap" VerticalScrollBarVisibility = "Auto" Text="0:00" HorizontalContentAlignment="Center" MaxWidth="100" MaxHeight="25"/>
            <StackPanel Orientation = 'Horizontal' Margin="10,0,0,0" Panel.ZIndex="5" Height="64">
                <Button x:Name = "OkBtn" Height = "50" Width = "65" Content = 'Lock Now' Background="Green" HorizontalAlignment="Right" VerticalAlignment="Center" >
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                </Button>
                <Button x:Name = "CancelBtn" Height = "50" Width = "65" Content = 'Cancel' Background="Red" Margin = "50,0,0,0" VerticalAlignment="Center" >
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                </Button>
            </StackPanel>
        </StackPanel>
    </Window>
    "@
     
    $iCtr = 0
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
    $Window=[Windows.Markup.XamlReader]::Load( $reader )
    
    #Connect to Controls
    $OKBtn = $Window.FindName('OkBtn')
    $Cancelbtn = $Window.FindName('CancelBtn')
    $TimeBox = $Window.FindName('TimeBox')
    
    #Event handlers             
    $Window.Add_SourceInitialized( {
         # Before the window's even displayed ...            
        # We'll create a timer            
        $script:timer = new-object System.Windows.Threading.DispatcherTimer            
        # Which fire 1 time each second
        $timer.Interval = [TimeSpan]"0:0:1.0"            
        # And will invoke the $updateBlock          
        $timer.Add_Tick.Invoke($UpDateBlock)           
        # Now start the timer running            
        $timer.Start()  
        if( $timer.IsEnabled -eq $false) { 
           write-warning "Timer didn't start"      
        }            
     } )            
    
    $OKBtn.Add_Click({
        Write-Warning "Locking Now"
        Close-Form
    })
    
    $CancelBtn.Add_Click({
        Close-Form
    })
    
    $UpDateBlock = ({
        #Simply decrement until zero does not work
        $iSeconds = $iSeconds - $iCtr
        [char[]]$mins = "{0}" -f ($iSeconds / 60)
        $secs = "{0:00}" -f ($iSeconds % 60)
    
        $TimeBoxTxt = "{0}:{1}" -f $mins[0], $secs
        #write $timeboxtxt
    
        $Timebox.Dispatcher.Invoke("Normal",[action]{($Timebox.text=$TimeBoxTxt)})
    
        if ($iSeconds -eq 0) {
           Close-Form
        }
      })
    
    $Window.ShowDialog() | Out-Null

    I have spent way too much time trying to figure this out, and appreciate suggestions and guidance.

    • Moved by Bill_Stewart Friday, August 14, 2015 7:12 PM This is not "scripts on demand"
    Tuesday, May 26, 2015 2:12 PM

All replies

  • Look up windows timer control for WPF.

    You cannot change how ISE works.  ISE really isn't designed to be a standalone execution engine and it is also a preexistent GUI. It will force your theme.


    \_(ツ)_/


    • Edited by jrv Tuesday, May 26, 2015 2:28 PM
    Tuesday, May 26, 2015 2:26 PM
  • This will tick for you.

    Add-Type –assemblyName PresentationFramework
    Add-Type –assemblyName PresentationCore
    Add-Type –assemblyName WindowsBase
    
    Function Close-Form {
        #$timer.Enabled = $false
        #$timer.Dispose()
        $Window.Close()
    }
    
    #XML for menu
    [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="Countdown" WindowStartupLocation = "CenterScreen" ResizeMode="NoResize"
        Width = "214" Height = "155" ShowInTaskbar = "True" Background = "LightBlue" WindowStyle="ThreeDBorderWindow">
        <StackPanel Margin="0,0,0,7" HorizontalAlignment="Right" Width="208" >
            <StackPanel.Effect>
                <DropShadowEffect/>
            </StackPanel.Effect>
            <Label Content='Time remaining before Lock' VerticalAlignment="Center" HorizontalAlignment="Center" />
            <TextBox x:Name="TimeBox" IsReadOnly = "False" Height = "30"
        		TextWrapping="Wrap" VerticalScrollBarVisibility = "Auto" Text="0:00" HorizontalContentAlignment="Center" MaxWidth="100" MaxHeight="25"/>
            <StackPanel Orientation = 'Horizontal' Margin="10,0,0,0" Panel.ZIndex="5" Height="64">
                <Button x:Name = "OkBtn" Height = "50" Width = "65" Content = 'Lock Now' Background="Green" HorizontalAlignment="Right" VerticalAlignment="Center" >
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                </Button>
                <Button x:Name = "CancelBtn" Height = "50" Width = "65" Content = 'Cancel' Background="Red" Margin = "50,0,0,0" VerticalAlignment="Center" >
                    <Button.Effect>
                        <DropShadowEffect/>
                    </Button.Effect>
                </Button>
            </StackPanel>
        </StackPanel>
    </Window>
    "@
    # "
    $iCtr = 0
    $reader = (New-Object System.Xml.XmlNodeReader $xaml)
    $Window = [Windows.Markup.XamlReader]::Load($reader)
    
    #Connect to Controls
    $OKBtn = $Window.FindName('OkBtn')
    $Cancelbtn = $Window.FindName('CancelBtn')
    $TimeBox = $Window.FindName('TimeBox')
    #Event handlers             
    $Window.Add_SourceInitialized({
        # Before the window's even displayed ...            
        # We'll create a timer            
        $script:seconds =([timespan]0).Add('0:2')  # 2 minutes
        $script:timer = new-object System.Windows.Threading.DispatcherTimer
        # Which fire 1 time each second
        $timer.Interval = [TimeSpan]'0:0:1.0'
        # And will invoke the $updateBlock          
        $timer.Add_Tick.Invoke($UpDateBlock)
        # Now start the timer running            
        $timer.Start()
        if ($timer.IsEnabled -eq $false) {
            write-warning "Timer didn't start"
        }
    })
    
    $OKBtn.Add_Click({
        Write-Warning "Locking Now"
       # Close-Form
    })
    
    $CancelBtn.Add_Click({
        Close-Form
    })
    
    $UpDateBlock = ({
        $script:seconds= $script:seconds.Subtract('0:0:1')
        
        $Timebox.Text=$seconds.ToString('mm\:ss')
        
        if($seconds -eq 0) {  Close-Form  }
    })
    
    $Window.ShowDialog() | Out-Null


    \_(ツ)_/



    • Edited by jrv Tuesday, May 26, 2015 3:04 PM
    Tuesday, May 26, 2015 3:03 PM
  • This. I've been trying to find something like this for months. Can't thank you enough!
    Thursday, July 2, 2015 7:08 AM