September 2nd, 2009

Hey, Scripting Guy! Can Windows PowerShell Alleviate My Need to Type Dates?

Share this post:

Hey, Scripting Guy! Question

Hey, Scripting Guy! I hate typing dates. There are several ways of typing dates, and they are all a pain. I do not like having to type the numbers and the whacks, and I do not like having to spell out month names, or attempting to remember if it is month first or day first. I like scripting, but I also like pointing and clicking. Is there something you can do for me?

— RS

Hey, Scripting Guy! Answer

Hello RS,

Microsoft Scripting Guy Ed Wilson here. I am glad you took the time to send an e-mail to scripter@microsoft.com because today I am in virtual meetings for 9 hours! I love meetings because I work from home, and I do not get to interact with Microsoftees too often unless I head to the office (a couple hour trek), am on campus in Redmond, speak at a conference such as Tech∙Ed or TechReady, or attend a virtual meeting. Of course, a Scripting Guy cannot spend all of his time in meetings, but he can always try.

Interestingly enough, when I was teaching my VBScript class at the Microsoft office in Sao Paulo, Brazil, one of my friends told me they were having problems getting people to attend meetings. He had however come up with the solution…Meeting Miles. You get 1 meeting mile for every hour you spend in a meeting (kind of like airline miles). At the end of the month, you can redeem your meeting miles for rewards and for prizes. You could even offer to attend meetings for other people to accrue meeting miles more rapidly. Great idea. I would be able to fly to Hawaii for free twice a year, if we implemented that in my organization.

I have gotten pretty good at multitasking (but that is the good thing about having a Scripting Wife who reads all of my Hey, Scripting Guy! articles and Craig who edits all my Hey, Scripting Guy! articles), but at times I do get confused and errors of both omission and commission are ultimately mine.

RS, I took the opportunity to write the Get-DatePickerFunction.ps1 script for you. The DatePicker will definitely solve your date issues by alleviating your need for typing dates. The full Get-DatePickerFunction.ps1 script is seen here.

Get-DatePickerFunction.ps1

Function Get-DatePicker
{  
 [System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”) |
 Out-Null
 
 $WinForm = New-Object Windows.Forms.Form  
 $WinForm.text = “DatePicker Control”  
 $WinForm.Size = New-Object Drawing.Size(205,55)

 $DatePicker = New-Object System.Windows.Forms.DateTimePicker  
 #$DatePicker.Format = [windows.forms.datetimepickerFormat]::custom
 #$DatePicker.CustomFormat = “MM-dd-yyyy”
 $WinForm.Controls.Add($DatePicker)  
 
 $WinForm.Add_Shown($WinForm.Activate()) 
 $WinForm.showdialog() | Out-Null 
 $DatePicker.value
} #end function Get-DatePicker

# *** Entry point to script ***

# Get-EventLog -LogName application -After [datetime](Get-Datepicker) # Windows PowerShell 2.0 call
# wps 1.0 version of call
$dte = [datetime](Get-DatePicker)
Get-EventLog -LogName application |
Where-Object { $_.timeWritten -gt $dte }

When the Get-DatePickerFunction.ps1 script runs, the very small dialog box seen here appears:

Image of dialog box that appears when script is run 

By keeping the dialog box small and unobtrusive, it makes the control easy to use. To use the control, you click the drop-down arrow on the far right of the control. When you do, a calendar that displays the current month appears. (Full disclosure: This post was written in August, so this did display the current month when I was writing this post.) This is seen here:

Image of calendar displaying current month

When you pick a date from the calendar, the selected date that is displayed in the Windows form will change. This is seen here:

Image of the selected date changing

Once you click the Close button in the upper right corner, the date is submitted back to the script. Simplicity, elegance, and refinement in a small, easy-to-reuse function.

The Get-DatePickerFunction.ps1 script begins by creating a function named Get-DatePicker. This function does not accept any parameters. To create the Get-DatePicker function, you only need to use the Function keyword and specify the name of the function. The function then opens a script block by using the opening curly brackets. This is seen here:

Function Get-DatePicker
{  

Now you will need to load the System.Windows.Forms .NET Framework assembly. This assembly is required for Windows PowerShell to provide access to the .NET Framework classes in the System.Windows.Forms .NET Framework namespace. By default the System.Windows.Forms assembly is not loaded and the classes from the System.Windows.Forms .NET namespace are not available. Many of the graphical classes that Windows PowerShell can use reside in the System.Windows.Forms namespace (but not all of them). The use of the LoadWithPartialName static method from the System.Reflection.Assembly .NET Framework class was discussed yesterday.

In Windows PowerShell 2.0, you can use the Add-Type cmdlet to load the assembly. This is seen here:

Add-Type –AssemblyName System.windows.forms

The LoadWithPartialName static method works on both Windows PowerShell 2.0 and on Windows PowerShell 1.0. The resulting confirmation message from the command is piped to the Out-Null cmdlet to avoid cluttering the screen. This is seen here:

 [System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”) |
 Out-Null

A new instance of the .NET Framework Windows.Forms.Form class is created by using the New-Object cmdlet. The resulting object is stored in the $WinForm variable. The Windows.Forms.Form .NET Framework class is documented on MSDN, and it will be used to host the date picker control that you will create later.  The Form class is created here:

 $WinForm = New-Object Windows.Forms.Form  

You can assign any title you wish to for the Windows.Forms.Form by assigning a value for the text property. This is seen here:

 $WinForm.text = “DatePicker Control”  

After you have created the Windows.Forms.Form class, you will need to create an instance of the System.Drawing.Size structure. The System.Drawing.Size .NET Framework structure is used to store the width and the height of the rectangular dimensions of the Windows.Forms.Form. These dimensions are assigned to the Size property of the Form. The Size dimensions must be supplied as an instance of the System.Drawing.Size class. This is seen here:

 $WinForm.Size = New-Object Drawing.Size(205,55)

The previous .NET Framework classes are required for most Windows PowerShell projects that create graphical interfaces. To create a date picker, we will need to create an instance of the System.Windows.Forms.DateTimePicker control. The DateTimePicker class is documented on MSDN.

 $DatePicker = New-Object System.Windows.Forms.DateTimePicker  

After the DateTimePicker control has been created, it is added to the Controls collection of the Form class. Once the DateTimePicker control is added to the Controls collection, the Add_Shown method is used to add to the active Form. The ShowDialog method from the Windows.Forms.Form class is used to display the dialog. This is seen here:

$WinForm.Controls.Add($DatePicker)
$WinForm.Add_Shown($WinForm.Activate()) 
$WinForm.ShowDialog() | Out-Null 

Once the Form with the DateTimePicker control is displayed, the value that is returned is the date that is selected from the control. The DateTimePicker control value property returns an instance of a DateTime class. After the value is returned, the function ends:

 $DatePicker.value
} #end function Get-DatePicker

RS, we are now finished creating the Get-DatePicker function. How can we use it? Because it returns a System.DateTime structure, which is documented on MSDN, you can use it the same way you use any other date in Windows PowerShell. In Windows PowerShell 1.0, for example, you might want to use the Get-DatePicker function to allow you to choose the beginning date to peruse the event logs. In your code, you store the date that is returned from the Get-DatePicker function into a variable called $dte. You then use the Get-EventLog cmdlet to retrieve all of the events from the application log on your local computer. You next pipe the resulting event log entries to the Where-Object cmdlet that sorts through the events based upon a timeWritten property value that is greater than the date value stored in the $dte variable. This is seen here:

$dte = [datetime](Get-DatePicker)

Get-EventLog -LogName application |

Where-Object { $_.timeWritten -gt $dte }

The above command, which is at the bottom of the Get-DatePickerFunction.ps1 script, returns the event log entries seen here:

Image of event log entries returned

If you are running Windows PowerShell 2.0, it is even easier to search the event log (and it can also be targeted at a remote computer by using the –computername parameter) because there is an after parameter. This functionality serves two purposes. It filters at the log level instead of returning everything to Windows PowerShell to make the Where-Object do the work, and also it makes writing the script code easier. This simplified syntax is seen here:

Get-EventLog -LogName application -After [datetime](Get-Datepicker)

RS, we are taking a five-minute break from the meeting. I need to head downstairs and make some Earl Grey tea, grab an ANZAC biscuit, and get back upstairs so that I can jump back on the conference call. Thanks for a great question!

Join us tomorrow as Graphical Windows PowerShell Week continues. If you want to know what we will be discussing tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to scripter@microsoft.com or post on the Official Scripting Guys Forum. See you tomorrow. Until then, keep on scripting.


Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Author

0 comments

Discussion are closed.