<?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>Josh Erickson &#187; powershell</title>
	<atom:link href="http://josherickson.org/category/code/powershell/feed" rel="self" type="application/rss+xml" />
	<link>http://josherickson.org</link>
	<description>And as you tread the halls of sanity...</description>
	<lastBuildDate>Wed, 01 Sep 2010 15:58:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Srt2DFXP version 0.3 is here!</title>
		<link>http://josherickson.org/2010/08/02/824/srt2dfxp-version-0-3-is-here</link>
		<comments>http://josherickson.org/2010/08/02/824/srt2dfxp-version-0-3-is-here#comments</comments>
		<pubDate>Mon, 02 Aug 2010 21:03:48 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[closed captioning]]></category>
		<category><![CDATA[dfxp]]></category>
		<category><![CDATA[Instant Watch]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[srt]]></category>
		<category><![CDATA[srt2dfxp]]></category>
		<category><![CDATA[subrip]]></category>
		<category><![CDATA[subtitle]]></category>
		<category><![CDATA[subvert]]></category>
		<category><![CDATA[timed text markup language]]></category>
		<category><![CDATA[ttml]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=824</guid>
		<description><![CDATA[A new week and a new release of Srt2DFXP! This release I&#8217;ve made some big changes to how the UI and conversion code works together. Now when running a conversion, the UI can be updated and so it can show the progress and in future releases, what it is currently doing. Though it may not [...]]]></description>
			<content:encoded><![CDATA[<h3><span style="font-weight: normal;">A new week and a new release of Srt2DFXP!</span></h3>
<p><span style="font-weight: normal;">This release I&#8217;ve made some big changes to how the UI and conversion code works together. Now when running a conversion, the UI can be updated and so it can show the progress and in future releases, what it is currently doing. Though it may not since it converts a full movie subtitle file so fast it would be hard to see the constant status changes.</span></p>
<p><span style="font-weight: normal;">Another important feature of this release is a the replacing newlines from the SubRip files with &lt;br /&gt; tags in DFXP. This allows multiline dialog to display in Netflix. I made this change after watching <a href="http://en.wikipedia.org/wiki/Moon_(film)" target="_blank">Moon</a> with the mrs. the other night and missing parts of the text as it overflowed off the video. Kudos to codeman38 for doing this in his initial python release!</span></p>
<h3>GUI Change Log</h3>
<div id="_mcePaste">
<ul>
<li>+Changed the replacement of newlines in srts to &lt;br /&gt; tags instead of nothing. (Works great with Netflix!)
<ul>
<li>Because of this I also have to change the default XML code to use InnerXML and had to clean the incoming text with util.cleanamp().</li>
</ul>
</li>
<li>+As a stopgap messure, moved srt2dfxp code to new file (srt2dfxp.cs). This should help in moving to a plugin system while cleaning up the MainWindow class.
<ul>
<li>Some massive changes to Mainwindow have resulted. It is slightly easier to read now methinks.</li>
<li>Conversion code is done in its own thread, is also now in its own thread making the UI more responsive.</li>
</ul>
</li>
<li>+Added an icon!</li>
<li>+Added a Change log file (changelog.txt).</li>
<li>+Added hotkeys.
<ul>
<li>Alt+C Starts conversion.</li>
<li>Alt+O expands the Options.</li>
<li>Alt+S opens the Subrip file browse.</li>
<li>Alt+D Opens the DFXP save location dialog.</li>
</ul>
</li>
<li>+Fixed ampersand issue where cleanamp would not take into account other character entities besides &amp;amp;.
<ul>
<li>For example, if &amp;#223; existed in the original srt, it would be become &amp;amp;#223;.</li>
</ul>
</li>
</ul>
</div>
<h3>Script Change Log</h3>
<ul>
<li>+Changed the replacement of newlines in srts to &lt;br /&gt; tags instead of nothing. (Works great with Netflix!)
<ul>
<li>Because of this I also have to change the default XML code to use InnerXML and had to clean the incoming text with cleanamp().</li>
</ul>
</li>
</ul>
<h3>Downloads</h3>
<p>If you used the installer version previously, your copy should automatically update itself. Otherwise you can grab a copy below!</p>
<h3><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: normal; line-height: 20px; font-size: 14px; color: #5b5b5b;">GUI v0.3: <a style="font-weight: inherit; font-style: inherit; font-size: 14px; font-family: inherit; vertical-align: baseline; color: #21759b; text-decoration: underline; padding: 0px; margin: 0px; border: 0px initial initial;" href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp_gui-installer.zip">Installer</a>, <a style="font-weight: inherit; font-style: inherit; font-size: 14px; font-family: inherit; vertical-align: baseline; color: #21759b; text-decoration: underline; padding: 0px; margin: 0px; border: 0px initial initial;" href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp_gui-bin.zip">Binaries</a>, <a style="font-weight: inherit; font-style: inherit; font-size: 14px; font-family: inherit; vertical-align: baseline; color: #21759b; text-decoration: underline; padding: 0px; margin: 0px; border: 0px initial initial;" href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp_gui%20-source.zip">Source<br />
</a></span><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: normal; line-height: 20px; font-size: 14px; color: #5b5b5b;">Command Line v0.3: <a style="font-weight: inherit; font-style: inherit; font-size: 14px; font-family: inherit; vertical-align: baseline; color: #21759b; text-decoration: underline; padding: 0px; margin: 0px; border: 0px initial initial;" href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp-cli.zip">Powershell</a></span></h3>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/08/02/824/srt2dfxp-version-0-3-is-here/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Srt2DFXP v0.2 and a GUI!</title>
		<link>http://josherickson.org/2010/07/29/845/srt2dfxp-v0-2-and-a-gui</link>
		<comments>http://josherickson.org/2010/07/29/845/srt2dfxp-v0-2-and-a-gui#comments</comments>
		<pubDate>Fri, 30 Jul 2010 03:22:15 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[closed captioning]]></category>
		<category><![CDATA[dfxp]]></category>
		<category><![CDATA[Instant Watch]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[srt]]></category>
		<category><![CDATA[srt2dfxp]]></category>
		<category><![CDATA[subrip]]></category>
		<category><![CDATA[subtitle]]></category>
		<category><![CDATA[subvert]]></category>
		<category><![CDATA[timed text markup language]]></category>
		<category><![CDATA[ttml]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=845</guid>
		<description><![CDATA[After reading Codeman38&#8216;s blog edit I figured I can&#8217;t leave my Windows brethren behind in the dust when it comes to PC vs. Mac. So I whipped up an update to the Powershell script and finished an exe/GUI! Script Changes SubRip parsing is faster (tests with Memento srt file finished in half the time.) A [...]]]></description>
			<content:encoded><![CDATA[<p>After reading <a href="http://blog.zone38.net/2010/07/28/920/">Codeman38</a>&#8216;s blog edit I figured I can&#8217;t leave my Windows brethren behind in the dust when it comes to PC vs. Mac. So I whipped up an update to the Powershell script and finished an exe/GUI!</p>
<h3>Script Changes</h3>
<ul>
<li>SubRip parsing is faster (tests with Memento srt file finished in half the time.)</li>
<li>A little more forgiving with some error messages to help with issues.</li>
<li>Fixes issues with parameters. If InputPath or InputString weren&#8217;t specified, it would fail.
<ul>
<li>Now you can actually do &#8220;srt2dfxp.ps1 file.srt file.dfxp&#8221;</li>
</ul>
</li>
<li>Modified TimeOffset so it now has to be named instead of having a position.</li>
<li>Added TimeOffset parsing so that integers or strings can be used instead of having to create a TimeSpan object.</li>
<li>Added cleanamp which checks for ampersands and fixes any that aren&#8217;t followed by &#8220;amp;&#8221;. Only used by -NetflixCompatible</li>
<li>Added progress bars, to see them use the -WatchProgress switch;</li>
<li>Added some debugging data.  Set $DebugPreference to &#8220;Continue&#8221; to see it.</li>
</ul>
<h3>GUI</h3>
<p><a href="http://josherickson.org/wp-content/uploads/screenshot01.png"><img class="aligncenter size-medium wp-image-850" title="screenshot01" src="http://josherickson.org/wp-content/uploads/screenshot01-300x171.png" alt="" width="300" height="171" /></a><br />
The is my first attempt at using WPF for an application, so it may be buggy. Though I&#8217;ve done a bunch of testing and tweaking. It&#8217;s feature set and features are pretty much 1:1 with the script. Some things like the converted DFXP to stdout though have been cut.</p>
<h3>Roadmap</h3>
<p>Definitely happening:</p>
<ul>
<li>Code base merge. Build a library in C# to do the heavy lifting and then either Powershell or WPF to access those methods.</li>
<li>Alternate <a href="http://www.w3.org/TR/ttaf1-dfxp/#timing-value-timeExpression">&lt;timeExpression&gt;</a> formats.</li>
<li>Inclusion of other subtitle/captioning formats.</li>
</ul>
<p>Meh, it would be nice:</p>
<ul>
<li>Text editing and timing.</li>
<li>Netflix: &#8220;Smart&#8221; splitting to make sure all text is rendered.</li>
<li>Video/Image preview for editing.</li>
<li>Signed installer/executables.</li>
<li>Subtitle search</li>
</ul>
<h3>Download</h3>
<ul>
<li>GUI v0.2.0.5: <a href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp_gui-installer.zip">Installer</a>, <a href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp_gui-bin.zip">Binaries</a>, <a href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp_gui -source.zip">Source</a></li>
<li>Command Line v0.2: <a href="http://josherickson.org/vsprojects/srt2dfxp/srt2dfxp-cli.zip">Powershell</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/07/29/845/srt2dfxp-v0-2-and-a-gui/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Netflix subtitles</title>
		<link>http://josherickson.org/2010/07/28/822/netflix-subtitles</link>
		<comments>http://josherickson.org/2010/07/28/822/netflix-subtitles#comments</comments>
		<pubDate>Wed, 28 Jul 2010 15:47:47 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[close]]></category>
		<category><![CDATA[dfxp]]></category>
		<category><![CDATA[Instant Watch]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[srt]]></category>
		<category><![CDATA[srt2dfxp]]></category>
		<category><![CDATA[subrip]]></category>
		<category><![CDATA[subtitle]]></category>
		<category><![CDATA[subvert]]></category>
		<category><![CDATA[timed text markup language]]></category>
		<category><![CDATA[ttml]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=822</guid>
		<description><![CDATA[Edit: There is a GUI converter now. Earlier this year Netflix finally added captioning to their Instant watch player. Which is about time, finally they can start catching up with Hulu&#8216;s awesome implementation. Sadly though, they only seem to offer the captioning for select videos which seem to all be episodes from the popular TV [...]]]></description>
			<content:encoded><![CDATA[<p><em>Edit: There is a <a href="http://josherickson.org/tag/subvert">GUI converter</a> now.</em></p>
<p>Earlier this year Netflix finally <a href="http://blog.netflix.com/2010/04/subtitles-now-available-for-some-titles.html">added captioning</a> to their Instant watch player. Which is about time, finally they can start catching up with <a href="http://www.hulu.com/support/content_faq">Hulu</a>&#8216;s awesome implementation. Sadly though, they only seem to offer the captioning for select videos which seem to all be episodes from the popular TV series Lost. Since me and the mrs. have already enjoyed in it&#8217;s entirety, it doesn&#8217;t help us when want to watch something now and don&#8217;t want to visit the local video rental shop.</p>
<p>That is until last night.</p>
<p>Last night I was working on an unrelated project when I came across <a href="http://markwarren.wordpress.com/2010/03/24/netflix-movie-player-keyboard-shortcuts/">keyboard shortcuts</a> for the Netflix player. One of them was for a menu, which had a strange entry &#8220;Load custom DFXP File&#8221; which turns out is a <a href="http://www.w3.org/TR/ttaf1-dfxp/">W3 standard</a> for subtitles! So I started off finding out how to construct my own <a href="http://en.wikipedia.org/wiki/SubRip">SubRip</a> to DFXP converter.</p>
<p>However things turned out to be not as simple as it first appeared. The Netflix player apparently is very picky about it&#8217;s XML, and by picky I mean the kid freaking out that the peas are touching the potatoes picky. I think it may just be using text parsing, but I can&#8217;t confirm since Netflix obfuscates their Silverlight code, making it hard to follow. This presented me with some difficulty until I started up Wireshark and captured the DFXP file for the Lost pilot episode and used that as a template.</p>
<p>At the moment this is a only a Powershell script. I do plan on writing a .NET GUI or web based converter in the near future so my wife can make use of it without me around.</p>
<h3>Script Usage</h3>
<p>Basic usage is to download the Subrip file you need and pass it through the converter.</p>
<pre>srt2dfxp.ps1 MovieSubtitles.srt MovieSubtitles.dfxp</pre>
<p>For a Netflix compatible version, include the -NetflixCompatible switch.</p>
<pre>srt2dfxp.ps1 MovieSubtitles.srt MovieSubtitles.dfxp -NetflixCompatible</pre>
<p>And for some Netflix videos you&#8217;ll need to account for video padding, like on their StarsPlay selections. The following example accounts for the 13 second StarsPlay preview before Memento.</p>
<pre>srt2dfxp.ps1 MovieSubtitles.srt MovieSubtitles.dfxp ([timespan]::parse("0:00:13")) -NetflixCompatible</pre>
<h3>Netflix Usage</h3>
<p>Now that you have a Netflix compatible DFXP file, open up your movie and hit Ctrl+Shift+Alt+M to bring up a menu. From here Select &#8220;Load custom DFXP File&#8221;, browse to the location of your file and enjoy your newly subtitled <a href="http://josherickson.org/wp-content/uploads/memento_example.png">Netflix Instant Watch</a> movie!</p>
<h3>Get it</h3>
<p>Download <a href="http://josherickson.org/wp-content/uploads/srt2dfxp.zip">srt2dfxp.zip</a>.</p>
<p>[Edit] Codeman38 has created <a href="http://blog.zone38.net/2010/07/28/920/">Python version</a> that works on Macs and I assume Linux.</p>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/07/28/822/netflix-subtitles/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Wake-on-Lan (WOL) via Powershell</title>
		<link>http://josherickson.org/2010/05/07/785/wake-on-lan-wol-via-powershell</link>
		<comments>http://josherickson.org/2010/05/07/785/wake-on-lan-wol-via-powershell#comments</comments>
		<pubDate>Fri, 07 May 2010 18:36:23 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[concepts]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[dump]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[wake-on-lan]]></category>
		<category><![CDATA[wol]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=785</guid>
		<description><![CDATA[Despite what others may say, Wake-on-LAN isn&#8217;t magic and isn&#8217;t that complicated a feat to do anymore. With Powershell and .NET you can have the power of WOL without having to resort to third-party applications! Code/Script: param ( $targetMac, $network = [net.ipaddress]::Broadcast, $subnet = [net.ipaddress]::Broadcast ) try { if($network.gettype().equals([string])) { $network = [net.ipaddress]::Parse($network); } if($subnet.gettype().equals([string])) [...]]]></description>
			<content:encoded><![CDATA[<p>Despite what others may say, Wake-on-LAN isn&#8217;t magic and isn&#8217;t that complicated a feat to do anymore. With Powershell and .NET you can have the power of WOL without having to resort to third-party applications!</p>
<h2>Code/Script:</h2>
<pre>param (
    $targetMac,
    $network = [net.ipaddress]::Broadcast,
    $subnet = [net.ipaddress]::Broadcast
)
try {
    if($network.gettype().equals([string])) {
        $network = [net.ipaddress]::Parse($network);
    }
    if($subnet.gettype().equals([string])) {
        $subnet = [net.ipaddress]::Parse($subnet);
    }
    $broadcast = new-object net.ipaddress (([system.net.ipaddress]::parse("255.255.255.255").address -bxor $subnet.address -bor $network.address))

    $mac = [Net.NetworkInformation.PhysicalAddress]::Parse($targetMac.toupper().replace(".",""))

    $u = New-Object net.sockets.udpclient
    $ep = New-Object net.ipendpoint $broadcast, 0
    $ep2 = New-Object net.ipendpoint $broadcast, 7
    $ep3 = New-Object net.ipendpoint $broadcast, 9

    $payload = [byte[]]@(255,255,255, 255,255,255);
    $payload += ($mac.GetAddressBytes()*16)

    for($i = 0; $i -lt 10; $i++) {
        $u.Send($payload, $payload.Length, $ep) | Out-Null
        $u.Send($payload, $payload.Length, $ep2) | Out-Null
        $u.Send($payload, $payload.Length, $ep3) | Out-Null
        sleep 1;
    }
} catch {
    $Error | Write-Error;
}</pre>
<h2>Usage:</h2>
<pre>
wol.ps1 "target-MAC"
wol.ps1 "target-MAC" 192.168.1.255
wol.ps1 "target-MAC" 192.168.1.123 255.255.255.0
</pre>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/05/07/785/wake-on-lan-wol-via-powershell/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Netview.ps1 v0.2</title>
		<link>http://josherickson.org/2010/04/14/780/netview-ps1-v0-2</link>
		<comments>http://josherickson.org/2010/04/14/780/netview-ps1-v0-2#comments</comments>
		<pubDate>Wed, 14 Apr 2010 20:20:13 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[netview.ps1]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=780</guid>
		<description><![CDATA[Oooo! Version 0.2 of netview.ps1! Some code changes and less dieing in the middle of a listing! Also included is a -IsCluster switch! It&#8217;s great for easily finding out if a given NetBIOS name is a machine or a cluster! param ( [string]$Computer, [string]$Domain, [switch]$Cache, [switch]$All, [switch]$ResolveIP, [switch]$GetOS, [switch]$GetUser, [switch]$IsCluster, [System.Management.Automation.PSCredential]$Credentials ) #Take some notes [...]]]></description>
			<content:encoded><![CDATA[<p>Oooo! Version 0.2 of netview.ps1! Some code changes and less dieing in the middle of a listing! Also included is a -IsCluster switch! It&#8217;s great for easily finding out if a given NetBIOS name is a machine or a cluster!</p>
<pre>
<#
.Synopsis
Parses the "net view" command into PowerShell objects for easy usage.
.description
Switches and parameters are copied stright from "Net view".

Return objects are named after the output table headers in net view.

NETVIEW.PS1 displays a list of resources being shared on a computer. When used without options, it displays a list of computers in the current domain or network.
.parameter Computer
    Is a computer whose shared resources you want to view.
.parameter Domain
    Specifies the domain for which you want to view the available computers. If domainname is omitted, displays all domains in the local area network.
.parameter Cache
    Displays the offline client caching settings for the resources on the specified computer
.parameter All
    Displays all the shares including the $ shares
.parameter ResolveIP
    Resolves the NetBIOS names to their network IP addresses.
.parameter GetOS
    Uses CIM_OperatingSystem WMI class to obtain the operating system.
.parameter GetUser
    Get's the last user who logged in to that machine.
.parameter IsCluster
    Tries to find out if the ServerName is a cluster name.
.parameter Credentials
    Optional credentials to use for GetOS. If none are supplied it tries to use current credentials.
.Notes
-Version 0.2
    *Made some code changes so it doesn't die after WMI query failure.
    *Added missing .parameters as well as .Link and .Note.
    *Added IsCluster switch which checks to see if WINS is a cluster name instead of a machine name.
.Link

http://josherickson.org/tag/netview-ps1

#>
param (
    [string]$Computer,
    [string]$Domain,
    [switch]$Cache,
    [switch]$All,
	[switch]$ResolveIP,
    [switch]$GetOS,
    [switch]$GetUser,
    [switch]$IsCluster,
    [System.Management.Automation.PSCredential]$Credentials
)

#Take some notes and clean up stuff.
if($Computer.length -gt 1 -and !$Computer.startswith("\\")) {
    $Computer = "\\$computer";
    #$computer = "/computer $computer";
}
if($Domain.length -gt 1) {
    $Domain = "/DOMAIN:$Domain";
}

if($Cache.ispresent) {
    $_Cache = "/CACHE";
}

if($All.ispresent) {
    $_All = "/ALL";
}
try {
    $nv_raw = (powershell "&#038; { net view $Computer $_Cache $_All $Domain }" 2>&#038;1)
    if(($nv_raw | where {$_.tolower().contains("error")})) { throw $nv_raw; }
} catch{
    $nv_raw | where {$_} | Write-Error;
    exit;
}
#If computer isn't defined, we just want to parse the net view output as a list of computers.
if($Computer.length -eq 0) {
	$nv = $nv_raw | where {$_.startswith("\\")} | foreach { @{"name" = $_.substring(2,$_.indexof(" ")-2).replace(" ",""); "remark" = [regex]::Split($_, "( ){2,}")[2]} }
	foreach($a in $nv) {
		try {
			$r = new-object object;

			Add-Member -InputObject $r -MemberType NoteProperty -Name "ServerName" -Value $a.name;
			Add-Member -InputObject $r -MemberType NoteProperty -Name "Remarks" -Value $a.remark;

			[string]::Format("Running computer: {0}", $r.ServerName) | Write-Debug;

			if($GetIP.IsPresent) {
				try {
					Add-Member -InputObject $r -MemberType NoteProperty -Name "AddressList" -Value ([net.dns]::GetHostEntry($r.ServerName).addresslist);
				}
				catch {}
			}

			Add-Member -InputObject $r -MemberType ScriptMethod -Force -Name "ToString" -Value {
				try {
					return $this.ServerName +"|"+ [string]::Join("|", ($this.Addresslist));
				}
				catch{
					return $this.ServerName;
				}
			}

			if($GetOS.ispresent) {
				$__error = $Null;
				try {
					#if this computer is the one we're currently working on we can't use the gwmi credentials parameter
					if($r.ServerName -ne (hostname) -and $Credentials) {
						$os_cap = (gwmi -Class CIM_OperatingSystem -ComputerName $r.ServerName -Credential $Credentials).caption 2> $__error;
					} else {
						$os_cap = (gwmi -Class CIM_OperatingSystem -ComputerName $r.ServerName).caption  2> $__error;
					}
					if($__error) { throw $__error; }
					Add-Member -InputObject $r -MemberType NoteProperty -Name "OS" -Value $os_cap;
				} catch {
					$Error | Write-Error;
				}
			}

			if($GetUser.ispresent) {
				try {
					#if this computer is the one we're currently working on we can't use the gwmi credentials parameter
					if($r.ServerName -ne (hostname)) {
						$loggedon_user = (gwmi -Class CIM_UnitaryComputerSystem -ComputerName $r.ServerName -Credential $Credentials).UserName 2> $__error;
					} else {
						$loggedon_user = (gwmi -Class CIM_UnitaryComputerSystem -ComputerName $r.ServerName).UserName 2> $__error;
					}
					if($__error) { throw $__error; }
					Add-Member -InputObject $r -MemberType NoteProperty -Name "LastLoggedOnUser" -Value $loggedon_user;
				} catch {
					$Error | Write-Error;
				}
			}

			if($IsCluster.ispresent -xor ($IsCluster.ispresent -and $r.os -and !$r.os.contains("Server"))) {
				Add-Member -InputObject $r -MemberType NoteProperty -Name "IsCluster" -Value $False;
				try {
					if($Credentials) {
						$c = (gwmi -ComputerName $r.servername -Namespace Root\MSCluster -Class MSCluster_Node -ErrorAction "SilentlyContinue" -Credential $Credentials)

					} else {
						$c = (gwmi -ComputerName $r.servername -Namespace Root\MSCluster -Class MSCluster_Node -ErrorAction "SilentlyContinue")
					}

					$r.IsCluster = ([int]$c.length -gt 0 -and !(($c | foreach {$_.name}) -contains $r.servername));
				} catch {
					$Error | Write-Error;
				}
			}
			#output the object.
			$r;
		} catch {}
	}
} else { #Parse shares list
	#Start of lines that we DON'T want.
	$lines = @("Shared resources at", "Share name", "-----------", "The command completed successfully.");

	foreach($l in $nv_raw) {
		if(($lines | where {$l.startswith($_);}) -eq $null -and $l.length -gt 0) {
		   $r = New-Object object;
		   $t = [regex]::Split($l, "( ){2,}") | where {$_.replace(" ","").length -gt 0};
		   Add-Member -InputObject $r -MemberType NoteProperty -Name "Name" -Value $t[0];
		   Add-Member -InputObject $r -MemberType NoteProperty -Name "Type" -Value $t[1];
		   Add-Member -InputObject $r -MemberType ScriptProperty -Name "Secret" -Value {
				$this.ShareName.EndsWith("$");
		   }
		   if($t.length -gt 3) {
			   Add-Member -InputObject $r -MemberType NoteProperty -Name "UsedAs" -Value $t[2];
			   Add-Member -InputObject $r -MemberType NoteProperty -Name "Comment" -Value $t[3];
		   } else {
			   Add-Member -InputObject $r -MemberType NoteProperty -Name "Comment" -Value $t[2];
		   }
		   $r;
		}
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/04/14/780/netview-ps1-v0-2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Net View for PowerShell</title>
		<link>http://josherickson.org/2010/03/31/775/net-view-for-powershell</link>
		<comments>http://josherickson.org/2010/03/31/775/net-view-for-powershell#comments</comments>
		<pubDate>Wed, 31 Mar 2010 16:02:06 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[dump]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[netview.ps1]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=775</guid>
		<description><![CDATA[A little PowerShell tool that wraps around &#8220;Net view&#8221; and outputs objects instead of plain text. param ( [string]$Computer, [string]$Domain, [switch]$Cache, [switch]$All, [switch]$ResolveIP, [switch]$GetOS, [System.Management.Automation.PSCredential]$Credentials ) #Take some notes and clean up stuff. if($Computer.length -gt 1 -and !$Computer.startswith("\\")) { $Computer = "\\$computer"; #$computer = "/computer $computer"; } if($Domain.length -gt 1) { $Domain = "/DOMAIN:$Domain"; } [...]]]></description>
			<content:encoded><![CDATA[<p>A little PowerShell tool that wraps around &#8220;Net view&#8221; and outputs objects instead of plain text.</p>
<pre><#
.Synopsis
Parses the "net view" command into PowerShell objects for easy usage.
.description
Switches and parameters are copied stright from "Net view".

Return objects are named after the output table headers in net view.

NETVIEW.PS1 displays a list of resources being shared on a computer. When used without options, it displays a list of computers in the current domain or network.
.parameter Computer
    Is a computer whose shared resources you want to view.
.parameter Domain
    Specifies the domain for which you want to view the available computers. If domainname is omitted, displays all domains in the local area network.
.parameter Cache
    Displays the offline client caching settings for the resources on the specified computer
.parameter All
    Displays all the shares including the $ shares
.parameter ResolveIP
    Resolves the NetBIOS names to their network IP addresses.
.parameter GetOS
    Uses CIM_OperatingSystem WMI class to obtain the operating system.
.parameter Credentials
    Optional credentials to use for GetOS.

#>
param (
    [string]$Computer,
    [string]$Domain,
    [switch]$Cache,
    [switch]$All,
	[switch]$ResolveIP,
    [switch]$GetOS,
    [System.Management.Automation.PSCredential]$Credentials
)

#Take some notes and clean up stuff.
if($Computer.length -gt 1 -and !$Computer.startswith("\\")) {
    $Computer = "\\$computer";
    #$computer = "/computer $computer";
}
if($Domain.length -gt 1) {
    $Domain = "/DOMAIN:$Domain";
}

if($Cache.ispresent) {
    $_Cache = "/CACHE";
}

if($All.ispresent) {
    $_All = "/ALL";
}

try {
    try {
        $nv_raw = (powershell "&#038; { net view $Computer $_Cache $_All $Domain }" 2>&#038;1)
        if(($nv_raw | where {$_.tolower().contains("error")})) { throw $nv_raw; }
    } catch{
        $nv_raw | where {$_}
        exit;
    }

    #If computer isn't defined, we just want to parse the net view output as a list of computers.
    if($Computer.length -eq 0) {
        $nv = $nv_raw | where {$_.startswith("\\")} | foreach { @{"name" = $_.substring(2,$_.indexof(" ")-2).replace(" ",""); "remark" = [regex]::Split($_, "( ){2,}")[2]} }
        foreach($a in $nv) {
            #return object
        	$r = new-object object;

            Add-Member -InputObject $r -MemberType NoteProperty -Name "ServerName" -Value $a.name;
            Add-Member -InputObject $r -MemberType NoteProperty -Name "Remarks" -Value $a.remark;

            if($GetIP.IsPresent) {
                try {
                    Add-Member -InputObject $r -MemberType NoteProperty -Name "AddressList" -Value ([net.dns]::GetHostEntry($r.ServerName).addresslist);
                }
                catch {}
            }

            Add-Member -InputObject $r -MemberType ScriptMethod -Force -Name "ToString" -Value {
                try {
                    return $this.ServerName +"|"+ [string]::Join("|", ($this.Addresslist));
                }
                catch{
                    return $this.ServerName;
                }
            }

            if($GetOS.ispresent) {
                try {
                    #if this computer is the one we're currently working on we can't use the gwmi credentials parameter
                    if($r.ServerName -ne (hostname)) {
                        Add-Member -InputObject $r -MemberType NoteProperty -Name "OS" -Value (gwmi CIM_OperatingSystem -ComputerName $r.ServerName -Credential $Credentials).caption
                    } else {
                        Add-Member -InputObject $r -MemberType NoteProperty -Name "OS" -Value (gwmi CIM_OperatingSystem -ComputerName $r.ServerName).caption
                    }
                } catch {
					$Error | write-error;
                    Add-Member -InputObject $r -MemberType NoteProperty -Name "OS" -Value "N/A"
                }
            }

            #output the object.
            $r;
        }
    } else {
        #Start of lines that we DON'T want.
        $lines = @("Shared resources at", "Share name", "-----------", "The command completed successfully.");

        foreach($l in $nv_raw) {
            if(($lines | where {$l.startswith($_);}) -eq $null -and $l.length -gt 0) {
               $r = New-Object object;
               $t = [regex]::Split($l, "( ){2,}") | where {$_.replace(" ","").length -gt 0};
               Add-Member -InputObject $r -MemberType NoteProperty -Name "Name" -Value $t[0];
               Add-Member -InputObject $r -MemberType NoteProperty -Name "Type" -Value $t[1];
               Add-Member -InputObject $r -MemberType ScriptProperty -Name "Secret" -Value {
                    $this.ShareName.EndsWith("$");
               }
               if($t.length -gt 3) {
                   Add-Member -InputObject $r -MemberType NoteProperty -Name "UsedAs" -Value $t[2];
                   Add-Member -InputObject $r -MemberType NoteProperty -Name "Comment" -Value $t[3];
               } else {
                   Add-Member -InputObject $r -MemberType NoteProperty -Name "Comment" -Value $t[2];
               }
               $r;
            }
        }
    }
} catch {
    $Error | Write-Error
}</pre>
<p><em>Edit: Fixed some variable name errors.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/03/31/775/net-view-for-powershell/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Is it an IP subnet mask?</title>
		<link>http://josherickson.org/2010/03/25/772/is-it-an-ip-subnet-mask</link>
		<comments>http://josherickson.org/2010/03/25/772/is-it-an-ip-subnet-mask#comments</comments>
		<pubDate>Thu, 25 Mar 2010 15:22:22 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[blah]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[powershell]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=772</guid>
		<description><![CDATA[Working on a tool to calculate IP ranges, I realized that I didn&#8217;t have a way to test if an input was an IP or a subnet mask! Thankfully subnet addresses are fairly easy to ID since they all start with 255 and, in binary, never have a 1 follow a 0. param ( [Parameter(Position [...]]]></description>
			<content:encoded><![CDATA[<p>Working on a tool to <a href="http://josherickson.org/2010/01/27/723/of-ips-subnets">calculate IP ranges</a>, I realized that I didn&#8217;t have a way to test if an input was an IP or a subnet mask!</p>
<p>Thankfully subnet addresses are fairly easy to ID since they all start with 255 and, in binary, never have a 1 follow a 0.</p>
<pre>
<#
.Synopsis
Determine whether or not a given IP/Subnet address is a Subnet mask.
.description
This script should make it easier to determine whether or not a given Net.IPAddress is suppose to be used as an subnet mask or not.
.parameter Address
A string or an System.Net.IPAddress object.
.Example
if(issubnet.ps1 255.255.254.0 -eq $True) {
    "this is a subnet";
}
.Example
if(issubnet.ps1 "192.168.1.254" -eq $True) {
    "This is a subnet";
}
#>
param (
    [Parameter(Position = 0, ValueFromPipelineByPropertyName = $true)]
    $Address
)
try {
    if($Address.gettype() -eq [net.ipaddress]) {
        $a = $Address;
    } elseif($Address.gettype() -eq [string]) {
        $a = [net.ipaddress]::Parse("$Address");
    } elseif($Address.gettype() -eq [Int64]) {
        $a = New-Object net.ipaddress $Address;
    }
    $b2subnet = [string]::join("", ($a.getaddressbytes() | foreach {[convert]::ToString($_, 2).padleft(8, "0")}))
}
catch {
    throw ("Invalid IPAddress or input type. Type given: " + $Address.GetType().name + ", Value: " + $Address)
}
try {
    if($a.getaddressbytes()[0] -eq 255 -and $b2subnet.indexof("1", $b2subnet.indexof("0")) -eq -1) {
        return $True;
    } else {
        return $False
    }
}
catch {
    if($a -eq [net.ipaddress]::Parse("255.255.255.255")) {
        return $True;
    } else {
        throw "There was some sort of error and I don't know why!";
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/03/25/772/is-it-an-ip-subnet-mask/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Logon UI Background Changer Revisited</title>
		<link>http://josherickson.org/2010/03/17/765/logon-ui-background-changer-revisited</link>
		<comments>http://josherickson.org/2010/03/17/765/logon-ui-background-changer-revisited#comments</comments>
		<pubDate>Wed, 17 Mar 2010 23:50:46 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[Background]]></category>
		<category><![CDATA[backgroundDefault]]></category>
		<category><![CDATA[imageprocessor]]></category>
		<category><![CDATA[info]]></category>
		<category><![CDATA[LogonUI]]></category>
		<category><![CDATA[OEMBackground]]></category>
		<category><![CDATA[oobe]]></category>
		<category><![CDATA[wallpaper]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=765</guid>
		<description><![CDATA[In a recent Hak5 episode (704, at 9 minutes) they covered changing the Logon UI background, which reminded me of my own little script. Since last working the script, I&#8217;d like to think I&#8217;ve learned more and it was about to time clean up the code and make it a little more user friendly. It [...]]]></description>
			<content:encoded><![CDATA[<p>In a recent Hak5 episode (<a href="http://www.hak5.org/episodes/episode-704">704</a>, <a href="http://www.youtube.com/watch?v=YtEBbnQCo9c#t=9m">at 9 minutes</a>) they covered changing the Logon UI background, which reminded me of my own little <a href="http://josherickson.org/2009/08/19/556/windows-7-powrrshell-logonui-changer">script</a>.</p>
<p>Since last working the script, I&#8217;d like to think I&#8217;ve learned more and it was about to time clean up the code and make it a little more user friendly. It still relies on the original ImageProcessor.dll, but this time, I moved the files around so you just need to unzip the archive and changing your background. If you&#8217;re as paranoid as I am, the source for ImageProcessor.dll is still included, as well as the build.bat file.</p>
<p>Download <a href='http://josherickson.org/wp-content/uploads/win7logonui1.zip'>win7logonui</a> now!</p>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/03/17/765/logon-ui-background-changer-revisited/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Of IPs &amp; Subnets</title>
		<link>http://josherickson.org/2010/01/27/723/of-ips-subnets</link>
		<comments>http://josherickson.org/2010/01/27/723/of-ips-subnets#comments</comments>
		<pubDate>Wed, 27 Jan 2010 16:57:41 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[concepts]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[Ip address]]></category>
		<category><![CDATA[range]]></category>
		<category><![CDATA[subnet]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=723</guid>
		<description><![CDATA[While if you look, there are tools to calculate a IP subnet/address range, they all seem to rely on string splitting and converting the address to binary manually. Which I think is bulky, hard to maintain, and more importantly, not that elegant. So pulling to mind my Cisco CCNA classes where my instructor would drill [...]]]></description>
			<content:encoded><![CDATA[<p>While if you look, there are tools to calculate a IP subnet/address range, they all seem to rely on string splitting and converting the address to binary manually. Which I think is bulky, hard to maintain, and more importantly, not that <em>elegant</em>. So pulling to mind my Cisco CCNA classes where my instructor would drill into us the binary ands and ors of IP and subnet addressing, I got down to work.</p>
<p>All examples are in Powershell, however they could be translated to C#, any .NET language or even some other language quite easily.</p>
<h3>Examples</h3>
<p>Including System.net. This may not be necessary, but I&#8217;ve mucked with my Powershell settings way too much to know about a vanilla install.</p>
<pre>
#Powershell v1.0
[reflection.assembly]::LoadWithPartialName("system.net");
#Powershell v2.0
Add-Type -AssemblyName System.Net;
</pre>
<p>A common plight for me is finding out if two different IP addresses are on the same local network.</p>
<pre>
$router = [net.ipaddress]::Parse("192.168.1.254");
$subnet = [net.ipaddress]::Parse("255.255.255.0");
$IP_one = [net.ipaddress]::Parse("192.168.1.23");
$IP_two = [net.ipaddress]::Parse("192.168.1.55");
$IP_three = [net.ipaddress]::Parse("33.21.9.1");

#get the network ID
#in this case it's 192.168.1.0
$network = $router.address -band $subnet.Address

($network -band $IP_one.Address) -eq $network #True
($network -band $IP_two.Address) -eq $network #True
($network -band $IP_three.Address) -eq $network #False
</pre>
<p>Of course there are also times where I need to know how many addresses there are in the network or what they are.</p>
<pre>
$seed = [net.ipaddress]::Parse("192.168.23.45");
$subnet = [net.ipaddress]::Parse("255.255.252.0");

$begin = ($seed.address -band $subnet.address)
$end = (([net.ipaddress]::Broadcast.Address -bxor $subnet.Address) -bor $seed.address)

#It's the same for both start and ending IP's
#We convert from a 64 to 32 bit integer (8 to 4 bytes) and then reverse it so we can do addition/subtraction math to later on.
$start_bytes = new-object byte[] 4;
[array]::copy([bitconverter]::getBytes(($seed.address -band $subnet.address)), $start_bytes, 4);
[array]::Reverse($start_bytes);
$start_int = [bitconverter]::ToInt32($start_bytes,0);

$end_bytes = new-object byte[] 4;
[array]::copy([bitconverter]::getBytes((([net.ipaddress]::Broadcast.Address -bxor $subnet.Address) -bor $seed.address)), $end_bytes, 4);
[array]::Reverse($end_bytes);
$end_int = [bitconverter]::ToInt32($end_bytes,0);

#Entire range including the network ID and Broadcast addresses
[math]::Abs($start_int - $end_int) + 1

#Just the number of usable addresses
[math]::Abs($start_int - $end_int) - 1

#Address list!
for($i=0; $i -le [math]::abs($start_int - $end_int); $i++) {
    $tba = [bitconverter]::getbytes($i + $start_int);
	[array]::Reverse($tba)
    (new-object net.ipaddress ([bitconverter]::ToInt64($tba + [byte[]]@(0,0,0,0),0))).tostring();
}
</pre>
<h3>Conclusion</h3>
<p>As you can see, using bitwise operations greatly reduces the complexity required to calculate network addresses. By simplifying the process, it makes it much easier to maintain the code and build on it later!</p>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/01/27/723/of-ips-subnets/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Restoring Hyper-V VM with snapshot tree</title>
		<link>http://josherickson.org/2010/01/27/728/restoring-hyper-v-vm-with-snapshot-tree</link>
		<comments>http://josherickson.org/2010/01/27/728/restoring-hyper-v-vm-with-snapshot-tree#comments</comments>
		<pubDate>Wed, 27 Jan 2010 15:44:06 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[concepts]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[work]]></category>
		<category><![CDATA[avhd]]></category>
		<category><![CDATA[differencing]]></category>
		<category><![CDATA[Hyper-V]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[snapshots]]></category>
		<category><![CDATA[vhd]]></category>

		<guid isPermaLink="false">http://josherickson.org/?p=728</guid>
		<description><![CDATA[For whatever reason, you&#8217;ve lost your virtual machine settings in Hyper-V and it just so happened they are snapshots. I sure hope that this was a test server and not a production one! Tsktsk! By now, you&#8217;ve probably scoured the interweb searching for a cure, and you&#8217;re in luck, you&#8217;ve found a way to get [...]]]></description>
			<content:encoded><![CDATA[<p>For whatever reason, you&#8217;ve lost your virtual machine settings in Hyper-V and it just so happened they are snapshots. I sure hope that this was a test server and not a production one! Tsktsk! By now, you&#8217;ve probably scoured the interweb searching for a cure, and you&#8217;re in luck, you&#8217;ve found a way to get back your snapshot tree instead of just merging the disks! Oh joy!</p>
<p>It would seem everyone out there is happy with just merging their VHDs and getting back to work, but not me, no sir! I want things back the way they were! It took me about half a day to get this, so hopefully, this will save you some time for more important things, like <a href="http://www.firstpersontetris.com/">tetris</a>!</p>
<h3>Steps</h3>
<ol>
<li>Create same number of pre-existing snapshots using the Hyper-V MMC.</li>
<li>Replace new snapshots with old snapshots while renaming the old to the same as the new, except the file extension should be &#8220;vhd&#8221; instead of &#8220;avhd&#8221;. The reason we&#8217;ll see later, but the Hyper-V tool to repair VHD chains auto-appends .vhd! (Grr <a href="http://blogs.technet.com/virtualization/">Hyper-V Team</a>, grr!)</li>
<li>Repair the vhd&#8217;s. Because of our renaming we&#8217;ve broken the differencing chain. To fix this, go to open  Hyper-V, go to the VM&#8217;s Settings and then the hard drive. Change the VHD to the new one (simply changing the extension should work) and click &#8220;inspect disk&#8221;. This will walk you through fixing the chain.</li>
<li>Modify the ACL to include the VM specific account. This you must to in Powershell since the Explorer GUI can&#8217;t seem to find the account. I don&#8217;t know why and there may be a way, but I&#8217;m to lazy to dig into it and this works. (Below you can find some sample code.) The account to add from the old VHD, is the one that starts with &#8220;NT VIRTUAL MACHINE&#8221; and ends with a GUID.
<pre>##START POWERSHELL CODE
#get the old vhd's permissions
$vm_perm = (get-acl .\old.vhd).access | where { $_.IdentityReference.tostring().contains("NT VIRTUAL MACHINE") }

#Load the new vhd's acl into memory
$newvhd = get-acl .\new.vhd

$newvhd.AddAccessRule($vm_perm)

$newvhd | set-acl .\new.vhd
##END POWERSHELL CODE</pre>
</li>
<li>Open all the VM&#8217;s XML setting files and make sure that any settings related the the VHD&#8217;s is correct. This should only be the filename. If you need to edit these files be sure to turn off the Hyper-V Management Service, this will not affect the VM&#8217;s running, only the managing of them. The XML files can be found wherever you made the VM.</li>
<li>You should now have a restored VM with the snapshot tree! Woo! Go you!</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://josherickson.org/2010/01/27/728/restoring-hyper-v-vm-with-snapshot-tree/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
