<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Aaron Lerch &#187; powershell</title>
	<atom:link href="http://www.aaronlerch.com/blog/category/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.aaronlerch.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 10 Mar 2010 12:45:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Refactoring C# with PowerShell</title>
		<link>http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/</link>
		<comments>http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/#comments</comments>
		<pubDate>Fri, 04 Jan 2008 18:06:07 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/</guid>
		<description><![CDATA[Visual Studio 2005 and 2008 have built-in support for refactoring code, including renaming namespaces, classes, variables, and more. Add-ins like Resharper also have support for refactoring by renaming. These tools work great, and have good integration into the Visual Studio IDE, for example being able to preview each change and exclude false positive matches. I [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.aaronlerch.com/files/blog/RefactoringCwithPowerShell_E201/image.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="240" alt="image" src="http://aaronlerch.com.s3.amazonaws.com/images/refactoring_with_powershell_screenshot_thumb.png" width="222" align="right" border="0" /></a>Visual Studio 2005 and 2008 have built-in <a href="http://msdn2.microsoft.com/en-us/library/ms379618(VS.80).aspx#vs05_refac_topic8">support for refactoring code</a>, including renaming namespaces, classes, variables, and more. Add-ins like <a href="http://www.jetbrains.com/resharper/">Resharper</a> also have support for <a href="http://www.jetbrains.com/resharper/features/code_refactoring.html#Rename_Symbol_full">refactoring by renaming</a>. These tools work great, and have good integration into the Visual Studio IDE, for example being able to preview each change and exclude false positive matches. I know many people swear by Resharper in particular (for more features than the refactoring alone).</p>
<p>Unfortunately all of these tools are restricted in one normally insignificant way: they only operate on the currently loaded project(s). For most software this really is insignificant. The entire application can be loaded into the IDE all at once. Sometimes, though, it is a problem&#8211;usually when there&#8217;s another problem at play: <a href="http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html">code &quot;bloat&quot;</a> (<a href="http://www.moserware.com/2007/12/how-legacy-of-dead-mathematician-can.html">via Jeff</a>).</p>
<p>If you&#8217;ve ever changed a namespace and wanted to simply push the change into every code file in an entire directory branch, PowerShell comes to our rescue with it&#8217;s search-and-replace capabilities. I wrote the following &quot;Move-Namespace&quot; function to do just that.</p>
<p>Invoke the function like so: &quot;Move-Namespace *.cs &quot;[current namespace]&quot; &quot;[current class name]&quot; &quot;[new namespace]&quot;.</p>
<p>After it completes, any explicit reference will be changed, and any implicit references (using traditional &quot;using [namespace];&quot; statements) will have a new &quot;using [new namespace];&quot; line inserted after the last existing using statement.</p>
<p>Let&#8217;s hope you don&#8217;t have a code base that requires this function. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  But if you do, I hope it helps!</p>
<p><em>Note that this function relies on my &quot;Replace-String&quot; function, </em><a href="http://www.aaronlerch.com/blog/2007/03/28/powershell-replace-string-function/"><em>found here</em></a><em>.</em></p>
<pre class="csharpcode"><span class="kwrd">function</span> Move-Namespace(
    $includes = $(<span class="kwrd">throw</span> <span class="str">'Specify a file filter to use'</span>),
    $oldNamespace = $(<span class="kwrd">throw</span> <span class="str">'The namespace to replace - i.e. MyCompany.Product'</span>),
    $className = $(<span class="kwrd">throw</span> <span class="str">'The class name to search for - i.e. MyClass'</span>),
    $newNamespace = $(<span class="kwrd">throw</span> <span class="str">'The new namespace to add - i.e. MyCompany.Product.Feature'</span>))
{
    <span class="rem"># Look for cases of $className</span>
    <span class="rem"># or $oldNamespace.$className</span>
    <span class="rem"># and replace as necessary</span>

    <span class="rem"># First check for assumed &quot;using&quot; statements, and add the using statement</span>
    $results = @{}
    $files = get-childitem -r -i $includes | select-string <span class="str">&quot;(?&lt;!$oldNamespace\.)\b$className\b&quot;</span> -list |% { $_.Path }
    select-string <span class="str">&quot;^using.*;&quot;</span> -path $files | group-object Path | select-object Name, @{Expression={ ($_.Group | measure-object -property LineNumber -max).Maximum }; Name=<span class="str">&quot;LastUsingStatement&quot;</span> } |% { $results[$_.Name] = $_.LastUsingStatement }
    <span class="kwrd">foreach</span> ($key <span class="kwrd">in</span> $results.keys)
    {
      $processFile = $true
      $lastUsingIndex = $results[$key]
      $fileContents = get-content $key
      <span class="rem"># look for existing using statement and cancel processing this file</span>
      <span class="kwrd">for</span> ($i = 0; $i <span class="preproc">-lt</span> $lastUsingIndex; $i++)
      {
        <span class="kwrd">if</span> ($fileContents[$i] <span class="preproc">-match</span> <span class="str">&quot;using $newNamespace;&quot;</span>)
        {
          <span class="rem"># this file already has the correct using statement, stop processing</span>
          Write-Warning <span class="str">&quot;File $key already has the required using statement, ignoring&quot;</span>
          $processFile = $false
          <span class="kwrd">break</span>;
        }
      }

      <span class="kwrd">if</span> ($processFile)
      {
        $newContents = $fileContents[0..($lastUsingIndex-1)] + <span class="str">&quot;using $newNamespace;&quot;</span> + $fileContents[$lastUsingIndex..$fileContents.Length]
        set-content -path $key -value $newContents
        Write-Host <span class="str">&quot;Successfully updated file $key&quot;</span> -foregroundcolor Green
      }
    }

    <span class="rem"># Next check for explicit references</span>
    replace-string <span class="str">&quot;\b$oldNamespace\.$className\b&quot;</span> <span class="str">&quot;$newNamespace.$className&quot;</span> $includes
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Symbol Store Manager &#8211; open source and a beta release</title>
		<link>http://www.aaronlerch.com/blog/2007/12/30/symbol-store-manager-open-source-and-a-beta-release/</link>
		<comments>http://www.aaronlerch.com/blog/2007/12/30/symbol-store-manager-open-source-and-a-beta-release/#comments</comments>
		<pubDate>Sun, 30 Dec 2007 22:18:04 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[Symbol Store Manager]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/12/30/symbol-store-manager-open-source-and-a-beta-release/</guid>
		<description><![CDATA[A while ago I &#34;released&#34; the Symbol Server Transaction Manager. It was a binaries-only, quick-and-dirty GUI wrapper utility I wrote on top of the symstore.exe command-line tool, at the prompting of John Robbins. If you&#8217;re not familiar with Symbol Servers, symstore.exe, or John Robbins, get up to speed by reading John&#8217;s still-relevant 2002 Bugslayer article [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I &quot;released&quot; the <a href="http://www.aaronlerch.com/blog/2007/09/01/symbol-server-transaction-manager/">Symbol Server Transaction Manager</a>. It was a binaries-only, quick-and-dirty GUI wrapper utility I wrote on top of the symstore.exe command-line tool, at the prompting of <a href="http://www.wintellect.com/cs/blogs/jrobbins/default.aspx">John Robbins</a>. If you&#8217;re not familiar with Symbol Servers, <a href="http://msdn2.microsoft.com/en-us/library/ms681417(VS.85).aspx">symstore.exe</a>, or John Robbins, get up to speed by reading John&#8217;s <a href="http://msdn.microsoft.com/msdnmag/issues/02/06/Bugslayer/">still-relevant 2002 Bugslayer article</a> in MSDN magazine, or taking his <a href="http://wintellect.com/CourseDetail.aspx?Course=30">Mastering .NET Debugging</a> class.</p>
<p>I got some good feedback on the utility, along with some additional feature requests that ran outside the bounds of what the symstore utility offered. That lead me to upgrade my project to include a full-fledged (well, almost) symstore <em>replacement</em>, plus the GUI manager utility.</p>
<p>I&#8217;ve published the project tonight on CodePlex as &quot;<a href="http://www.codeplex.com/PSSymbolStore">PSSymbolStore</a>&quot;, and I&#8217;ve released the initial 0.1 beta release.</p>
<p>So what did I add and what did I change?</p>
<h5>PowerShell</h5>
<p>PSSymbolStore is now founded on a set of PowerShell cmdlets that replace and extend symstore&#8217;s functionality. (<em>Almost</em>: I need some feedback about a few symstore features and how they might work in the PowerShell world. If you&#8217;re a symstore wizard &#8211; ahem, John &#8211; <a href="mailto:aaronlerch@gmail.com">drop me a line</a>.) The initial release includes the following cmdlets, along with full help, including examples:</p>
<ul>
<li><b>Add-Symbols</b> &#8211; Adds symbols to the symbol store </li>
<li><b>Get-Transaction</b> &#8211; Retrieves some or all of the transactions from a symbol store </li>
<li><b>Remove-Transaction</b> &#8211; Deletes transaction(s) from a symbol store </li>
<li><b>Lock-Transaction</b> &#8211; Locks transaction(s), preventing them from being deleted with the Remove-Transaction cmdlet </li>
<li><b>Unlock-Transaction</b> &#8211; Unlocks transaction(s), allowing them to be deleted with the Remove-Transaction cmdlet </li>
</ul>
<h5>Symbol Store Manager</h5>
<p>The Symbol Store Manager (formerly &quot;Symbol Server Transaction Manager&quot;) is basically the same from a UI perspective, but has been massively gutted. The internal changes (MVP pattern, PowerShell hosting, etc.) are all for the better as they fully enable unit testing, which is coming in a future release. I&#8217;m looking for feedback on the UI &#8211; what I can improve, etc. It&#8217;s really basic right now. I had started adding a search feature using <a href="http://www.shuffletext.com/Highlight/Default.aspx">ShuffleText&#8217;s Highlight</a> fuzzy search library, but didn&#8217;t have time to finish it the way I wanted so I&#8217;ve pushed it out to a future release.</p>
<p><a href="http://www.aaronlerch.com/files/blog/SymbolStoreManageropensourceandabetarele_13996/SymbolStoreManager.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="302" alt="Symbol Store Manager" src="http://aaronlerch.com.s3.amazonaws.com/images/SymbolStoreManager_thumb.png" width="500" border="0" /></a> </p>
<h5>vNext</h5>
<p>So what&#8217;s coming next? I&#8217;ve already mentioned unit tests and searching. I&#8217;m also kicking around some UI enhancements. Aside from those features, and finishing up some &quot;paperwork&quot; like installs, I don&#8217;t currently have a strong feature list. If you have ideas, please either post them as a comment here, or even better on the <a href="http://www.codeplex.com/PSSymbolStore">codeplex project site</a>. For example: would this be more useful as an MMC snap-in instead of a standalone application?</p>
<p><a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx">Download PowerShell</a> if you haven&#8217;t already, and give <a href="https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=PSSymbolStore&amp;ReleaseId=9441">PSSymbolStore 0.1 Beta</a> a whirl &#8211; I hope it&#8217;s useful!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/12/30/symbol-store-manager-open-source-and-a-beta-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cmdlets vs. APIs</title>
		<link>http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/</link>
		<comments>http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 02:53:29 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[powershell]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/</guid>
		<description><![CDATA[I&#8217;ve been working on a set of Powershell Cmdlets to fully replace the symstore.exe utility that is included with the Debugging Tools for Windows. (To be released as open source when I&#8217;m done.) When I think about writing Cmdlets, I tend to think that the best approach is to create an API and then wrap [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a set of Powershell Cmdlets to fully replace the symstore.exe utility that is included with the <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">Debugging Tools for Windows</a>. (To be released as open source when I&#8217;m done.) When I think about writing Cmdlets, I tend to think that the best approach is to create an API and then wrap it in a Cmdlet implementation. That enables the best of both worlds&#8211;someone can write an application that uses the API, or people can interact with the Cmdlets via the command line or in an application hosting a Powershell runspace.</p>
<p>But I think I&#8217;ve been very wrong. A while back Jeffrey Snover posted a great &#8220;core dump&#8221; of <a href="http://blogs.msdn.com/powershell/archive/2007/07/03/cmdlets-vs-apis.aspx">cmdlets vs. APIs</a>. He makes some good points, but even after reading it (back when he first posted it) I still thought that API + Cmdlet was the best approach. Experience has changed my mind. Here are, in my opinion, the most important points from his list (paraphrased).</p>
<p><strong>Error handling.</strong> An API can throw exceptions, but a Cmdlet can have terminating and non-terminating errors. With Cmdlets users can easily control the behavior when a non-terminating error occurs as well as get access to the collection of troublemaker objects.</p>
<p><strong>-WhatIf, -Confirm, and -Verbose support.</strong> There simply isn&#8217;t an easy way to have an API support a -WhatIf type of operation, while remaining a good API.</p>
<p><strong>Pipelines and wildcards.</strong> Wildcard support needs to be implemented on a per-API basis, making it a time-consuming (and possibly difficult) task. Working with &#8220;pipelines&#8221; requires specific coding by the user of the API.</p>
<p>The common thread between those three points is that an API simply can&#8217;t provide those services independent of Powershell. You really can&#8217;t create an API and wrap it in a Cmdlet. (If you have a choice.) If my &#8220;Remove-Foo&#8221; Cmdlet simply wraps &#8220;foo.Delete()&#8221;, &#8220;foo.Delete()&#8221; can&#8217;t make use of advanced error handling, or conditional processing (ala &#8220;-WhatIf&#8221; or &#8220;-Confirm&#8221;), or pipeline or wildcard support.</p>
<p>Because applications can host a Powershell runspace, any argument for an API goes away. Your Cmdlets <em>are</em> an API that developers can write code against. The thing that still gets me about this, though, is the verbose code it requires to exercise a Cmdlet&#8217;s &#8220;API&#8221;. Apparently Powershell V2 is going to <a href="http://blogs.msdn.com/powershell/archive/2007/11/06/what-s-new-in-ctp-of-powershell-2-0.aspx">help simplify the runspace hosting story</a>. Maybe that&#8217;s enough to knock the final leg out of my leaning towards an API? Once I finish my work, perhaps I&#8217;ll update the symstore SnapIn for V2 &#8211; in the meantime, I&#8217;d like to release them in a state that people could actually use them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerShell v2.0 CTP</title>
		<link>http://www.aaronlerch.com/blog/2007/11/02/powershell-v20-ctp/</link>
		<comments>http://www.aaronlerch.com/blog/2007/11/02/powershell-v20-ctp/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 17:54:43 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/11/02/powershell-v20-ctp/</guid>
		<description><![CDATA[This is one of the few times (I hope) that I echo what probably a bunch of bloggers are, or will be, posting. I just saw that Jeffrey Snover announced an upcoming CTP of Windows PowerShell.
I&#8217;m excited to download it and check it out &#8211; though as a non-admin I don&#8217;t do enough with PowerShell [...]]]></description>
			<content:encoded><![CDATA[<p>This is one of the few times (I hope) that I echo what probably a bunch of bloggers are, or will be, posting. I just saw that <a href="http://blogs.msdn.com/powershell/archive/2007/11/02/ctp-watch-this-space.aspx">Jeffrey Snover announced an upcoming CTP of Windows PowerShell</a>.</p>
<p>I&#8217;m excited to download it and check it out &#8211; though as a non-admin I don&#8217;t do enough with PowerShell to be as excited about what seems to be the killer feature: Remoting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/11/02/powershell-v20-ctp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Create a directory &quot;Table of Contents&quot; with PowerShell</title>
		<link>http://www.aaronlerch.com/blog/2007/11/02/create-a-directory-table-of-contents-with-powershell/</link>
		<comments>http://www.aaronlerch.com/blog/2007/11/02/create-a-directory-table-of-contents-with-powershell/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 17:48:58 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/11/02/create-a-directory-table-of-contents-with-powershell/</guid>
		<description><![CDATA[My friend job (IT at a major pharmaceutical company) has him dealing with tons and tons of documents. He periodically has to burn large directory trees of documents to some media (CD/DVD). He asked me about a way he could easily create an HTML-based &#8220;table of contents&#8221; (TOC) for the entire burned media &#8211; like [...]]]></description>
			<content:encoded><![CDATA[<p>My friend job (IT at a major pharmaceutical company) has him dealing with tons and tons of documents. He periodically has to burn large directory trees of documents to some media (CD/DVD). He asked me about a way he could easily create an HTML-based &#8220;table of contents&#8221; (TOC) for the entire burned media &#8211; like an index.html file which would live at the root that hyperlinked all the files. My friend is a really smart guy, so I assumed that he actually needed this and it wasn&#8217;t a symptom of the real problem. PowerShell is a great candidate for just such a task, and it was a good excuse to get him to install it. It was really fast and easy to write a New-TableOfContents function just by thinking through the problem, almost &#8220;out loud&#8221; and writing my thoughts in PowerShell-ese.</p>
<pre class="csharpcode"><span class="kwrd">function</span> New-TableOfContents($path)
{
    <span class="rem"># Verify the path exists and retrieve the official full path</span>
    $root = (Get-Item $path).FullName

    Write-Output <span class="str">"&lt;html&gt;&lt;head&gt;&lt;title&gt;Table of Contents&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;h1&gt;Table of Contents&lt;/h1&gt;"</span>
    <span class="rem"># For each child item that's not a directory, create a link containing the relative path</span>
    Get-ChildItem $root -recurse | where { $_.PSIsContainer <span class="preproc">-eq</span> $false } |% {
        <span class="rem"># Strip the root out of the path name (including the trailing slash)</span>
        <span class="rem"># in order to create a hyperlink that can be used from any location</span>
        $relPath = $_.FullName.Remove(0, $root.Length + 1)
        <span class="rem"># Write the link out - this is where you could get fancier with what you output</span>
        <span class="rem"># For example, you could include the last modified date/time, etc.</span>
        Write-Output <span class="str">"&lt;a href=`"</span>$relPath`<span class="str">"&gt;$relPath&lt;/a&gt;&lt;br /&gt;"</span>
    }
    Write-Output <span class="str">"&lt;/body&gt;&lt;/html&gt;"</span>
}</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<p>This function will output the html to the pipeline, which doesn&#8217;t do us much good unless you direct it somewhere useful, like a file. While it&#8217;s tempting to make a function like this output the results to a file (replace &#8220;Write-Output&#8221; with &#8220;Out-File -append&#8221;), I&#8217;m of the opinion that functions should return their results to the pipeline whenever possible, allowing the user to decide what to do with it. In this case, it&#8217;s as simple as this:</p>
<pre class="csharpcode">PS:&gt; New-TableOfContents <span class="str">"C:\\Doc Tree"</span> | Out-File <span class="str">"C:\\Doc Tree\\index.html"</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<p>It&#8217;s simple, but effective. And because PowerShell passes objects around instead of strings, you can easily include more information in the hyperlink, or create a table instead of a list, or sort, or whatever. The sky&#8217;s the limit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/11/02/create-a-directory-table-of-contents-with-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Save I3DIR Files to CSV with PowerShell</title>
		<link>http://www.aaronlerch.com/blog/2007/09/18/save-i3dir-files-to-csv-with-powershell/</link>
		<comments>http://www.aaronlerch.com/blog/2007/09/18/save-i3dir-files-to-csv-with-powershell/#comments</comments>
		<pubDate>Wed, 19 Sep 2007 03:10:53 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[interactive intelligence]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/09/18/save-i3dir-files-to-csv-with-powershell/</guid>
		<description><![CDATA[Here&#8217;s a post that will apply to exactly 0.3 people out there. But I think it&#8217;s a great story of how PowerShell came to the rescue for one of our customers.
A support request came in this morning for a customer who had accidentally deleted the source for one of their data sources. (Background: our client [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a post that will apply to exactly 0.3 people out there. But I think it&#8217;s a great story of how PowerShell came to the rescue for one of our customers.</p>
<p>A support request came in this morning for a customer who had accidentally deleted the source for one of their data sources. (Background: our client software displays directories&#8211;sort of like detailed address books&#8211;that can be sourced from pretty much anywhere.) They remembered that our client app maintains an encrypted local cache of the data and wanted to know if there was any way they could use that to create a CSV file to re-import back to the original data source.</p>
<p>My first thought: <a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx">PowerShell</a>.</p>
<p>It took 20-30 minutes to review and remember what our application code was doing and create a PowerShell script that decrypted the data and exported it to CSV. It helps that we used standard .NET functionality like the built-in serialization of a DataSet and the Data Protection API. If anything had been customized it would&#8217;ve been trickier, but still do-able.</p>
<p>End result, here&#8217;s the script (it&#8217;s also available for <a href="http://www.aaronlerch.com/files/blog/Convert-I3DirToCSV.zip">download here</a>, if you&#8217;re an Interactive Intelligence customer and find it useful in some way) &#8212; completely unsupported of course, use at your own risk, etc.</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --><br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}</p>
<p>.csharpcode pre { margin: 0em; }</p>
<p>.csharpcode .rem { color: #008000; }</p>
<p>.csharpcode .kwrd { color: #0000ff; }</p>
<p>.csharpcode .str { color: #006080; }</p>
<p>.csharpcode .op { color: #0000c0; }</p>
<p>.csharpcode .preproc { color: #cc6633; }</p>
<p>.csharpcode .asp { background-color: #ffff00; }</p>
<p>.csharpcode .html { color: #800000; }</p>
<p>.csharpcode .attr { color: #ff0000; }</p>
<p>.csharpcode .alt
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}</p>
<p>.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode"><span class="kwrd">param</span>
(
    [string] $i3DirFile = $(<span class="kwrd">throw</span> <span class="str">"You must specify an i3dir file that has been created on this same machine"</span>),
    [string] $outputCSVFile = $(<span class="kwrd">throw</span> <span class="str">"You must specify an output file name for the resulting CSV data"</span>)
)

<span class="rem"># Load the DPAPI assembly</span>
[System.Reflection.Assembly]::LoadWithPartialName(<span class="str">"System.Security"</span>) | out-null

<span class="rem"># Load the encrypted file</span>
$encryptedData = get-content -encoding byte $i3DirFile
$decryptedData = [System.Security.Cryptography.ProtectedData]::Unprotect($encryptedData, $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine)

$rawXml = [System.Text.Encoding]::UTF8.GetString($decryptedData)

$dataset = new-object System.Data.DataSet
$reader = new-object System.IO.StringReader($rawXml)
$dataset.ReadXml($reader, [System.Data.XmlReadMode]::ReadSchema) | out-null

$dataset.Tables[0] | export-csv $outputCSVFile</pre>
<p>That&#8217;s it! Just 8 or so lines of code (with no error checking, of course). A great example of how PowerShell came to the rescue, even though this had nothing to do with the command line, or scripting, or PowerShell itself.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f68e9ad3-ce38-4d5e-a671-4b9fbbf5c529" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati tags: <a href="http://technorati.com/tags/PowerShell" rel="tag">PowerShell</a>, <a href="http://technorati.com/tags/Interactive%20Intelligence" rel="tag">Interactive Intelligence</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/09/18/save-i3dir-files-to-csv-with-powershell/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Breaking Up: Moving Blog Engines</title>
		<link>http://www.aaronlerch.com/blog/2007/08/23/breaking-up-moving-blog-engines/</link>
		<comments>http://www.aaronlerch.com/blog/2007/08/23/breaking-up-moving-blog-engines/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 18:49:43 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/08/23/breaking-up-moving-blog-engines/</guid>
		<description><![CDATA[Like relationship break-ups, leaving a blog engine (for another, no less!) is not easy. There&#8217;s pleading (&#8220;Stick with Blogger, it&#8217;ll change to meet your needs, I swear!&#8221;), denial (&#8220;Database driven blogs are slower than statically published blogs.&#8221;), and crying (&#8220;Why, why, oh why is this so hard? *sob*&#8221;). Not to mention the &#8220;grass is greener&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Like relationship break-ups, leaving a blog engine (for another, no less!) is not easy. There&#8217;s pleading (&#8220;Stick with Blogger, it&#8217;ll change to meet your needs, I swear!&#8221;), denial (&#8220;Database driven blogs are slower than statically published blogs.&#8221;), and crying (&#8220;Why, why, oh why is this so hard? *sob*&#8221;). Not to mention the &#8220;grass is greener&#8221; syndrome: &#8220;only once I switch to Wordpress will I <em>truly </em>be happy &#8211; it will have every single feature I need!&#8221;.</p>
<p>That&#8217;s been my spare-time-life on and off over the past few weeks, and now you all get to benefit from my pain. Here are the requirements I had to move to a new blogging platform:</p>
<ol>
<li><strong>Self hosted</strong> &#8211; while not a hard-and-fast requirement, I really want something I can tweak if necessary. And it can&#8217;t be ASP.NET-based, as much as I wanted it to, because I&#8217;m not going to pay for ASP.NET hosting. As a developer I also get warm fuzzies about being in 100% absolute control. (Okay, really, as a <em>human being</em> I get warm fuzzies about being in 100% absolute control&#8230;)</li>
<li><strong>Old permalinks need to 301 redirect to new permalinks</strong> &#8211; I don&#8217;t have a lot of subscribers (but I love you all, so very much) and get a <em>very</em> modest number of hits every day. I really want/need those old links to point to the new ones. It needed to be seamless.</li>
<li><strong>Full, or nearly-full, import</strong> &#8211; I wanted to bring as much information as possible from my Blogger blog to my new blog platform. That means no &#8220;import from RSS&#8221; features for me, I wanted comments to come over, etc.</li>
<li><strong>Well used/tested, and feature rich</strong> &#8211; I wanted a blog engine that&#8217;s been proven. I don&#8217;t want to be overwhelmed with spam, or anything else. Along those lines, if a platform is going to be mature, it should have plenty of features. I want to be able to do things like moderate comments (if I ever feel like it), write an occasional article instead of a blog post, etc.</li>
</ol>
<p>Given those requirements, I decided to switch to <a href="http://wordpress.org/">Wordpress</a>, and here&#8217;s how I did it. (Spoiler: it took longer than I thought it would, required some custom development, and worked out okay in the end.)</p>
<p>I would divide my tasks into three components: exporting from <a href="http://www.blogger.com/">Blogger</a>, importing to Wordpress, and &#8220;general configuration&#8221; (permalink redirects, etc.)</p>
<h5>Export from Blogger</h5>
<p>I&#8217;ve actually already posted on this <a href="http://www.aaronlerch.com/blog/2007/07/21/export-blogger-blogs-to-blogml-with-powershell/">here</a>. I decided on <a href="http://www.blogml.org/">BlogML</a> as my &#8220;offline&#8221; format for my blog, and wrote a PowerShell script to export from Blogger and output the BlogML format. So step one, export to BlogML using my script.</p>
<p><a href="http://www.aaronlerch.com/files/blog/BreakingUpMovingBlogEngines_B582/BlogExportInProgress.png" atomicselection="true"><img src="http://www.aaronlerch.com/files/blog/BreakingUpMovingBlogEngines_B582/BlogExportInProgress_thumb.png" style="border: 0px none " alt="BlogExportInProgress" border="0" height="104" width="500" /></a><br />
<font size="1">Figure 1. Exporting from Blogger to a local BlogML file.</font></p>
<h5>Import to Wordpress</h5>
<p><strong>Update:</strong> <a href="http://www.softwarebyrob.com/2007/10/05/a-tale-of-moving-blog-engines-community-server-to-wordpress/">Rob Walling</a> from softwarebyrob.com has updated the import module to work with Wordpress 2.3 &#8211; get the updated version from my <a href="http://www.aaronlerch.com/blog/tools/">tools page</a>. Thanks Rob!</p>
<p>This took the most work. The first thing I had to do was write a Wordpress import module for BlogML, since none existed. <a href="http://www.aaronlerch.com/files/wordpress/blogml.zip">You can download the import module here.</a> <strong>IMPORTANT NOTE:</strong> This requires the <a href="http://sourceforge.net/projects/phpxpath/">Php.XPath library available from SourceForge</a>. Go there and <a href="http://sourceforge.net/project/showfiles.php?group_id=36731&amp;package_id=28963">download v3.5</a>, making sure to upload it to the same directory as &#8220;blogml.php&#8221; (typically something like &#8220;/wp-admin/import/&#8221;). It is a single .php file. You&#8217;ll need to do this at least until I figure out how licensing works between BlogML and Php.XPath&#8211;once I get that figured out I&#8217;ll be adding this import module to the <a href="http://www.codeplex.com/BlogML">BlogML CodePlex project</a>.</p>
<p>My steps were as follows:</p>
<ol>
<li>Back up my Blogger files (on my FTP server) to my local hard drive.</li>
<li>Log into my Wordpress install and update the URL to be &#8220;http://www.aaronlerch.com/blog&#8221; (instead of the intermediate location of &#8220;http://www.aaronlerch.com/wp&#8221;). Note that as soon as I saved this setting, it tried to redirect me to a location that doesn&#8217;t exist yet. It&#8217;ll fail, that&#8217;s okay.</li>
<li>Rename the &#8220;/blog&#8221; directory with my Blogger files to something else, and rename my intermediate Wordpress directory &#8220;/wp&#8221; to &#8220;/blog&#8221;.</li>
<li><strong>Change the encoding in my BlogML output file.</strong> This sucks, but the XML class I used (Php.XPath) requires the XML to be in UTF-8 format. My Blogger-&gt;BlogML export script generates it using the .NET APIs, which uses UTF-16 (Unicode) encoding by default. Instead of spending a lot of time tweaking the BlogML output-which wouldn&#8217;t benefit anybody but myself-I just fired up <a href="http://www.flos-freeware.ch/notepad2.html">Notepad2</a> and changed the file encoding to UTF-8 (File -&gt; Encoding -&gt; UTF-8), making sure to also update the &#8220;encoding&#8221; attribute of the &#8220;&lt;?xml&#8221; header tag from &#8220;utf-16&#8243; to &#8220;utf-8&#8243;.<br />
<img src="http://www.aaronlerch.com/files/blog/BreakingUpMovingBlogEngines_B582/CropperCapture1.png" style="border: 0px none " alt="CropperCapture[1]" border="0" height="186" width="412" /><br />
<font size="1">Figure 1. Be sure to change the &#8220;encoding&#8221; attribute of your XML file when changing the file encoding.</font><br />
<img src="http://www.aaronlerch.com/files/blog/BreakingUpMovingBlogEngines_B582/CropperCapture2.png" style="border: 0px none " alt="CropperCapture[2]" border="0" height="42" width="500" /><br />
<font size="1">Figure 2. Before conversion &#8211; &#8220;Unicode BOM&#8221; (BOM = Byte Order Mark)</font><br />
<img src="http://www.aaronlerch.com/files/blog/BreakingUpMovingBlogEngines_B582/CropperCapture3.png" style="border: 0px none " alt="CropperCapture[3]" border="0" height="42" width="500" /><br />
<font size="1">Figure 3. After conversion</font> &#8211; &#8220;UTF-8&#8243;</li>
<li>Import my BlogML export from Blogger into Wordpress (very straightforward&#8211;just try it). On the &#8220;completed&#8221; page of the import, it lists the posts that were imported, and at the bottom it gives a link to a permalinkmap.csv file which contains a mapping of old permalinks to new permalinks. I downloaded that file and saved it for use later.</li>
</ol>
<h5>General Configuration</h5>
<p>Finally, I needed to set up my redirects. Using the permalinkmap.csv file I downloaded, I ran the following PowerShell one-liner to create a text file containing entries that I copied into my &#8220;.htaccess&#8221; file (my hosting company uses LAMP):</p>
<p>import-csv permalinkmap.csv |% { $oldurl = ($_.OldPermalink -replace &#8220;http://www.aaronlerch.com&#8221;, &#8220;&#8221;); &#8220;redirect 301 $oldurl &#8221; + $_.NewPermalink } | out-file htaccessredirectdata.txt</p>
<p>It simply creates a list of redirect commands that end up looking something like this:<br />
redirect 301 /blog/2007/08/uri.html http://www.aaronlerch.com/blog/2007/08/21/uri-purity/</p>
<p>Finally, I needed to set up redirects for my archive files. Those were all stored in a single &#8220;archive&#8221; subfolder by Blogger, which I had locally as part of my original backup. This PowerShell one-liner output more redirect commands for me to copy into my .htaccess file:</p>
<p>dir archive | select Name |% { ($_ -match &#8220;([0-9]{4})_([0-9]{2})_.*&#8221;) | out-null; &#8220;redirect 301 /blog/archive/&#8221; + $_.Name + &#8221; http://www.aaronlerch.com/blog/&#8221; + $matches[1] + &#8220;/&#8221; + $matches[2] + &#8220;/&#8221; }  | out-file archivehtaccessdata.txt</p>
<p>This short command takes a file named &#8220;2007_08_01_archive.html&#8221; and produces the following redirect line:<br />
redirect 301 /blog/archive/2007_08_01_archive.html http://www.aaronlerch.com/blog/2007/08/</p>
<h5>Cleanup</h5>
<p>What good blog migration would be complete with out some cleanup? The export/import process mangled some special characters various blog writing tools I&#8217;ve used inserted. Not to mention code examples getting new-lines removed. (Beware!) A quick visual skim and it was all fixed up.</p>
<h5>Conclusion</h5>
<p>So what do we take away from all this? A few things:</p>
<ul>
<li>Cleanly migrating between blogging platforms <em>sucks</em>. It&#8217;s not straightforward, and &#8220;clean&#8221; is in the eye of the beholder.</li>
<li>If you ever want to migrate from Blogger to Wordpress, you&#8217;ve hopefully found some help here. At a higher (even <em>more</em> helpful) level, if you ever want to export from Blogger to BlogML, or import from BlogML to Wordpress, you&#8217;ve got some tools and guidance.</li>
</ul>
<p class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:2d190132-c02c-4bf5-b2a6-72ba4fe80f82" contenteditable="false" style="margin: 0px; padding: 0px; display: inline">Technorati Tags: <a href="http://technorati.com/tags/blogml" rel="tag">blogml</a>, <a href="http://technorati.com/tags/blogger" rel="tag">blogger</a>, <a href="http://technorati.com/tags/wordpress" rel="tag">wordpress</a>, <a href="http://technorati.com/tags/powershell" rel="tag">powershell</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/08/23/breaking-up-moving-blog-engines/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Windows PowerShell Presentation</title>
		<link>http://www.aaronlerch.com/blog/2007/08/10/windows-powershell-presentation/</link>
		<comments>http://www.aaronlerch.com/blog/2007/08/10/windows-powershell-presentation/#comments</comments>
		<pubDate>Fri, 10 Aug 2007 17:36:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[community]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/08/10/windows-powershell-presentation/</guid>
		<description><![CDATA[Well, it&#8217;s done.
I presented on Windows PowerShell last night at Indianapolis .NET Developers Association meeting.  Considering it was my first-ever presentation to a group anywhere close to that size (technical or otherwise), I thought it went very well.  Feedback was good, including some constructive criticism, which I wholeheartedly agreed with.  Considering my [...]]]></description>
			<content:encoded><![CDATA[<p>Well, it&#8217;s done.</p>
<p>I presented on Windows PowerShell last night at <a href="http://www.indynda.com/">Indianapolis .NET Developers Association</a> meeting.  Considering it was my first-ever presentation to a group anywhere close to that size (technical or otherwise), I thought it went very well.  Feedback was good, including some constructive criticism, which I wholeheartedly agreed with.  Considering my audience (developers who likely don&#8217;t live on the command line like my co-workers and I tend to&#8211;which isn&#8217;t a bad thing) I unintentionally spent too much time covering using the command-line and not enough time doing the demos on writing cmdlets or hosting powershell in apps, etc.  Live and learn, I always say! The biggest lesson I learned? Going barefoot while presenting is a Good Thing<sup>TM</sup>.  It made me feel so much more at ease. Ahhh, bare feet. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>If you were there, or are just interested, you can download my illustrious PointPoint presentation and demo code.  Note that I&#8217;m not a huge fan of a lot of PowerPoint slides in technical presentations, so you&#8217;ll see that I really only have 2 content slides (and use of the word &#8220;content&#8221; is questionable).</p>
<p><a href="http://www.aaronlerch.com/files/powershell/Windows%20PowerShell.pptx">Presentation (Office 2007 format)</a><br />
<a href="http://www.aaronlerch.com/files/powershell/Windows%20PowerShell.ppt">Presentation (Office 200x format)</a><br />
<a href="http://www.aaronlerch.com/files/powershell/Windows%20PowerShell%20Demos.zip">Demo code/scripts</a></p>
<p>Due to the really short time I had to prepare, I&#8217;d like to say a huge thanks to <a href="http://blogs.msdn.com/powershell">Jeffrey Snover</a> for his <a href="http://blogs.msdn.com/powershell/archive/2007/06/03/new-and-improved-start-demo.aspx">Start-Demo script</a> (and some example demos using it), <a href="http://blogs.msdn.com/daiken">David Aiken</a> for his &#8220;<a href="http://channel9.msdn.com/shows/The_DFO_Show">DFO Show</a>&#8221; walk-throughs (and associated code), <a href="http://www.leeholmes.com/blog/">Lee Holmes</a> for his &#8220;<a href="http://www.leeholmes.com/blog/MSHLogoAllowingUsersToExtendItsFunctionality.aspx">MSH Logo</a>&#8221; app, and <a href="http://www.hanselman.com/blog/">Scott Hanselman</a> for some <a href="http://www.hanselman.com/blog/content/radiostories/2003/01/22/scottHanselmansTipsForASuccessfulMsftPresentation.html">presentation advice</a> (including responding to some extra questions I had).  I totally hijacked their stuff, but did give full credit for it. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Note that I&#8217;m including my &#8220;tweaked&#8221; versions of their applications here, for all to enjoy. But all credit goes to them for originally creating it&#8211;I hardly did anything to it, literally.  You guys all saved me, thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/08/10/windows-powershell-presentation/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Speaking at the Indianapolis .NET Developer&#8217;s Association</title>
		<link>http://www.aaronlerch.com/blog/2007/07/31/speaking-at-the-indianapolis-net-developers-association/</link>
		<comments>http://www.aaronlerch.com/blog/2007/07/31/speaking-at-the-indianapolis-net-developers-association/#comments</comments>
		<pubDate>Tue, 31 Jul 2007 16:17:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[community]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/07/31/speaking-at-the-indianapolis-net-developers-association/</guid>
		<description><![CDATA[I&#8217;m speaking on August 9th at the Indianapolis .NET Developer&#8217;s Association meeting on Windows PowerShell. If you&#8217;re in the neighborhood, come on by! The talk will be geared towards developers, not admins, but hopefully it will help us (devs) think more about them (admins) when we&#8217;re designing and implementing our applications.  That, and there&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m speaking on August 9th at the <a href="http://www.indynda.com/">Indianapolis .NET Developer&#8217;s Association</a> meeting on Windows PowerShell. If you&#8217;re in the neighborhood, come on by! The talk will be geared towards developers, not admins, but hopefully it will help us (devs) think more about them (admins) when we&#8217;re designing and implementing our applications.  That, and there&#8217;s always ways to automate our day-to-day tasks, <a href="http://blogs.msdn.com/powershell/archive/2007/06/26/surfing-the-web-the-powershell-way.aspx">just like Jeffrey Snover</a>.</p>
<p>Due to the very short notice (I just found out a day or two ago) I&#8217;ll mostly be aggregating existing demos from the web and doing them live, as well as walking through using PowerShell much like <a href="http://www.wrox.com/WileyCDA/Section/id-292183.html">Scott Hanselman did</a> for his user group presentation.</p>
<p>It should be a good time &#8211; hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/07/31/speaking-at-the-indianapolis-net-developers-association/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Export Blogger Blogs to BlogML with PowerShell</title>
		<link>http://www.aaronlerch.com/blog/2007/07/21/export-blogger-blogs-to-blogml-with-powershell/</link>
		<comments>http://www.aaronlerch.com/blog/2007/07/21/export-blogger-blogs-to-blogml-with-powershell/#comments</comments>
		<pubDate>Sat, 21 Jul 2007 00:47:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[blogging]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/07/21/export-blogger-blogs-to-blogml-with-powershell/</guid>
		<description><![CDATA[I&#8217;m in the process of moving my blog from Blogger to WordPress, and I&#8217;m finding out just how important a project like BlogML really is.  Most blog engines will integrate with a select few other engines to allow importing/exporting.  What we really need is something just like BlogML &#8211; a standard format describing [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m in the process of moving my blog from <a href="http://www.blogger.com/">Blogger</a> to <a href="http://www.wordpress.org/">WordPress</a>, and I&#8217;m finding out just how important a project like <a href="http://blogml.com/">BlogML</a> really is.  Most blog engines will integrate with a select few other engines to allow importing/exporting.  What we really need is something just like BlogML &#8211; a standard format describing blog metadata that allows maximum interoperability.  I&#8217;d <em>love</em> it if I could change my blogging engine periodically to get the best feature set for my ever-changing needs.  But at this rate, the pain and effort is not really worth it.</p>
<p>My frustration led me to create a PowerShell script to export a Blogger blog to BlogML.  Other methods exist, but they all required changing something about my blog, whether it was the template, or the hosting (and thus domain name).  Not gonna happen.  The script makes use of the BlogML .NET library (for ease) and the Blogger API.  No Blogger login is required, you simply have to specify your &#8220;userid&#8221;.  Your user id (it&#8217;s most likely public) can be found in your profile URL, like so:</p>
<p><a href="http://www.aaronlerch.com/files/blog/ExportBloggertoBlogMLwithPowerShell_131B7/BloggerProfile.png" atomicselection="true"><img src="http://www.aaronlerch.com/files/blog/ExportBloggertoBlogMLwithPowerShell_131B7/BloggerProfile_thumb.png" style="border-width: 0px" alt="Blogger-Profile" border="0" height="143" width="500" /></a></p>
<p>Once you get that id, just run the script and pipe the output to a file.  The output is actually an array of strings, each one is BlogML XML that represents a single blog.  You can have multiple Blogger blogs associated with your user account&#8211;this will automatically download all of them.  You can change the script not to do that if you need to.</p>
<p>To use it, type the following at the command line, I&#8217;m using my user id as an example (and I know I only have a single blog):<br />
<font face="Courier New">PS C:\Test&gt; .\BloggerToBlogML.ps1 &#8220;17257708406345880368&#8243; | out-file aaronlerch.blogml.xml</font></p>
<p>You&#8217;ll get a progress bar as it downloads your posts, and when it&#8217;s completed it shows a short summary.<br />
<a href="http://www.aaronlerch.com/files/blog/ExportBloggertoBlogMLwithPowerShell_131B7/BlogExportInProgress.png" atomicselection="true"><img src="http://www.aaronlerch.com/files/blog/ExportBloggertoBlogMLwithPowerShell_131B7/BlogExportInProgress_thumb.png" style="border-width: 0px" alt="BlogExportInProgress" border="0" height="89" width="500" /></a></p>
<p><a href="http://www.aaronlerch.com/files/blog/ExportBloggertoBlogMLwithPowerShell_131B7/BlogExportCompleted.png" atomicselection="true"><img src="http://www.aaronlerch.com/files/blog/ExportBloggertoBlogMLwithPowerShell_131B7/BlogExportCompleted_thumb.png" style="border-width: 0px" alt="BlogExportCompleted" border="0" height="68" width="500" /></a></p>
<p><a href="http://www.aaronlerch.com/files/blog/BloggerToBlogML.zip">Download the script here</a>, or from my <a href="http://www.aaronlerch.com/tools">Garage Sale Code</a> page.  Let me know of any bugs or improvements I can make&#8211;I made it do what I needed, and not much more (the Blogger API is a little sparse anyway), but I&#8217;m happy to update it to include more if someone has a need.</p>
<p>Technorati Tags: <a href="http://technorati.com/tags/powershell" rel="tag">powershell</a>, <a href="http://technorati.com/tags/blogml" rel="tag">blogml</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/07/21/export-blogger-blogs-to-blogml-with-powershell/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>
