Summary: Microsoft Scripting Guy Ed Wilson shows how to use Windows PowerShell to get a weather forecast from inside the Windows PowerShell ISE.

 

Microsoft Scripting Guy Ed Wilson here. It is amazing how quickly things change on the Internet. A couple of years ago I found a website that hosted several web services. It was really cool. Most of the services were easy to use and were well documented. Unfortunately, that site is rarely up any longer. In fact, it seems to be down more frequently than it is up. I began looking around for a more reliable web service to retrieve weather information, and I came across the United States National Weather Service's website. I figured they would be more reliable than the other web service I was using. This gave me an opportunity to re-write my old weather script, to return a Windows PowerShell object by using the Windows PowerShell V2 style of object creation (supply the properties in a hash table).

I ended up writing two versions of my script. The first is a traditional script, and the second is a script file that contains only the function itself. If I configure the function as a Windows PowerShell script, I have to add command line parameters to allow for flexibility. The Get-UsGovWeather.ps1 script is seen here.

Get-UsGovWeather.ps1

Param (

 $zip = 28201,

 $numberDays = 3

)

Function Get-UsGovWeather

{

 Param([string]$zip,

       [int]$numberDays

      )

$URI = "http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl"

$Proxy = New-WebServiceProxy -uri $URI -namespace WebServiceProxy

[xml]$latlon=$proxy.LatLonListZipCode($zip)

foreach($l in $latlon)

{

 $a = $l.dwml.latlonlist -split ","

 $lat = $a[0]

 $lon = $a[1]

 $sDate = get-date -UFormat %Y-%m-%d

 $format = "Item24hourly"

 [xml]$weather = $Proxy.NDFDgenByDay($lat,$lon,$sDate,$numberDays,$format)

 For($i = 0 ; $i -le $numberDays -1 ; $i ++)

 {

  New-Object psObject -Property @{

  "Date" = ((Get-Date).addDays($i)).tostring("MM/dd/yyyy") ;

  "maxTemp" = $weather.dwml.data.parameters.temperature[0].value[$i] ;

  "minTemp" = $weather.dwml.data.parameters.temperature[1].value[$i] ;

  "Summary" = $weather.dwml.data.parameters.weather."weather-conditions"[$i]."Weather-summary"}

 }

}

} #end function Get-UsGovWeather

 

# ***** Entry point to script ***

 

Get-UsGovWeather -zip $zip -numberDays $numberDays |

Format-Table -Property date, maxTemp, minTemp, Summary -AutoSize

 

Because I use default values for the command line parameters, the script can be run by dragging it to the Windows PowerShell console and pressing Enter. Of course, if you want to compare the weather from your home with that of another location, use the up arrow, and add the -zip parameter. To view the weather for more than the default three days, use the -numberdays parameter. The commands and the associated outputs are seen in the following figure.

 

Most of the time I will be using the Get-UsGovWeather function inside my Windows PowerShell ISE. Because the function returns an object, the output can be easily sorted and arranged by using Windows PowerShell cmdlets. The problem is that is too much work when all one wants to do is to get a quick weather forecast. The solution is twofold. First, I store the function in a .ps1 script file that is kept in my ISEProfileModule folder. The function is only the function code, without any default values and without any formatting. A good function returns a rich object that can be processed later as required. The behavior is like a Windows PowerShell cmdlet. The Get-UsGovWeather function is seen here.

Get-UsGovWeather

Function Get-UsGovWeather

{

 Param([string]$zip,

       [int]$numberDays

      )

$URI = "http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl"

$Proxy = New-WebServiceProxy -uri $URI -namespace WebServiceProxy

[xml]$latlon=$proxy.LatLonListZipCode($zip)

foreach($l in $latlon)

{

 $a = $l.dwml.latlonlist -split ","

 $lat = $a[0]

 $lon = $a[1]

 $sDate = get-date -UFormat %Y-%m-%d

 $format = "Item24hourly"

 [xml]$weather = $Proxy.NDFDgenByDay($lat,$lon,$sDate,$numberDays,$format)

 For($i = 0 ; $i -le $numberDays -1 ; $i ++)

 {

  New-Object psObject -Property @{

  "Date" = ((Get-Date).addDays($i)).tostring("MM/dd/yyyy") ;

  "maxTemp" = $weather.dwml.data.parameters.temperature[0].value[$i] ;

  "minTemp" = $weather.dwml.data.parameters.temperature[1].value[$i] ;

  "Summary" = $weather.dwml.data.parameters.weather."weather-conditions"[$i]."Weather-summary"}

 }

}

} #end function Get-UsGovWeather

 

This folder is seen in the following figure.

 

After the function is stored in my profile module location, I then create a short function in my Windows PowerShell ISE profile to display only the weather configuration I want. The function that I put in my Windows PowerShell ISE profile is seen here.

Function Get-MyWeather
{
. $moduleHome\iseProfileModule\Get-UsGovWeatherFunction.ps1
Get-UsGovWeather -zip 29745 -numberDays 3 |
Format-Table -Property date, maxTemp, minTemp, Summary -AutoSize
}

 

The Windows PowerShell ISE profile is seen in the following figure.

 

The cool thing is that the weather is now immediately available. I type get-MyWeather (actually I type get-my and press <tab> to retrieve the current weather. The output is shown in the following figure.

 

Well, that is about it for messing around with web services, and the Windows PowerShell ISE profile. Join me tomorrow as I begin talking about object member discovery. It should be a very good week.

 

I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson, Microsoft Scripting Guy