Moving Get-PowerShell from Word Press to Blog Engine .NET

If you happen to be one of the six people that read this blog on a regular basis, you will have noticed a few changes. I recently converted my blog from Word Press to BlogEngine.NET. There are a few reasons why I made the change. First, I wanted to start learning more about web development on .NET. Secondly, Microsoft just released a product called WebMatrix. WebMatrix is an app that allows a techy guy like me to start hacking and slashing at a web site and provides a vehicle for me to get into some ASP.NET code if I choose to do so. What’s great about WebMatrix is that it allows you to pull down templates and sites from a large list of great open source projects that you can use in your own web site. From this list I chose Blog Engine.NET.  This is where the fun begins.

My first problem was to figure out how to move content from my Word Press blog to my new Blog Engine.NET blog. Searching the Interwebs with Bingle, I came across a project on codeplex called BlogML. Blog ML is essentially a form of XML used specifically to transfer Blog data between different Blog Engines. Blog Engine .NET has native functionality to import a BlogML file. However, getting Word Press to export Blog ML was a bit of trick, until I found this Export Script.

Once I had the BlogML file, I needed to clean up the file a little bit. Luckily, the BlogML project has a XML Schema file that I was able to use to check the validity of the XML. There were about 10 errors in the exported file that I had to clean up.

So now I have a new web site with my content pulled in, but there is one big problem. I needed to be able to maintain my permalinks. Here’s where PowerShell came into action. By the way, this is what I love about PowerShell. It’s a complete and total Swiss Army knife. You can use it to do just about anything anywhere.

I needed to get a list of all my permalinks. So what I did was tweak my RSS feed on my old and new blog to list all of my blog entries. Then I used the System.Web.Client to download the XML and parse out the URL’s that I needed.

001
002
003
004
005
006
007
008
009
010
011
012

Function Get-RssLink {
param(

$url="http://www.get-powershell.com/syndication.axd" 
)

$web = New-Object System.Net.WebClient 
$rss = $web.downloadString($url) 
$cleaned = $rss -replace  '',"" 
$xml = [xml]$cleaned 
$xml.rss.channel.item | select link

}

 

Once I had this from the old and new blogs, I generated a CSV file that had two columns, OldURL and NewURL. Armed with this information, I started looking at a tool in IIS called URL Rewrite 2.0. My blog is hosted at Cytanium. One thing that is really cool about them is that you can manage your Web Site directly using IIS Manager. Looking at my CSV file, there was an obvious basic pattern and I looked at using RegEx in URL Rewrite.  This worked for a few of my PermaLinks but I quickly found out that there were many more exceptions than rules in how the URL’s were translated. What I ended up doing was creating a rule for each permalink. Sure this may not be the most optimal situation, but its not like I am running Amazon.com.

However, I needed to be able to create a good chunk of URL Rewrite Rules. Again, I busted out my trusty old Swiss Army Knife – aka PowerShell. I actually found out the IIS Manager can generate scripts for you, but it generates C# and  JavaScript. Now these are nice languages but not ideal for IT Admins. I took the liberty of converting the generated C# to PowerShell.

Here’s what I came up with:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046

Function Add-UrlRewriteRule {
param(

$name,
$matchUrl,
$actionType,
$actionUrl ,
$actionRedirectType = "Found"
)


$serverManager = new-object Microsoft.Web.Administration.ServerManager
$config = $serverManager.GetWebConfiguration("blog")
$rulesSection = $config.GetSection("system.webServer/rewrite/rules")
$rulesCollection = $rulesSection.GetCollection()

$ruleElement = $rulesCollection.CreateElement("rule")
$ruleElement["name"] = 
$name
$ruleElement
["stopProcessing"] = 
$true

$matchElement
 = $ruleElement.GetChildElement("match")
$matchElement["url"] = 
$matchUrl

$actionElement
 = $ruleElement.GetChildElement("action")
$actionElement["type"] = 
$actionType
$actionElement
["redirectType"] = 
$actionRedirectType
$actionElement
["url"] = 
$actionUrl
$rulesCollection
.Add($ruleElement)

$serverManager.CommitChanges
()
}



$maps = import-csv "d:\Users\My Documents\UrlRewriteMapping.csv"


foreach ($map in $maps ) {
        Add-UrlRewriteRule -name $map.old.trim() `
                            -matchUrl $map.old.trim() `
                            -actionUrl $map.new.trim() `
                            -actionType "Redirect"

                    }
          
       


 

Once I had my URL Rewrites working, I was pretty much ready to go. All the basic functionality that I need is up and running now. If there are any quirks, please send any feedback via my Contact Page.

Search TechNet Script Center Forum for Unanswered PowerShell Questions

I wanted a quick and easy way to search the TechNet Script Center forums for all questions that had the word “PowerShell” in either the title or in the question itself. Here is what I came up with:

001
002
003
004
005
006
007
008
009
010
011

Function Get-ScriptCenterUnanswered {
$url = 
"http://social.technet.microsoft.com/Forums/en/ITCG/threads?outputAs=rss&filter=unanswered"
$web
 = New-Object System.Net.WebClient
$rss = $web.downloadString($url)
$cleaned = $rss -replace  '',
""
$xml
 = [xml]
$cleaned
$xml
.rss.channel.item | ? {
        ($_.Title -like "*powershell*") -or ($_.Description -like "*powershell*")
 
       
} | fl title,link
}

You can use a filter to get only the unanswered questions. Once I pulled those down, I found that it was giving me some odd characters at the beginning of the feed. I just used the –replace operator to get rid of them. Once I did that, I can convert to XML and treat the output as an object and use the where-object cmdlet to filter the output based on my criteria.

I slapped this together in about 10 minutes so this is not very reusable – but I thought I would share.

-Andy

Search TechNet Script Center Forum for Unanswered PowerShell Questions

I wanted a quick and easy way to search the TechNet Script Center forums for all questions that had the word “PowerShell” in either the title or in the question itself. Here is what I came up with:

001
002
003
004
005
006
007
008
009
010
011
Function Get-ScriptCenterUnanswered {
$url = 
"http://social.technet.microsoft.com/Forums/en/ITCG/threads?outputAs=rss&filter=unanswered"
$web
 = New-Object System.Net.WebClient
$rss = $web.downloadString($url)
$cleaned = $rss -replace  '',
""
$xml
 = [xml]
$cleaned
$xml
.rss.channel.item | ? {
        ($_.Title -like "*powershell*") -or ($_.Description -like "*powershell*")
 
       
} | fl title,link
}

You can use a filter to get only the unanswered questions. Once I pulled those down, I found that it was giving me some odd characters at the beginning of the feed. I just used the –replace operator to get rid of them. Once I did that, I can convert to XML and treat the output as an object and use the where-object cmdlet to filter the output based on my criteria.

I slapped this together in about 10 minutes so this is not very reusable – but I thought I would share.

-Andy

Scripting Games 2011

I am very excited about the upcoming Scripting Games this year. This is always a great opportunity for people to learn an incredible amount. If you are a beginner, this is a great place to start learning. If you’ve scripted yourself out of some deep dark holes, it’s a great opportunity to learn from other top notch folks and to also share your expertise. Also, I get to be one of the judges this year. I am really looking forward to reviewing scripts and seeing all the great solutions that ya’ll are going to come up with!  Hope to see you there !

 

 

ScriptingGames

It's what's on the inside that counts

Have you ever ran a PowerShell Cmdlet, looked at the properties and want do something with one of those properties like sort or group the output and have it fail? This has happened to me a few times. One example of this was with the NetApp PowerShell Toolkit.

I was looking at snapshots and wanted to sort by their Created date.Notice that there is a Created column in the output

image

Looks good, but when I try to sort by Created I get the same output as when I sort by “foo” (This is not a good thing)

image

It turns out “Created”, just like “foo”, is not a real property contained in the SnapShot objects. Lets see what is really there. There are a couple ways you can see what’s really going on. First, you can use get-member

image

Get-member tells us that there are a couple properties, AccessTime and AccessTimeDT that could be useful. From this I can infer that Created is somehow related to AccessTimeDT. But how and why is the real question.

An author of a PowerShell module can create a xml file that tells PowerShell how to display data in the console. If we go and look at the formatting file in the NetApp toolkit, we find that Created is mapped to the AccessDT property for SnapMirror objects.

image

So what’s this mean for you as a person using PowerShell. If Sorting or grouping by a property is not working, make sure that property is real. You can use get-member or go hacking through the format.ps1xml file for that particular module.

What does this mean for PowerShell Module authors? I would say be very careful of how you present data to end users. My humble suggestion is to use types.ps1xml file and create script properties and have those properties exposed to end users using the format file. This way, we can sort, group, and filter by the properties we expect to be there.