Timer
In this post I showed how to set a count down timer
http://msmvps.com/blogs/richardsiddaway/archive/2011/08/02/a-count-down-timer.aspx
but what if you want to go the other way i.e. see how long something takes
The count down function can be modified
Import-Module ShowUI function timegone { $ts = (Get-Date) - $start $time = $ts.ToString() -split "\." if ($ts.Hours -eq 0) { $time[0].Substring(3,5) } else { $time } } $start = Get-Date $windowAttributes = @{ WindowStartupLocation = "CenterScreen" SizeToContent = "WidthAndHeight" WindowStyle = "None" Background = "Transparent " On_MouseRightButtonDown = { Close-Control} On_MouseLeftButtonDown = { $_.Handled = $true;$window.DragMove() } On_Loaded = { Register-PowerShellCommand -ScriptBlock { $window.Content.Content = timegone } -Run -In "0:0:0.5" } } $labelAttributes = @{ Content = timegone FontFamily = "Impact, Arial" FontWeight = 800 FontSize = 30 } New-Window @windowAttributes -AllowsTransparency -Show { Label @labelAttributes -Name Clock -Foreground ( LinearGradientBrush $( GradientStop -Color Red -Offset 1 GradientStop -Color Orange -Offset 0.85 GradientStop -Color Yellow -Offset 0.7 GradientStop -Color Green -Offset 0.55 GradientStop -Color Blue -Offset 0.4 GradientStop -Color Indigo -Offset 0.2 GradientStop -Color Violet -Offset 0 ) ) }
The main change is that our starting point is now. We then get the current time, subtract our starting point and we have the elapsed time.
Display as before
A count down timer
Last month I started playing with WPF to show how a multi-coloured clock could be displayed on screen. This was picked up and an easier version was created by Doug Finke using the ShowUI module from codeplex http://showui.codeplex.com/.
Other links are here
http://msmvps.com/blogs/richardsiddaway/archive/2011/07/08/an-easier-clock.aspx
As well as wanting to know the time I often want to set a count down timer. I did a version of this ages ago using PowerGadgets but if you don’t have that then we can do something with show UI
Import-Module ShowUI function timeleft { $ts = $close - (Get-Date) $time = $ts.ToString() -split "\." $time[0].Substring(3,5) } $close = (Get-Date).AddMinutes(35) $windowAttributes = @{ WindowStartupLocation = "CenterScreen" SizeToContent = "WidthAndHeight" WindowStyle = "None" Background = "Transparent " On_MouseRightButtonDown = { Close-Control} On_MouseLeftButtonDown = { $_.Handled = $true;$window.DragMove() } On_Loaded = { Register-PowerShellCommand -ScriptBlock { $window.Content.Content = timeleft } -Run -In "0:0:0.5" } } $labelAttributes = @{ Content = timeleft FontFamily = "Impact, Arial" FontWeight = 800 FontSize = 90 } New-Window @windowAttributes -AllowsTransparency -Show { Label @labelAttributes -Name Clock -Foreground ( LinearGradientBrush $( GradientStop -Color Red -Offset 1 GradientStop -Color Orange -Offset 0.85 GradientStop -Color Yellow -Offset 0.7 GradientStop -Color Green -Offset 0.55 GradientStop -Color Blue -Offset 0.4 GradientStop -Color Indigo -Offset 0.2 GradientStop -Color Violet -Offset 0 ) ) }
All I changed was to point the Content to the timeleft function instead of get-date. The function takes the closing time – in this case 35 minute from starting and subtracts the current datetime (from get-date). The resultant timespan is converted to a string and split at the millisecond point. The minutes and seconds are extracted as a substring to display
By the way – anyone noticed the deliberate(?) mistake with the colours
Reminders
If I am working on my home machine I don’t necessarily have Outlook or any other application that gives me calendaring capability open. There are times when I need a simple reminder to do something. For some reason I always seem to have PowerShell open so I thought of using the eventing system to give me a reminder. I could also do this via the task scheduler functions in the PowerShellPack (Windows 7 Resource kit) which I’ll look at another day.
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 |
function Set-Alarm {
param ( [datetime]$time, [string]$msg = "Alert Issued" ) $now = Get-Date |
My function accepts a time and a message
Set-Alarm "18:47" "Test1"
It then gets the current time, compares the two times and assuming the alert is to be issued in the future creates a Timespan object be subtracting the times as shown.
We can then create .NET timer object and set the interval to the total number of milliseconds in our timespan. We only want it to fire once so we set autoReset to false and then enable the timer.
I then create a global variable containing the powershell start up commands. In this case I want it to start in Single Thread mode so I can use the WPF classes. I call a script when PowerShell starts and pass the script the message. Note the number of quotes around the $msg variable – this is to make sure the string passed to invoke-expression is correct. This is messy but needed.
The $act variable has to be global because the action scriptblock for Register-objectevent isn’t evaluated until the event fires. If $act is in the script scope it won’t be found and the event won’t fire correctly.
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 |
param (
[string]$msg = "Testing", [string]$title = "Alert" ) ## load WPF assemblies Add-Type –assemblyName PresentationFramework Add-Type –assemblyName PresentationCore Add-Type –assemblyName WindowsBase ## create a window ## display window |
The script loads the WPF assemblies I need and then creates a window and writes out the message thats been passed in.
This is a bit messy with having to create a global variable but I can’t think of a simpler way to access the variable in the scriptblock for Register-objectevent. The other issue is that I can only have a single event of this type defined because of the variable. I would need to create the variable with a random name and create another string of the Register-objectevent invocation.