Reading IIS.NET Blogs with Powershell
Being a member of the IIS team, I often find myself checking blog posts to see what the members of the product team are blogging about. However, since Powershell came out, I find myself doing more and more work on my scripts. It's a bit annoying to have to jump out of Powershell to go read blog posts. As such, I've written a few quick scripts to help me read IIS.NET from my pretty blue shell. For those of you who are already familiar with powershell and don't want to read the long blog post, you can download my blog script from the DownloadCENTER: http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1387
Setting up your Powershell environment
To start, I've written a few supporting functions in my profile. These functions help me keep my scripts organized and, since I change my scripts quite often, it helps me to sign them as well.
First off, if you haven't created your own certificate for signing code, please go back and take a look at my first Powershell blog post that give you the details on how to do this.
Next, we need to add a few things to your Powershell profile. To open your Powershell profile from within Powershell, type:
PS > notepad $profile
First, I add a function to allow us to easily sign our scripts (assuming you have created a cert to sign them wth):
## Sign a file ##------------------------------------------- function global:Sign-Script ( [string] $file ) { $cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0] Set-AuthenticodeSignature $file $cert } set-alias -name sign -value sign-script
The next function is used to help me organize things. I have several scripts for various work environments. I like to organize them by function. So, I keep my IIS scripts in an "IIS" directory, my common scripts in a "common" directory and so on. Inside each of my script directories, I keep a "load.ps1" script that I can use to initialize any of my work environments. Lastly, I create a Powershell drive that matches the work environment name so I can get to my scripts easily. The function below does all the work for me.
## Create a Drive ##------------------------------------------- function global:New-Drive([string]$alias) { $path = (join-path -path $global:profhome -childpath $alias) if( !(Test-Path $path ) ) { ## Create the drive's directory if it doesn't exist new-item -path $global:profhome -name $alias -type directory } else { ## Execute the load script for this drive if one exists $loadscript = (join-path -path $path -childpath "load.ps1") if( Test-Path $loadscript) { $load = &$loadscript } } # Create the drive new-Psdrive -name $alias -scope global -Psprovider FileSystem -root $path }
Within my profile, I simply call this function and pass in an alias. When the function executes it will create a directory with the alias name, if it doesn't exist already. If the directory does exist, it will check for the load.ps1 file inside that path and execute it. Lastly, it will create powershell drive. I have the following calls added to my profile below:
## Custom PS Drives ##------------------------------------------- New-Drive -alias "common" New-Drive -alias "iis"
Go ahead and save your profile now and type these commands:
PS > Set-ExecutionPolicy Unrestricted
PS > &$profile
PS > Sign $profile
PS > Set-ExecutionPolicy AllSigned
The first command sets Powershell into unrestricted mode. This is because we need to execute the profile script and it hasn't been signed yet. The next command executes the profile. The third command uses the "sign" function that our profile script loaded. Since our profile is now signed, we can set our execution policy back to AllSigned. AllSigned means that Powershell will execute scripts as long as they are signed.
From this point on, we can make changes to our profile and simply call our sign function again before we close our Powershell instance. The next instance of powershell that is opened will have our changes.
Creating / Using Blog Functionality
Now that we have our environment set up, lets get to the blogging part. If you've set up your environment right, you can execute the following command:
PS > cd iis:
This command will put you in the iis scripts directory. Next, create a new blogs script by typing:
PS > notepad blogs.ps1
You'll be prompted if you want to create the file. Go ahead and say yes. Next, paste the following into the the notepad and save it:
## Sets up all custom feeds from feeds.txt ##--------------------------------------------------- function global:Import-Feed { if( $global:RssFeeds -eq $null ) { $global:RssFeeds = @{}; } $RssFeeds.Add( "iisblogs", "http://blogs.iis.net/rawmainfeed.aspx" ); $RssFeeds.Add( "iisdownloads", "http://www.iis.net/DownloadCENTER/all/rss.aspx" ); } Import-Feed ## Call Import-Feed so we are ready to go ## Gets a feed or lists available feeds ##--------------------------------------------------- function global:Get-Feed( [string] $name ) { if( $RssFeeds.ContainsKey( $name ) ) { return $RssFeeds[$name]; } else { Write-Host "The path requested does not exist"; Write-Output $RssFeeds; } } ## Gets IIS Blogs ##--------------------------------------------------- function global:Get-Blog([int]$index, [int]$last, [int]$first, [int]$open) { $url = (Get-Feed iisblogs) return (Get-RSS $url $index $last $first $open) } ## Gets a specific blog ##--------------------------------------------------- function global:Get-AuthorBlog([string]$creator) { Get-Blog | Where-Object {$_.creator -eq $creator} } ## Gets Downloads from IIS ##--------------------------------------------------- function global:Get-Download([int]$index, [int]$last, [int]$first, [int]$open) { $url = (Get-Feed iisdownloads) return (Get-RSS $url $index $last $first $open) } ## Gets a generic RSS Feed ##--------------------------------------------------- function global:Get-RSS([string]$url, [int]$index, [int]$last, [int]$first, [int]$open) { $feed = [xml](new-object System.Net.WebClient).DownloadString($url) if($index) { return $feed.rss.channel.item[$index] } if($open) { $ieaddr = $env:programfiles + "\internet explorer\iexplore.exe" return &(get-item $ieaddr) $feed.rss.channel.item[$open].link } if($last) { return ($feed.rss.channel.item | Select -last $last) } if($first) { return ($feed.rss.channel.item | Select -first $first) } return $feed.rss.channel.item }
Once you've saved this file, close it. We need to sign this script and execute it by typing:
PS IIS:> sign blogs.ps1
PS IIS:> ./blogs.ps1
Now lets start reading.
- Read all Blogs
PS iis:\> Get-Blog
- Read the last five blog posts
PS iis:\> Get-Blog -last 5
- Read the first five blog posts
PS iis:\> Get-Blog -first 5
- Read the 8th blog post
PS iis:\> Get-Blog -index 8
- Open the 12th blog post and open in Internet Explorer
PS iis:\> Get-Blog -open 12
- Read all blog posts by Bill Staples
PS iis:\> Get-AuthorBlog bills
- Read all items in DownloadCENTER
PS iis:\> Get-Download
- Get titles of all items in DownloadCENTER
PS iis:\> Get-Download | Select Title
Of course, all the laws of Powershell still apply, so I can still do fun stuff like like listing only the blog titles from my blog.
PS iis:\> Get-AuthorBlog TobinTitus | Select Title
I can do the same witht he raw blog output:
PS iis:\> Get-Blog -last 5 | Select pubDate, Creator, Title
Happy reading.