<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-6011603498138679949</atom:id><lastBuildDate>Fri, 05 Mar 2010 23:50:15 +0000</lastBuildDate><title>CodeBlog.TheG2.NET</title><description>Random code postings for various programing languages.</description><link>http://codeblog.theg2.net/</link><managingEditor>noreply@blogger.com (Greg Bray)</managingEditor><generator>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/TheG2NetCode" /><feedburner:info uri="theg2netcode" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-3269897090282426206</guid><pubDate>Fri, 05 Mar 2010 23:40:00 +0000</pubDate><atom:updated>2010-03-05T16:50:15.766-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">userscript</category><category domain="http://www.blogger.com/atom/ns#">JavaScript</category><category domain="http://www.blogger.com/atom/ns#">Bookmarklet</category><category domain="http://www.blogger.com/atom/ns#">CSS</category><category domain="http://www.blogger.com/atom/ns#">HTML</category><title>Slashdot Zoom Fix: a Greasemonkey and Chrome compatible userscript</title><description>&lt;p&gt;One of my top ten visited websites is probably &lt;a href="http://www.slashdot.org"&gt;Http://www.slashdot.org&lt;/a&gt; who’s headline is “News for nerds, stuff that matters”. The site usually posts over 20 stories a day covering technology, math, physics, and computer related topics, which help me keep informed and entertained. One problem that I often have is that the text size is very hard to read when using a high resolution monitor or when using the projector that I have setup on a media center computer at home. Usually this is easy to solve, since one of the &lt;a href="http://blog.theg2.net/2009/04/who-needs-100-mouse-you-do.html" target="_blank"&gt;11 buttons on my mouse&lt;/a&gt; is mapped to the CTRL button and can be combined with the scroll wheel to zoom in and out on web pages quickly. However in this case there are boxes on the right hand side of the screen that also enlarge when the page is zoomed, causing the text width to be smaller and more difficult to read. Here is an article on Slashdot normal and zoomed:&lt;/p&gt;  &lt;div align="center"&gt; &lt;table border="1" cellspacing="0" cellpadding="2" width="600" align="center"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;center&gt;&lt;a href="http://lh5.ggpht.com/_G06mB5h-kvQ/S5GWTDuD-4I/AAAAAAAAGek/jeKl8Aenqf0/s1600-h/Slashdot%20Normal%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Slashdot Normal" border="0" alt="Slashdot Normal" src="http://lh5.ggpht.com/_G06mB5h-kvQ/S5GWT400FUI/AAAAAAAAGes/coBMMor8K44/Slashdot%20Normal_thumb.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;             &lt;br /&gt;Normal&lt;/center&gt;&lt;/td&gt;          &lt;td valign="top" width="300"&gt;&lt;center&gt;&lt;a href="http://lh5.ggpht.com/_G06mB5h-kvQ/S5GWUqC5z7I/AAAAAAAAGe0/O3P1rkJWjPs/s1600-h/Slashdot%20Zoomed%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Slashdot Zoomed" border="0" alt="Slashdot Zoomed" src="http://lh3.ggpht.com/_G06mB5h-kvQ/S5GWVWg8mRI/AAAAAAAAGe8/SP7P0xFVu3U/Slashdot%20Zoomed_thumb.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;            &lt;br /&gt;Zoomed &lt;/center&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The site is designed using CSS and for some reason the advertisement and “Interviews” box will get bigger when the page is zoomed, shrinking the width of the textbox significantly. If you are a registered user Slashdot will not display the ad but will still have a side panel on the right that grows larger when you try and zoom in. I initially created a bookmarklet that could be used to remove the side panel by clicking on a link in my favorites to inject some javascript into the webpage to alter the CSS classes, but that still required that I manually click the button every time that I visit he website. &lt;/p&gt;  &lt;p&gt;I planned on making a Google Chrome Extension, but recently Chrome announce that they now will automatically convert &lt;a href="http://googlesystem.blogspot.com/2009/11/google-chrome-converts-user-scripts.html" target="_blank"&gt;Greasemonkey scripts into Chrome Extensions&lt;/a&gt;. This means you can write a cross-browser compatible script that can run in Firefox, Chrome or any other browser that supports &lt;a href="http://en.wikipedia.org/wiki/Greasemonkey" target="_blank"&gt;Greasemonkey&lt;/a&gt; scripts. It only took a few minutes to convert the bookmarklet into a userscript, and I posted it on &lt;a href="http://userscripts.org/scripts/show/70637" target="_blank"&gt;userscripts.org&lt;/a&gt; so that anyone can use it. The script will automatically remove the sidebar so that zooming works much better. You can even change the script to automatically zoom a specified amount, however I left this off by default since the right amount highly depends on the width of your screen. Here are the results:&lt;/p&gt;  &lt;div align="center"&gt;   &lt;table border="1" cellspacing="0" cellpadding="2" width="602" align="center"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="300"&gt;&lt;center&gt;&lt;a href="http://lh3.ggpht.com/_G06mB5h-kvQ/S5GWV3riLlI/AAAAAAAAGfE/2AmCt-x0ANI/s1600-h/Slashdot%20Fix%20Zoom%20User%20Script%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Slashdot Fix Zoom User Script" border="0" alt="Slashdot Fix Zoom User Script" src="http://lh6.ggpht.com/_G06mB5h-kvQ/S5GWWmEe4dI/AAAAAAAAGfM/p9MFdcpOcXY/Slashdot%20Fix%20Zoom%20User%20Script_thumb.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;&amp;#160;&amp;#160; &lt;br /&gt;Normal&lt;/center&gt;&lt;/td&gt;          &lt;td valign="top" width="300"&gt;&lt;center&gt;&lt;a href="http://lh3.ggpht.com/_G06mB5h-kvQ/S5GWXMedIuI/AAAAAAAAGfU/rX5HtFUQnsQ/s1600-h/Slashdot%20Fix%20Zoom%20User%20Script%20%28zoomed%29%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Slashdot Fix Zoom User Script (zoomed)" border="0" alt="Slashdot Fix Zoom User Script (zoomed)" src="http://lh6.ggpht.com/_G06mB5h-kvQ/S5GWX8y1qaI/AAAAAAAAGfc/PlaFWwHMlac/Slashdot%20Fix%20Zoom%20User%20Script%20%28zoomed%29_thumb.png?imgmax=800" width="244" height="184" /&gt;&lt;/a&gt;             &lt;br /&gt;Zoomed&lt;/center&gt;&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Hopefully someone else will find this useful. I have a few other bookmarklets that I use and will probably convert into userscripts soon, as well as a few new ones that I want to work on when I get some free time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-3269897090282426206?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/NihRveHRFGg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/NihRveHRFGg/slashdot-zoom-fix-greasemonkey-and.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2010/03/slashdot-zoom-fix-greasemonkey-and.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-209502873748720276</guid><pubDate>Fri, 19 Feb 2010 23:08:00 +0000</pubDate><atom:updated>2010-03-04T15:13:58.478-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">PowerShell</category><category domain="http://www.blogger.com/atom/ns#">Cloud Computing</category><title>Powershell, 7-Zip, Amazon S3 Upload Script with AES-256 Encryption</title><description>&lt;p&gt;I recently was tasked with finding a way to store some backup files from our server in a secure and reliable off-site location. After talking with our hosting provider, who wanted around $600 a month for off-site tape rotation, we decided to look at using &lt;a href="http://aws.amazon.com/s3/" target="_blank"&gt;Amazon Simple Storage Service&lt;/a&gt; (Amazon S3) to store the files in the cloud instead. We needed a way to automate the upload process and make sure that the data was encrypted, so I spent a few days working on a Powershell script (using the &lt;a href="http://powergui.org" target="_blank"&gt;excellent PowerGui Script Editor&lt;/a&gt;) that uses &lt;a href="http://www.7-zip.org/" target="_blank"&gt;7-zip&lt;/a&gt; to create a .7z archive with AES-256 encryption and then send it up to Amazon S3 using the &lt;a href="http://aws.amazon.com/sdkfornet/" target="_blank"&gt;Amazon Web Services SDK for .NET&lt;/a&gt;. Here is the script:&lt;/p&gt;  &lt;p&gt;&lt;textarea class="brush:ps" rows="118" cols="80"&gt;
#Description: Powershell 2.0 script to zip and encrypt a folder using 7zip and then send it to Amazon S3
#Author: Greg Bray (2/19/2010)
#Website: http://codeblog.theg2.net/2010/02/powershell-7-zip-amazon-s3-upload.html
#License: free for personal or commercial use under the Creative Commons Attribution 3.0 United States License.
#Prerequisite: You must first install the latest version of 7Zip from http://www.7-zip.org/ (licensed under the GNU LGPL)
#Prerequisite: You must also install the Amazon Web Services SDK for .NET from http://aws.amazon.com/sdkfornet/ (licensed under the Apache License, Version 2.0)
#Recommended: I recommend using CloudBerry S3 Explorer for managing Amazon S3 files. http://cloudberrylab.com/default.aspx?page=cloudberry-explorer-amazon-s3
#Recommended: I recommend using http://PowerGui.org Script editor if you want to change or debug this script.

#Usage: ps7ZiptoAmazonS3 'BackupFolderPath' 'S3ObjectKey' 'TranscriptLogFile'
#  BackupFolderPath = Folder to backup (do not include a trailing slash)
#  S3ObjectKey = Object key where to store file on Amazon S3. Note: If object already exists on S3 it will be overwritten.
#  TranscriptLogFile = Optional log file where the transcript will be appended.
#NOTE: you also will need to set the Zip and Encrypt settings, Amazon S3 settings, and 7Zip/AWSSDK file paths below

&lt;#Example calling from another powershell script (with log file): 
&amp; 'c:\Backups\ps7ZiptoAmazonS3.ps1' 'c:\Backups\DataFolder' 'S3Backups/DataFolder.7z' 'c:\Backups\BackupLog.txt'
#&gt;
&lt;#Example calling from Run or task Scheduler: NOTE: may need to run "Set-ExecutionPolicy RemoteSigned" in powershell to allow unsigned local scripts to execute
powershell.exe -Command "&amp; 'c:\Backups\ps7ZiptoAmazonS3.ps1' 'c:\Backups\DataFolder' 'S3Backups/DataFolder.7z' 'c:\Backups\BackupLog.txt'"
#&gt;

#Check arguments and set variables
if ($args.count -ge 2) {
    $FolderPath = $args[0] #Local folder to encrypt and send to S3 (No trailing slash)
    $S3ObjectKey = $args[1] #Destination on S3 where file will be stored. Note: If object exists it will be overwritten.
    if ($args.count -ge 3) { #start logging transcript
        Start-Transcript $args[2] -Append | Out-Null
    }
} else { #Default preset arguments used if no values are provided
    $FolderPath = "c:\Backups\DataFolder"
    $S3ObjectKey = "S3Backups/DataFolder.7z"
}
 
write-host "`r`n`r`n" #Start log file with 2 blank lines 
$dtStart = [System.DateTime]::Now #Save start time to calculate total time below
write-host ($dtStart.ToString() + " - Script started")

#Zip and Encrypt settings
$EncryptionKey = "secret_password" #Data is encrypted using Strong AES-256 encryption. Recommended password size is 10-16 characters.
$TemporaryPath = "c:\Temp" #No trailing slash. Used to store zip file localy before uploading. File will be deleted after upload but not if there is an exception (see below).

#Amazon S3 account settings (See http://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key):
$S3AccessKeyID = "ABCDEFGHIJKLMNOPQRST" #Your Amazon S3 Access Ky ID
$S3SecretKeyID = "0123456789abcdefghijklmnopqrstuvwzyz" #Your Amazon S3 Secret Access Key
$S3BucketName = "S3BackupBucket" #S3 Bucket name where the file will be stored
Write-Host ($dtStart.ToString() + " - FolderPath:'$FolderPath' S3BucketName:'$S3BucketName' S3ObjectKey:'$S3ObjectKey'")


#Load AWS Assembly and Initialize 7Zip path (only runs once when debugging script)
if($7ZipPath -eq $null){
    $7ZipPath = "C:\Program Files\7-Zip\7z.exe" #Path to 7Zip
    $AWSDOTNETSDKPath = "C:\Program Files (x86)\AWS SDK for .NET\bin\AWSSDK.dll" #Path to Amazon SDK for x64 system. Remove " (x86)" when running on an x86 machine
    if (-not [System.IO.File]::Exists($AWSDOTNETSDKPath)) { #Try path for x86 system
         $AWSDOTNETSDKPath = $AWSDOTNETSDKPath.Replace(" (x86)","")
         if (-not [System.IO.File]::Exists($AWSDOTNETSDKPath)) { #File not found, throw exception
            write-error "ERROR: Cannot find Amazon Web Services SDK. Please download .NET SDK from http://aws.amazon.com/sdkfornet/ and update AWSDOTNETSDKPath in script."
            exit 2
         }
    }
    #Load AWS Assembly
    [Reflection.Assembly]::LoadFile($AWSDOTNETSDKPath) | Out-Null
}

#Function for computing Amazon S3 MD5 digest (128 bit base64 encoded) using System.Security.Cryptography.MD5
function Hash-MD5 ($file) {
    $cryMD5 = [System.Security.Cryptography.MD5]::Create()
    $fStream = New-Object System.IO.StreamReader ($file)
    $bytHash = $cryMD5.ComputeHash($fStream.BaseStream)
    $fStream.Close()
    return [Convert]::ToBase64String($bytHash)
}

#Zip and Encrypt files
Write-Host ([System.DateTime]::Now.ToString() + " - Zip and Encrypt Files")
$FolderName = $FolderPath.Substring($FolderPath.LastIndexOf("\")+1) #grab the name of the backup folder
$TimeStamp = [datetime]::Now.ToString("yyyy-MM-dd_HHmm") #Create unique timestamp string
$strFile = [String]::Format("{0}\{1}_{2}.7z", $TemporaryPath,$FolderName,$TimeStamp) #Create filename for the zip
#7z options: add, type 7z, Archive filename, Files to add (with wildcard. Change \* to \prefix* or \*.txt to limit files), compression level 9, password, encrypt filenames, Send output to host so it can be logged.
#See http://dotnetperls.com/7-zip-examples or the 7zip help file for more info on command line switches. 
#NOTE: -mx7 and -mx9 get around 10 to 1 compression for text files and take round 5 minutes for 1GB of data. Use -mx3 or -mx5 to increase speed but decrease compression level.
&amp; $7ZipPath "a" "-t7z" "$strFile" "$FolderPath\*" "-mx9" "-r" "-p$EncryptionKey" "-mhe" | out-host #Call 7z.exe to create archive file
if($LASTEXITCODE -ne 0){ #Detect errors from 7Zip. Note: 7z will crash sometimes if file already exists
        Write-Error "ERROR: 7Zip terminated with exit code $LASTEXITCODE. Script halted."
        exit $LASTEXITCODE
}

#Create Amazon PutObjectRequest. Details at http://docs.amazonwebservices.com/sdkfornet/latest/apidocs/html/T_Amazon_S3_Model_PutObjectRequest.htm
Write-Host ([System.DateTime]::Now.ToString()) " - Creating S3 PutObjectRequest"
$AmazonS3 = [Amazon.AWSClientFactory]::CreateAmazonS3Client($S3AccessKeyID, $S3SecretKeyID)
$S3PutRequest = New-Object Amazon.S3.Model.PutObjectRequest 
$S3PutRequest.BucketName = $S3BucketName
$S3PutRequest.Key = $S3ObjectKey
$S3PutRequest.FilePath = $strFile
Write-Host ([System.DateTime]::Now.ToString()) " - Compute File MD5 Digest"
$strMD5 = Hash-MD5($strFile) #NOTE: may take 5-30 seconds to compute digest for 1GB file.
$S3PutRequest.MD5Digest = $strMD5 #Use MD5 digest to ensure data is not corrupted during transport. 

$dFileSize = (Get-Item $strFile).Length / 1MB #Get archive size in MB
Write-Host ([System.DateTime]::Now.ToString()) ([String]::Format(" - Uploading File:'{0}' Size:{1:#,###.#} MB", $strFile, $dFileSize)) 
$S3Response = $AmazonS3.PutObject($S3PutRequest) #NOTE: upload defaults to 20 minute timeout.
#If upload fails it will throw an exception and $S3Response will be $null
if($S3Response -eq $null){
    Write-Error "ERROR: Amazon S3 put requrest failed. Script halted."
    exit 1
}

Write-Host ([System.DateTime]::Now.ToString()) " - Delete Local 7z File:'$strFile'"
Remove-Item $strFile -Force

$dtEnd = [datetime]::Now
$tsTotal = $dtEnd.Subtract($dtStart)
Write-Host ($dtEnd.ToString()) " - Script finished. Total time: " $tsTotal
write-host "`r`n`r`n" #End log file with 2 blank lines 

if ($args.count -ge 3) { #stop transcript
    Stop-Transcript
}
&lt;/textarea&gt;&lt;/p&gt;  &lt;p&gt;It seems to work pretty well so far, taking about 5-10 minutes to zip and encrypt 1GB of SQL Backups down to 100MB and then upload it to Amazon S3. From there we can use tools like &lt;a href="http://cloudberrylab.com/default.aspx?page=cloudberry-explorer-amazon-s3" target="_blank"&gt;CloudBerry S3 Explorer&lt;/a&gt; to browse or download files when needed. The monthly costs to keep data on Amazon S3 is $0.150 per GB, with $0.10 per GB transfer in and $0.150 per GB transfer out. With a 1 week backup retention and minimal data-out transfers we expect to pay around around $10 to $20 a month and should be able to access it much quicker than if we were using off-site tape storage. Cloud computing FTW!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-209502873748720276?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/VDfzwEX8O7U" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/VDfzwEX8O7U/powershell-7-zip-amazon-s3-upload.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://codeblog.theg2.net/2010/02/powershell-7-zip-amazon-s3-upload.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-8844505391198683781</guid><pubDate>Fri, 12 Feb 2010 23:58:00 +0000</pubDate><atom:updated>2010-02-14T01:06:21.439-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tips n Tricks</category><category domain="http://www.blogger.com/atom/ns#">Parallel Programming</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>Parallel ForEach file processing in IronPython: Get some TPL love in IPY!</title><description>&lt;p&gt;I recently have started playing around with the Task Parallel Library (TPL) that will be shipping in .NET 4, which lets you easily spread a workload across multiple cores using a simple Parallel.ForEach statement. I have a few IronPython scripts that I want to convert to start using multiple threads, so I thought I would try using the &lt;a href="http://codeblog.theg2.net/2010/02/tpl-and-parallelforeach-in-net-35-using.html" target="_blank"&gt;.NET 3.5 version of the TPL&lt;/a&gt; from inside of IronPython. It turns out that the TPL works just fine, but writing thread safe code in IronPython can be tricky. First off, the System.Threading.Interlocked class does not work on IronPython integers because &lt;a href="http://lists.ironpython.com/pipermail/users-ironpython.com/2008-November/008960.html" target="_blank"&gt;python integers are immutable&lt;/a&gt;. That really sucks, because it means that the only way to change a global integer value in a thread safe manner is to use &lt;a href="http://old.nabble.com/Converting-C--to-Python-...-the-lock()-keyword--td27114498.html" target="_blank"&gt;locks or the System.Threading.Monitor class&lt;/a&gt;. One interesting workaround is to use a python list instead of an integer. Appending a value to a list is an atomic operation, so instead of calling Interlocked.Add you can just append all the values to an empty list an use sum to return the aggregate value or len() to get the number of items in the list (emulating incrementing a variable). It is a bit of a hack, but sometimes easier that using locks. Also, you have to remember that the print statement is not thread safe, so instead you should use something like System.Text.StringBuilder to buffer your print statements and then print them once you are back to a single thread code section.&lt;/p&gt;  &lt;p&gt;Below is a small sample script that I wrote to test processing a large number of text files using IronPython. It will search through all files in a given directory that match a given pattern (ie: *.txt) and return the total number of files and lines. It will also search for a given tolken inside each file and return the total number of matches. This is a task that is very easy to run on multiple cores and is a perfect fit for the Parallel.ForEach method. By default it will search your temporary files folder, which on my workstation had 69 .txt files with a total of 469,286 lines. The single threaded version took about 2.3 seconds to run and the multi-threaded version took between 0.8 and 1.0 seconds. The workload was spread across 8 cores, which caused a 2x improvement in speed, even thought this example is still primarily bound by the drive IO speed. Still it shows how using the TPL can greatly increase performance for common tasks.&lt;/p&gt;  

&lt;textarea class="brush: py;" rows="130" cols="80"&gt;
"""Uses the Task Parallel Libray (TPL) to processes files using multiple threads.
Please download and install the Reactive Extensions (Rx) for .Net 3.5 from http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx before running this script
Usage: import the file into an existing script or run the following from the IronPython console:
execfile("c:\PathToFile\Filename.py")
"""
import clr
from System import Environment
from System.IO import File,Directory
from System.Diagnostics import Stopwatch
from System.Text import StringBuilder
from System.Threading import Monitor
clr.AddReference('System.Windows.Forms')


strAssembly = "C:\Program Files (x86)\Microsoft Reactive Extensions\Redist\DesktopV2\System.Threading.dll";
if not File.Exists(strAssembly): # Try both 32bit and 64bit file path
    strAssembly = "C:\Program Files\Microsoft Reactive Extensions\Redist\DesktopV2\System.Threading.dll";
    if not File.Exists(strAssembly): # Library does not exist, prompt with error message
        print "TPL assembly not found. Please download and install the Reactive Extensions (Rx) for .Net 3.5 from http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx"
        raise Exception("Task Parallel Libray not found. Please download and install the Reactive Extensions (Rx) for .Net 3.5");
        #Rx and TPL for .NET 3.5 can be downloaded from  http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

#Load TPL
clr.AddReferenceToFileAndPath(strAssembly)
from System.Threading.Tasks import *

#Method to process files. See test call at bottom of file
def TPLProcessFiles(strTolken, strPath=None, strFilter="*.txt"):
    """Finds all occurences of strTolken in strPath for files that match strFilter.
        strTolken = string tolken used for searching. NOTE: search is case-insensitive and includes partial match (cat will match Category).
        strPath = Path to the directory used for searching. Default is system's temp directory
        strFilter = file match filter for search. Default is *.txt"""
    print "Start TPLProcessFiles('%s', '%s', '%s')" % (strTolken, strPath, strFilter)
    
    if strPath == None:
        strPath = Environment.GetEnvironmentVariable("TEMP")
        print "Using temporary files path: %s" % strPath
    elif not Directory.Exists(strPath):
        raise Exception("Invalid path: " + strPath)
    
    #Setup
    swTime = Stopwatch()
    swTime.Start()
    LogWriter.Reset()
    Results.Reset()
    strFiles = Directory.GetFiles(strPath, strFilter)

    #Single thread test code. Useful for when you get an AggregateException_ctor_DefaultMessage exception in the Parallel.ForEach version or for benchmarking
    #for aFile in strFiles:
    #    SearchFile(aFile, strTolken)
    
    #TPL version with multiple threads
    pfeResult = Parallel.ForEach(strFiles, lambda aFile: SearchFile(aFile, strTolken))
    
    print LogWriter.ToString() #Have to use LogWriter class below because print is not a threadsafe function
    strResults = Results.ToString() #Have to store results in a thread safe class
    swTime.Stop()
    print "Finished. Total Files: %d  LogCallCount: %d   Total Time: %0.3fs  Total Cores: %d" % (len(strFiles), LogWriter.GetCallCount(), float(swTime.ElapsedMilliseconds)/1000, Environment.ProcessorCount)
    print "Results - %s" % strResults

#File search method    
def SearchFile(strFilename, strTolken):
    """Method used for searching a file. This will be called from the Parallel.ForEach loop.
        Returns a tuple of (Filename, Total line count, Total tolken count).
        NOTE: Code must be thread safe, so you cannot use the print statement or increment global variables."""
    #LogWriter.WriteLine("Start file: %s searching for %s" % (strFilename, strTolken))
    f = open(strFilename, "r") #open file as readonly
    t = f.read() #get text
    f.close()
    Results.Add(1, t.count("\n"),t.count(strTolken)) #Add to global results

#Class used to store results    
class Results:
    Files = 0 #static members
    Lines = 0
    Tolkens = 0   
    
    @staticmethod
    def Reset(): #NOTE: this is not thread safe, but we will only call this method from a single thread
        Results.Files = 0
        Results.Lines = 0
        Results.Tolkens = 0

    @staticmethod
    def Add(intFiles, intLines, intTolkens):
        Monitor.Enter(Results) #Use the System.Threading.Monitor class to ensure addition is thread safe
        Results.Files += intFiles
        Results.Lines += intLines
        Results.Tolkens += intTolkens
        Monitor.Exit(Results) #Finish thread safe code

    @staticmethod
    def GetValues():
        return (Results.Files, Results.Lines, Results.Tolkens)
        
    @staticmethod
    def ToString():
        return "Total files: %d  Total lines: %d  Total tolkens: %d" % Results.GetValues()
        
#Log writer class to buffer print statements    
class LogWriter:
    sbLog = StringBuilder() #StringBuilder is thread safe when used as a static member
    CallCount = [] #Integer operations are not threadsafe, but appending to a list is
    
    @staticmethod
    def WriteLine(strMessage): #NOTE: must be thread safe. String 
        LogWriter.sbLog.Append(strMessage+"\r\n")
        LogWriter.CallCount.append(1)
    
    @staticmethod
    def ToString():
        return LogWriter.sbLog.ToString()
    
    @staticmethod
    def Reset():
        LogWriter.sbLog.Length = 0
        LogWriter.intCallCount = []    

    @staticmethod
    def GetCallCount():
        return sum(LogWriter.CallCount)

        
if __name__ == "__main__":
    TPLProcessFiles("Error") #Run test if this file is loaded from the IronPython Console
&lt;/textarea&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-8844505391198683781?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/g2A5pipxbdI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/g2A5pipxbdI/parallel-foreach-file-processing-in.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codeblog.theg2.net/2010/02/parallel-foreach-file-processing-in.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-764152777116694147</guid><pubDate>Sat, 06 Feb 2010 23:39:00 +0000</pubDate><atom:updated>2010-02-06T16:42:05.787-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Fun</category><category domain="http://www.blogger.com/atom/ns#">Parallel Programming</category><category domain="http://www.blogger.com/atom/ns#">Poker</category><title>TPL and Parallel.ForEach in .Net 3.5 using Reactive Extensions for .NET (Rx)</title><description>&lt;p&gt;The next version of the .Net framework and Visual Studio both have &lt;a href="http://codeblog.theg2.net/2010/01/vs2010-parallel-computing-features-tour.html" target="_blank"&gt;some pretty cool features&lt;/a&gt; to help programmers work with multiple cores, which is great but doesn’t help the majority of us that are stuck with .Net 3.5 for the foreseeable future. Luckily &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Erik-Meijer-and-Team-Cloud-Data-Programmability-Connecting-the-Distributed-Dots/" target="_blank"&gt;Erik Meijer and the Cloud Programability Team&lt;/a&gt; have back ported the &lt;a href="http://en.wikipedia.org/wiki/Parallel_Extensions" target="_blank"&gt;Parallel Extensions Framework (PFX)&lt;/a&gt; to .Net 3.5 and Silverlight 3 as part of the &lt;a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx" target="_blank"&gt;Reactive Extensions for .NET (Rx)&lt;/a&gt;. Rx adds the IObservable&amp;lt;T&amp;gt; and IObserver&amp;lt;T&amp;gt; interfaces, which are the mathematical duality of the IEnumerable&amp;lt;T&amp;gt; and IEnumerator&amp;lt;T&amp;gt; and provide tools for doing &lt;a href="http://www.leading-edge-dev.de/?p=501" target="_blank"&gt;Reactive Programming.&lt;/a&gt; There are &lt;a href="http://rxwiki.wikidot.com/101samples" target="_blank"&gt;many different ways to use Rx&lt;/a&gt;, but internally they all use the Task Parallel Library (TPL) as the “special sauce” to automate processing tasks across multiple threads.&lt;/p&gt;  &lt;p&gt;Parallel.ForEach is a part of the TPL that can be used to unroll an outer loop and have it run across multiple threads. Take the following example. This is standard single threaded code that loops through a collection of 2 card Texas Holdem starting hands and evaluates all possible 7 card hands that include those two cards:&lt;/p&gt; 

&lt;textarea class="brush: py;" rows="11" cols="80"&gt;
//Enumerate all possible 2 card starting hands with an Ace and a King
foreach (var aPKAK in HoldemHand.PocketHands.Query(&amp;quot;AK&amp;quot;))
{
    //Enumerate and score all possible 7 card hands that include the starting hand
    foreach (var aHand in HoldemHand.Hand.Hands(aPKAK, 0, 7))
    {
        ulHand = HoldemHand.Hand.Evaluate(aHand);
        lCount++;
    }
}
&lt;/textarea&gt;  

&lt;p&gt;There are over 2 million hands in the inner loop, which gets run once for each of the possible starting hands in the outer loop. There are 12 offsuit starting hands and 4 suited starting hands with an Ace and a King, which means that the outer loop would run 16 times, however those 16 executions are separate and could easily be run across multiple threads. That is where Parallel.ForEach comes in. Here is the same code, which will automatically be scheduled across multiple threads:&lt;/p&gt; 

&lt;textarea class="brush: py;" rows="12" cols="80"&gt;//Use Parallel.ForEach and a Lambda Expression to get the same results
Parallel.ForEach(HoldemHand.PocketHands.Query(&amp;quot;AK&amp;quot;), aPKAK =&amp;gt;
{
    long plcount = 0; //Local loop count
    foreach (var aHand in HoldemHand.Hand.Hands(aPKAK, 0, 7))
    {
        ulHand = HoldemHand.Hand.Evaluate(aHand);
        plcount++;
    }
    //Use threadsafe method to increment global count
    System.Threading.Interlocked.Add(ref lCount, plcount);
});
&lt;/textarea&gt;

&lt;p&gt;The bulk of the code is the same, with the only changes being that the inner block gets converted into a Lambda Expression (could have also used a delegate) and instead of incrementing lCount in the inner loop we increment a local loop variable and then atomically add it to the global value. We could have used System.Threading.Interlocked.Increment to atomically increment lCount inside the inner loop, but this adds a lot of unneeded locks that slow down all the threads. Keeping a local copy of the values and only locking once at the end provides much better performance.&lt;/p&gt;  &lt;p&gt;And with those few small changes we are able to start using multiple threads, which on my local machine with 4 cores and 8 threads ended up decreasing the processing time from 1.55 seconds to 0.67 seconds and more than doubling the number of hands processed per second from 16,420,998 to 37,816,595.&lt;/p&gt;  &lt;p&gt;If you want to start using the TPL you can download it &lt;a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx" target="_blank"&gt;here&lt;/a&gt; and add a reference to the System.Threading.dll located in the “C:\Program Files (x86)\Microsoft Reactive Extensions\Redist\DesktopV2” folder. And while you are at it you might as well play around with Rx too!&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-764152777116694147?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/CduhmccQhHw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/CduhmccQhHw/tpl-and-parallelforeach-in-net-35-using.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2010/02/tpl-and-parallelforeach-in-net-35-using.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-6031259373714016183</guid><pubDate>Wed, 20 Jan 2010 19:40:00 +0000</pubDate><atom:updated>2010-01-20T12:40:01.574-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Video</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><category domain="http://www.blogger.com/atom/ns#">Parallel</category><title>VS2010 Parallel Computing Features Tour: Wow!</title><description>&lt;p&gt;Microsoft Visual Studio 2010 and .NET Framework 4.0 are in beta 2 right now and should be available in a few months, but after watching videos about the features of &lt;a href="http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-optional-parameters-more-COM-friendly/" target="_blank"&gt;C# 4.0&lt;/a&gt; and the features of Visual Studio 2010 I don’t know how much longer I can wait! I just finished watching a video about the &lt;a href="http://channel9.msdn.com/posts/DanielMoth/VS2010-Parallel-Computing-Features-Tour/" target="_blank"&gt;parallel computing features in VS2010&lt;/a&gt; and I seriously am drooling over the multi-core programming tools available in the next release! C# 4.0 was introduced by &lt;a href="http://channel9.msdn.com/pdc2008/TL16/" target="_blank"&gt;Anders Hejlsberg at PDC 2008&lt;/a&gt;, but it is great to see it finally coming to fruition. And with .NET 4 splitting the download into &lt;a href="http://channel9.msdn.com/posts/Jaime+Rodriguez/NET-4-Client-Profile/" target="_blank"&gt;Client and Full profiles&lt;/a&gt; it now can be downloaded and installed on most machines at about half the size (30-40MB vs 70-160MB for .NET 3.5).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-6031259373714016183?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/ks5uTenWOPc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/ks5uTenWOPc/vs2010-parallel-computing-features-tour.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2010/01/vs2010-parallel-computing-features-tour.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-6314031986436168457</guid><pubDate>Thu, 03 Dec 2009 23:56:00 +0000</pubDate><atom:updated>2009-12-03T16:56:58.147-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Watin</category><category domain="http://www.blogger.com/atom/ns#">Testing</category><title>Watin 2.0 and Gallio 3.1 in x64 environment: fixing System.Reflection.ReflectionTypeLoadException and System.Runtime.InteropServices.COMException "The interface is unknown" issues</title><description>&lt;p&gt;We use &lt;a href="http://www.gallio.org/" target="_blank"&gt;Gallio/MbUnit&lt;/a&gt; and &lt;a href="http://watin.sourceforge.net/"&gt;Watin&lt;/a&gt; at my work for unit testing of an ASP.NET website, as it provides &lt;a href="http://www.theroamingcoder.com/node/22" target="_blank"&gt;excellent reports&lt;/a&gt; including the raw Watin events (click, type, select) and &lt;a href="http://blog.benhall.me.uk/2007/12/watin-integration-into-mbunitgallio.html" target="_blank"&gt;screenshots for failed cases&lt;/a&gt;. Today I spent a few hours trying to get the project working on my new Windows 7 x64 development machine, and things did not start out very well. When I first tried to load the project in the Gallio Icarus runner none of the unit tests showed up and it indicated that an exception was thrown while exploring tests. I tried using both the x64 and x86 versions of Gallio/MbUnit, and even tried using the &lt;a href="http://testdriven.net/" target="_blank"&gt;TestDriven.NET&lt;/a&gt; loader from within Visual Studio, but couldn’t get anything to work. Here is the full error message for Google’s sake:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;[error] An exception was thrown while exploring tests.
Location: D:\SVN_Development\OQA Unit Testing\OQA Testing Framework\OQA Testing Framework\bin\Debug\OQA Testing Framework.EXE
Reference: OQA Testing Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Details: System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. 
   at System.Reflection.Module._GetTypesInternal(StackCrawlMark&amp;amp; stackMark) 
   at System.Reflection.Assembly.GetTypes() 
   at Gallio.Common.Reflection.Impl.NativeAssemblyWrapper.GetTypes() in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Common\Reflection\Impl\NativeAssemblyWrapper.cs:line 72 
   at Gallio.Framework.Pattern.TestAssemblyPatternAttribute.PopulateChildrenImmediately(IPatternScope assemblyScope, IAssemblyInfo assembly) in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Framework\Pattern\TestAssemblyPatternAttribute.cs:line 147 
   at Gallio.Framework.Pattern.TestAssemblyPatternAttribute.Consume(IPatternScope containingScope, ICodeElementInfo codeElement, Boolean skipChildren) in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Framework\Pattern\TestAssemblyPatternAttribute.cs:line 75 
   at Gallio.Framework.Pattern.DefaultPatternEvaluator.Consume(IPatternScope containingScope, ICodeElementInfo codeElement, Boolean skipChildren, IPattern defaultPrimaryPattern) in c:\RelEng\Projects\MbUnit v3.1\Work\src\Gallio\Gallio\Framework\Pattern\DefaultPatternEvaluator.cs:line 153&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The error message indicates that it is due to an issue with missing assemblies, and suggested that you make sure the CopyLocal option is set to true for all 3rd party references, but that didn’t help either. Finally I created a test project and started ripping the original project to peaces to find out why it was failing. Turns out it worked fine if I remove a reference to an interface stored in the Watin.Core.Dll assembly, so I setup a workaround and was finally able to load the tests. Only problem was that it would fail whenever the test tried to load Watin. At this point I figured it had to be an issue with the Watin dll, and it turns out that it was simply trying to load an x64 version of the library that doesn’t actually exist (the library is x86 only). &lt;a href="http://stackoverflow.com/questions/916769/watin-error-cannot-load" target="_blank"&gt;This link&lt;/a&gt; suggested setting Visual Studio to use x86 as the build platform type instead of “Any CPU”, and once I did that the original project started working. Yay!&lt;/p&gt;

&lt;p&gt;It didn’t take long though for something else to fail, as it threw an exception as soon as one of the tests tried to access the Document object. This time the exception was System.Runtime.InteropServices.COMException with Message=&amp;quot;The interface is unknown. (Exception from HRESULT: 0x800706B5)&amp;quot; coming from mshtml.HTMLDocumentClass.IHTMLDocument2_get_url(). Another quick search lead to another &lt;a href="http://stackoverflow.com/questions/1014815/how-do-you-get-watin-to-work-on-windows-server-2008-with-ie8" target="_blank"&gt;StackOverflow answer&lt;/a&gt; suggesting to run Visual Studio as an Administrator. That seem to do the trick!&lt;/p&gt;

&lt;p&gt;So if you are using an x64 machine to do unit testing with Gallio, MbUnit, and Watin, make sure to set the platform to x86 and make sure to run Visual Studio and Icarus as an Administrator! I should probably get back to working on those unit tests now :-P&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-6314031986436168457?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/32jXDA1qnEI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/32jXDA1qnEI/watin-20-and-gallio-31-in-x64.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/12/watin-20-and-gallio-31-in-x64.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-5633059212620007688</guid><pubDate>Tue, 10 Nov 2009 20:52:00 +0000</pubDate><atom:updated>2009-11-10T15:04:07.179-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tips n Tricks</category><category domain="http://www.blogger.com/atom/ns#">Bookmarklet</category><category domain="http://www.blogger.com/atom/ns#">Video</category><category domain="http://www.blogger.com/atom/ns#">CSS</category><category domain="http://www.blogger.com/atom/ns#">HTML</category><title>Channel 9 Full Screen Video Player: My first Bookmarklet</title><description>&lt;p&gt;I really enjoy watching videos from &lt;a href="http://channel9.msdn.com" target="_Blank"&gt;Channel 9&lt;/a&gt;, Microsoft’s community site that targets users and developers. It is a great way to keep updated on the latest technologies and learn more about future products before they come out. The only thing that I don’t like is that the website is not very user friendly for people that have multiple monitors. This surprises me, as most developers that I know use at least two monitors, sometimes three or four. Even after their recent layout change, which increased the size of the video player significantly, the embedded video player is still too small to be able to read code from screencasts. There is of course a full screen button, but this doesn’t really work when multitasking on multiple monitors as it will close as soon as you click on another browser or window on another screen. Both Silverlight and Flash have this issue, which they consider to be a security feature, but it renders the full screen mode worthless useless you stop using your second monitor while watching the video. &lt;/p&gt;  &lt;p&gt;Currently there are only two workarounds to the Silverlight/Flash full screen issue, both of which &lt;a href="http://www.youtube.com/watch?v=Mh85R-S-dh8" target="_Blank"&gt;YouTube&lt;/a&gt; has already implemented using buttons at the top of the video player. The first is enlarging the video so that it takes up more of the page, and the second is opening it in a new page that can be resized to as large or small as you want. Alternatively you can use a different video player such as the embedded Windows Media Player, but while the WMV links on Channel 9 display full screen in the browser they sometimes have buffering or quality issues and cannot take advantage of the &lt;a href="http://www.iis.net/media/experiencesmoothstreaming" target="_Blank"&gt;Smooth Streaming&lt;/a&gt; that the Silverlight player can offer. All I really wanted was a way to enlarge the video to fit the full width of the browser window, so I figured why not just write a script to do it?&lt;/p&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Bookmarklet" target="_Blank"&gt;Bookmarklets&lt;/a&gt; are essentially small snippets of javascript code that live in a browser’s favorites and do simple things like &lt;a href="http://www.mitchelaneous.com/2009/02/26/wikipedia-bookmarklet-for-your-desktop-research/" target="_Blank"&gt;opening a Wikipedia box for searching&lt;/a&gt;, &lt;a href="http://www.makeuseof.com/tag/google-reader-tools-tips/" target="_Blank"&gt;Subscribe/Share/Note&lt;/a&gt; the current webpage in Google Reader, using &lt;a href="http://googlesystem.blogspot.com/2009/10/google-sidewiki-bookmarklet.html" target="_Blank"&gt;Google SideWiki&lt;/a&gt;, or &lt;a href="http://www.amazon.com/wishlist/get-button" target="_Blank"&gt;adding any item to an Amazon Wishlist&lt;/a&gt;. Due to cross-site scripting restrictions implemented in most browsers they are relatively safe, so they shouldn’t be able to drain your bank account or spam all your friends on Facebook. Plus unlike &lt;a href="http://en.wikipedia.org/wiki/Greasemonkey" target="_Blank"&gt;Greasemonkey&lt;/a&gt; scripts they will only run when you click on the link in your favorites, so they won’t slow down or change your normal browsing habits. This seems like a perfect fit for resizing the Silverlight video player on Channel 9. &lt;/p&gt;  &lt;p&gt;So after dissecting the way that the Google bookmarklets worked I started coding my own. If you want to try it out you can simply drag this link to your favorites (or right click and select "Add to Favorites"): &lt;a href="javascript:b=document.body;if(b&amp;amp;&amp;amp;!document.xmlVersion){void(z=document.createElement('script'));void(z.src='http://www.theg2.net/bookmarklets/C9SLFullScreen.js');void(b.appendChild(z));}else{alert('Bookmarklet-Failed');}"&gt;C9FullScreen&lt;/a&gt; and then click on the new link that it created after browsing to your &lt;a href="http://channel9.msdn.com/shows/PingShow/Ping-37-SQL-Server-WIndows-7-Bing-Google-Bill-Gates-Birthday/" target="_Blank"&gt;favorite Channel 9 video&lt;/a&gt;. To see how it works, here is the code that gets embedded into the C9FullScreen link:&lt;/p&gt;  &lt;textarea class="brush: js;" rows="1" cols="75"&gt;javascript:b=document.body;if(b&amp;amp;&amp;amp;!document.xmlVersion){void(z=document.createElement('script'));void(z.src='http://www.theg2.net/bookmarklets/C9SLFullScreen.js');void(b.appendChild(z));}else{alert('Bookmarklet-Failed');}&lt;/textarea&gt;   &lt;p&gt;And here is the script that gets injected into the page to resize the video:&lt;/p&gt;

&lt;textarea class="brush: js;" rows="80" cols="75"&gt;
//C9FullScreen: Increases the size of the Silverlight player to the full width of the window
//Works with Internet Explorer, Safari, Firefox, and Chrome
//Author: Greg Bray
//Information: http://codeblog.theg2.net/2009/11/channel-9-full-screen-video-player-my.html
//Blog: http://blog.theg2.net
//License: Released to Public Domain

//alert('Start JS Code');

//Reverse a string. Used to get PID from URL
//Code From: http://www.bytemycode.com/snippets/snippet/400/
String.prototype.reverse = function(){
    splitext = this.split("");
    revertext = splitext.reverse();
    reversed = revertext.join("");
    return reversed;
}

//Method to enlarge the Channel 9 Silverlight Player.
function C9SLFullScreen(){
    var b=document.body;
    var d=document.getElementById('ctl00_MainPlaceHolder_Starter_MediaPlayer');
    if(d){
        //Good test video is http://channel9.msdn.com/posts/Charles/Introducing-Click-to-Run-in-Office-2010/
        //alert("Player DIV found. Now check if Silverlight Player is already loaded.");
        o = d.getElementsByTagName('object');
        if(o.length==1){ //Video is already playing
            //alert('Player already loaded. Clear player and grab URL/PID');
            if(navigator.userAgent.toLowerCase().indexOf('chrome/') &gt; -1){
                alert('Player has already loaded. Resizing the video in Chrome will cause the player to load a partial version of the clip from the cache. Please refresh the page and try going C9FullScreen before starting the video.');
            } else {
                myregexURL = /m=(.+),autostart=/ //Regex to get video URL from object
                myregex = /\/ch9((?:\/\d)+)\// //Regex to get pid from video url
                mURL=myregexURL.exec(d.getElementsByTagName('object')[0].getElementsByTagName('param')[1].value)[1]; 
                mpID= myregex.exec(mURL); //Match regex
                pID = mpID[1].replace(/\//g,"");
                pID = pID.reverse();
                //alert("pID:"+pID+"\r\n"+mURL);
                d.removeChild(o[0]);//Remove active Silverlight object. Use o[0] to reference the player object
            }
        } else { //Video player not loaded. Grab movie url and pid.
            myregex = /\/ch9((?:\/\d)+)\//
            mURL=d.getElementsByTagName('a')[0].href; 
            mpID= myregex.exec(mURL); //Match regex
            pID = mpID[1].replace(/\//g,"");
            pID = pID.reverse();
            //alert("pID:"+pID+"\r\n"+mURL);
        }

        //Hide bar at top
        document.getElementById("cb_main").style.display = "none";
        document.body.style.padding = "0 0 0 0";
        //Get window size (Leave a little extra as some browsers will act strange with the scroll bar.
        var h = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
        var w = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
        z=document.createElement('div');
        //Set Style (see http://www.comptechdoc.org/independent/web/cgi/javamanual/javastyle.html)
        //z.style.position = "absolute";
        //z.style.left = "20px";
        //z.style.top = "200px";
        intW = (w-35);
        intH = (h-20);
        z.style.width = intW+"px";
        z.style.height = intH+"px";
        z.style.marginLeft = "5px";
        z.style.marginTop = "5px";
        z.style.marginBottom = "10px";
        z.style.backgroundColor = "LightGrey";
        z.style.border = "medium solid black";
        //z.innerHTML = s;//'&lt;center&gt;'+s+'&lt;/center&gt;'; 
        bStart ="true"; //true=Starts onload, false=waits for click. Download will start immediatly, so true is recommended. NOTE: the AutoHide feature does not work (must be set to true otherwise it is always hidden).
        z.innerHTML = '&lt;object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="'+intW+'" height="'+intH+'"&gt;&lt;param name="source" value="http://channel9.msdn.com/App_Themes/default/vp09_06_22.xap" /&gt;&lt;param name="initParams" value="m='+mURL+',autostart='+bStart+',autohide=true,showembed=true,postid='+pID+'" /&gt;&lt;param name="background" value="#00FFFFFF" /&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"&gt;&lt;img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/&gt;&lt;/a&gt;&lt;/object&gt;'       
        b.insertBefore(z, b.firstChild);
    }else{
        alert('ctl00_MainPlaceHolder_Starter_MediaPlayer not found. Make sure Channel 9 video page is loaded. Note: this does not work on the main homepage');
    }
}

C9SLFullScreen();
//alert('End JS Code');
&lt;/textarea&gt;
&lt;p&gt;And here is the result: A full screen video... Enjoy!&lt;/p&gt;
&lt;center&gt;&lt;a href="http://picasaweb.google.com/lh/photo/R1qcv4iIJf64PuISEBYNRw?authkey=Gv1sRgCKC0mp6P4ZPaGg&amp;feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_G06mB5h-kvQ/Svnf8EKSuLI/AAAAAAAABJ0/yWMQ5txFo_c/s800/PingC9FullScreen.jpg" /&gt;&lt;/a&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-5633059212620007688?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/liwBBQVOsww" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/liwBBQVOsww/channel-9-full-screen-video-player-my.html</link><author>noreply@blogger.com (Greg Bray)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_G06mB5h-kvQ/Svnf8EKSuLI/AAAAAAAABJ0/yWMQ5txFo_c/s72-c/PingC9FullScreen.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/11/channel-9-full-screen-video-player-my.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-2638797829242021985</guid><pubDate>Mon, 09 Nov 2009 04:51:00 +0000</pubDate><atom:updated>2009-11-08T21:51:44.321-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tips n Tricks</category><category domain="http://www.blogger.com/atom/ns#">Video</category><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Testing</category><category domain="http://www.blogger.com/atom/ns#">Analysis</category><title>Short .Net Reflector Training Video from Pluralsight</title><description>&lt;p&gt;Today’s &lt;a href="http://www.simple-talk.com/" target="_blank"&gt;Simple-Talk newsletter&lt;/a&gt; had a video from &lt;a title="http://www.pluralsight.com" href="http://www.pluralsight.com" target="_blank"&gt;http://www.pluralsight.com&lt;/a&gt; that talked about the basic features of &lt;a href="http://www.red-gate.com/products/reflector/" target="_blank"&gt;Red Gate’s .NET Reflector.&lt;/a&gt; If you are not familiar with the .NET Reflector, I highly recommend you give it a try, as it is by far one of the best .NET tools available. &lt;a href="http://www.pluralsight.com/main/partnerPrograms/redgate.aspx?utm_source=redgate&amp;amp;utm_medium=newsletter&amp;amp;utm_campaign=reflector1" target="_blank"&gt;This short 14 minute video&lt;/a&gt; walks you through most of the features of the program and shows you why it can be so useful. I’ve used .NET Reflector for system testing or when a library’s documentation is incomplete or out of date. The video doesn’t cover the Analyze feature for finding all class references and dependencies, and it doesn’t talk about all the &lt;a href="http://www.codeplex.com/reflectoraddins" target="_blank"&gt;cool plug-ins&lt;/a&gt; you can add, but it does provide a great introduction to a very powerful tool!&amp;#160; &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-2638797829242021985?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/WYhqR5fztQY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/WYhqR5fztQY/short-net-reflector-training-video-from.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/11/short-net-reflector-training-video-from.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-724712821167903293</guid><pubDate>Sun, 01 Nov 2009 23:15:00 +0000</pubDate><atom:updated>2009-11-01T16:20:44.514-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Fun</category><category domain="http://www.blogger.com/atom/ns#">Analysis</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><category domain="http://www.blogger.com/atom/ns#">Poker</category><title>Texas Holdem Hand Equity Calculation in IronPython</title><description>&lt;p&gt;This year I have been working in my free time to create &lt;a href="http://blog.theg2.net/2009/10/ironpython-texas-holdem-poker.html" target="_blank"&gt;easy to use Texas Holdem poker spreadsheets&lt;/a&gt; based on IronPython using &lt;a href="http://www.resolversystems.com/" target="_blank"&gt;Resolver One&lt;/a&gt;. These spreadsheets can be used to calculate Win/Tie/Loss odds, but some people like to use hand equity instead since it represents a player’s overall stake in the pot. Equity of 1.0 or 100% means that they will win the entire pot, where as equity of 0.5 (50%) or 0.25 (25%) means that they will split the pot with other players. You can again use Monte Carlo analysis to run a number of trials before all of the board cards are dealt to estimate a player’s current equity in the hand. This means that if during 4 trials I would win 2 of them and split the pot with one other player on the other 2, then my equity would be (1.0+1.0+0.5+0.5)/4 =&amp;#160; 3/4 or 75%.&lt;/p&gt;  &lt;p&gt;Calculating Win/Tie/Loss statistics on an independent player vs player basis is very simple, as the player’s pocket cards are evaluated against each opponent one at a time to show which opponent hands are stronger or weaker than your own. This does not take into account how the pocket cards of other opponents might change the odds, since in reality you usually play verse a table of opponents not just one opponent at a time. Changing the spreadsheet to work against the whole table would require changing the Monte Carlo simulation from a “row by row” analysis to a “table by table” analysis, where by you setup a table of opponents using a random hand for each player given the information that you have about their hand (AK, KK or QQ, Group1, etc..) and then generate a random 5 card hand based on the currently dealt cards. &lt;/p&gt;  &lt;p&gt;There are a lot of issues that you have to watch out for in this type of &lt;a href="http://www.codingthewheel.com/archives/multiway-ranged-isometric-equity-calculation-in-poker-1" target="_blank"&gt;Multiway Isometric Ranged Equity Calculation&lt;/a&gt;, but the basics are simple so long as you have a method of comparing multiple player’s hands for a given board. The &lt;a href="http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup#pokersource_keithrule" target="_blank"&gt;C# poker library&lt;/a&gt; that I use is mainly focused on heads-up hands, but it only took me about an hour to whip up a method that would take a board setup and a list of player pocket hands and return the scored value and equity for each hand as well as the highest ranked hand and a list of the winners. Here’s the code:&lt;/p&gt; 
&lt;textarea class="brush: py;" rows="59" cols="75"&gt;
#This function can be used to calculate equity for multiple hands and a given board
def HandEquity(ulBoard, lstulHands, bPrintResults=False):
    &amp;quot;&amp;quot;&amp;quot;Used to calculate hand equity for a given 5 card poker hand and a list of players hands. If a hand wins then it's equity is 1, a loss is 0, and a tie is 1/n where n is the number of hands that tie.
        ulBoard: A 5 card hand for the board represented as a 52 bit mask in an unsigned long. Use HoldemHand.Hand.ParseHand method to parse &amp;quot;Ac Kd Th 3c 2d&amp;quot; type strings into bitmasks.
        lstulHands: a list of 2 card pocket hand masks as unsigned longs. Invalid hands that duplicate board cards are accepted but will get None for their score and equity. Use Use HoldemHand.Hand.ParseHand(&amp;quot;Ac Kc&amp;quot;) or HoldemHand.PocketHands.Query(&amp;quot;AK&amp;quot;).ToArray() to get hand masks.
        bPrintResults: True will print the results to the console. Use False for fastest results. NOTE: change 'pass #print' or '#print' lines to 'print' to enable more detailed debug messages 
    Returns a tuple of (lstintScores, lstfEquity, intHighScore, lstHighScorers):
        lstintScores = integer representing the scored value for each hand. If hand is invalid given the board cards, value will be None.
        lstfEquity = float representing the hand's equity. If hand is invalid given the board cards, value will be None. Sum of all valid hands will equal 1.
        intHighScore = integer representing the highest scored value (ie what the winner(s) had). Use HoldemHand.Hand.DescriptionFromHandValueInternal(intHighScore) to get a string description
        lstHighScorers = list of the index to each of the winners. use len(lstHighScorers) to find out how many winners there were.
    Example:
        testBoard = ((288&amp;lt;&amp;lt; (13 * 3)) + (7&amp;lt;&amp;lt; (13 * 2))) #0b100100000000000000011100000000000000000000000000 is Ts 7s 4h 3h 2h
        testHands = [3, 3 &amp;lt;&amp;lt; 13, 3 &amp;lt;&amp;lt; (13*2), int('1100',2)] #3 is 0b11 for 3c 2c, &amp;quot;3 &amp;lt;&amp;lt; 13&amp;quot; is 3d 2d, &amp;quot;3 &amp;lt;&amp;lt; (13*2)&amp;quot; is 3h 2h, and int('1100',2) is 4c 5c
        (lstintScores, lstfEquity, intHighScore, lstHighScorers) = HandEquity(testBoard, testHands)&amp;quot;&amp;quot;&amp;quot;
    intTotalHands = len(lstulHands)     
    if intTotalHands &amp;lt; 1:
        raise Exception(&amp;quot;Error: lstulHands must have at least one hand.&amp;quot;)
    if HoldemHand.Hand.BitCount(ulBoard) != 5:
        raise Exception(&amp;quot;Error: ulBoard must be a 5 card hand.&amp;quot;)
    if(bPrintResults):
        print &amp;quot;Start HandEquity with %d hands and board cards: %s&amp;quot; % (intTotalHands, HoldemHand.Hand.MaskToString(ulBoard))
    lstintScores = [None]*intTotalHands #List that holds scores for all the handss
    lstfEquity = [None]*intTotalHands #List that holds equity values for all the hands
    intHighScore = -1 #The highest score currently found
    lstHighScorers = [] #list of the index for hands that currently have the highscore
    intScore = None #temp variable to hold the current score
    
    #NOTE: Hand equity will not be available until after this loop finishes!
    for intIndex,aHand in enumerate(lstulHands):
        if HoldemHand.Hand.BitCount(aHand) != 2:
            raise Exception(&amp;quot;Error: Pocket hands must contain 2 cards. lstulHands index %03d HandMask=0x%0.13X contains %d cards.&amp;quot; % (intIndex, aHand, HoldemHand.Hand.BitCount(aHand)))
        if(aHand &amp;amp; ulBoard == 0): #Make sure there are no duplicate cards on the board and hand first
            lstintScores[intIndex] = intScore = HoldemHand.Hand.Evaluate(aHand | ulBoard) #evaluate the hand and board cards to get the score
            if intScore &amp;gt; intHighScore:
                intHighScore = intScore #Set new high score
                lstfEquity[intIndex] = float(1)
                for aScoreIndex in lstHighScorers: #Reset old high scores equity to zero
                    lstfEquity[aScoreIndex] = 0
                lstHighScorers = [intIndex] #Reset high score list
            elif intScore == intHighScore: #There is a tied pot, so calculate partial equity
                lstHighScorers.append(intIndex) #Add this index to the current high score
                for aScoreIndex in lstHighScorers: #Reset old high scores equity to partial equity
                    lstfEquity[aScoreIndex] = 1 / float(len(lstHighScorers))
            else:
                lstfEquity[intIndex] = 0 #losing hand gets no equity
            #print &amp;quot;%03d: Hand %s score is %s (%d)&amp;quot; % (intIndex, HoldemHand.Hand.MaskToString(aHand), HoldemHand.Hand.DescriptionFromHandValueInternal(intScore),intScore)
        else:
            pass #print &amp;quot;%03d: Hand %s has duplicate cards. Score and Equity are None.&amp;quot; % (intIndex, HoldemHand.Hand.MaskToString(aHand))
    
    #Hand equity is now finished.
    if(bPrintResults): #Print results for each hand
        print &amp;quot;Best hand is '%s' with %d winner(s) getting %0.2f equity in the hand.&amp;quot; % (HoldemHand.Hand.DescriptionFromHandValueInternal(intHighScore), len(lstHighScorers), 1 / float(len(lstHighScorers)))
        for intIndex,aHand in enumerate(lstulHands):
            if(lstintScores[intIndex] == None):
                print &amp;quot;%03d: Hand %s HandScore=None      Equity=None.&amp;quot; % (intIndex, HoldemHand.Hand.MaskToString(aHand))                  
            else:
                print &amp;quot;%03d: Hand %s HandScore=%09d Equity=%0.2f.&amp;quot; % (intIndex, HoldemHand.Hand.MaskToString(aHand), lstintScores[intIndex], lstfEquity[intIndex])  
    return (lstintScores, lstfEquity, intHighScore, lstHighScorers) #Return Results
&lt;/textarea&gt;  &lt;p&gt;Here is a sample print-out when bPrintResults is True:&lt;/p&gt;  &lt;p&gt;testBoard = ((288&amp;lt;&amp;lt; (13 * 3)) + (7&amp;lt;&amp;lt; (13 * 2))) #0b100100000000000000011100000000000000000000000000 is Ts 7s 4h 3h 2h   &lt;br /&gt;testHands = [3, 3 &amp;lt;&amp;lt; 13, 3 &amp;lt;&amp;lt; (13*2), int('1100',2)] #Hands: 3c 2c, 3d 2d, 3h 2h, and 4c 5c    &lt;br /&gt;(lstintScores, lstfEquity, intHighScore, lstHighScorers) = HandEquity(testBoard, testHands, True)&lt;/p&gt;  &lt;p&gt;Start HandEquity with 4 hands and board cards: Ts 7s 4h 3h 2h   &lt;br /&gt;Best hand is 'Two pair, Three's and Two's with a Ten for a kicker' with 2 winner(s) getting 0.50 equity in the hand.    &lt;br /&gt;000: Hand 3c 2c HandScore=033622016 Equity=0.50    &lt;br /&gt;001: Hand 3d 2d HandScore=033622016 Equity=0.50    &lt;br /&gt;002: Hand 3h 2h HandScore=None&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Equity=None    &lt;br /&gt;003: Hand 5c 4c HandScore=016942384 Equity=0.00&lt;/p&gt;  &lt;p&gt;This is just a first step towards a full table Monte Carlo Simulator, but it gives you all of the details that are needed to find the winner(s) for a hand and calculate hand equity. The code used to generate a random board would be the same as in the other poker spreadsheets, but the player hand selection logic would need to use some sort of Round Robin algorithm to make sure that each player gets equal access to all of their possible pocket cards. Then you would use the HandEquity method to calculate the player’s equity for each hand and aggregate the results. My next goal is to change the spreadsheet code to use multiple threads, so I probably won’t tackle multi-way analysis anytime soon. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-724712821167903293?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/9q_mINOIjpg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/9q_mINOIjpg/texas-holdem-hand-equity-calculation-in.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/11/texas-holdem-hand-equity-calculation-in.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-8568786967779591637</guid><pubDate>Fri, 02 Oct 2009 04:15:00 +0000</pubDate><atom:updated>2009-10-01T22:15:10.572-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Over Complicated</category><category domain="http://www.blogger.com/atom/ns#">Hardware</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>Windows 7 Issues with JMicron JMB36X Controller in AHCI mode</title><description>&lt;p&gt;I had a lot of issues when &lt;a href="http://codeblog.theg2.net/2009/05/installing-windows-7-on-asus-p6t-with.html" target="_blank"&gt;setting up a RAID controller when installing Windows 7&lt;/a&gt; a few months ago, and today I had more problems trying to get an IDE drive to work in the same machine. The ASUS P6T motherboard has two hard drive controllers: one Intel ICH10R SATA controller for the 6 red SATA ports, and one JMicron controller for the two orange SATA ports and the single IDE connection. When I installed an old IDE hard drive to the JMicron controller, it was recognized in Windows but I was never able to format the drive. It kept saying that the window needed to be refreshed or that I needed to reboot the machine.&lt;/p&gt;  &lt;p&gt;After trying a few times with no progress, I decided to check and see if there was any &lt;a href="http://support.asus.com/download/download.aspx?model=P6T&amp;amp;SLanguage=en-US" target="_blank"&gt;updated drivers on the ASUS website&lt;/a&gt;. Turns out there was a recent BIOS update for the JMB322 firmware, so I download it to a jump drive, rebooted the computer and used the EZ Flash 2 utility built into the BIOS to run the update (I love this feature!) After changing the ICH10R settings back to RAID and setting the volume to be the primary hard drive and default boot device I was able to load back into Windows, but now there was another issue: There were two JMicron JMB36X devices listed in the device manager and only one of them was working.&lt;/p&gt;  &lt;p&gt;I tried removing both of them, thinking that one was a duplicate, but they both were detected again and one of them always listed “This device cannot start. (Code 10)” as the error message. The BIOS settings had the JMicron controller setup as AHCI mode, but no matter what I tried I could not get it to work. I even tried the latest drivers right from the &lt;a href="ftp://driver.jmicron.com.tw/jmb36x/XP_Vista_Win7/" target="_blank"&gt;JMicron website&lt;/a&gt;, but still nothing.&lt;/p&gt;  &lt;p&gt;Finally I tried changing the JMicron Controller settings from AHCI to IDE, and it started working again. This time I could detect the drive and the formatting worked just fine. Seems like the P6T motherboard still has a few bugs to work out specifically with the SATA and IDE controllers when using Windows 7 64bit edition. If I had to do it again I would probably ditch the hardware RAID array and instead buy an SSD drive for much better performance and a lot less headaches trying to set things up. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-8568786967779591637?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/9gT9LrvQoWc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/9gT9LrvQoWc/windows-7-issues-with-jmicron-jmb36x.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/10/windows-7-issues-with-jmicron-jmb36x.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-1551871316033146968</guid><pubDate>Tue, 15 Sep 2009 17:21:00 +0000</pubDate><atom:updated>2009-09-15T11:21:30.131-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tips n Tricks</category><category domain="http://www.blogger.com/atom/ns#">Video</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">PowerShell</category><title>Powershell V2 training videos on Channel 9</title><description>&lt;p&gt;If you are a Windows system administrator and are not familiar with &lt;a href="http://en.wikipedia.org/wiki/Windows_PowerShell" target="_blank"&gt;Powershell&lt;/a&gt; yet, you &lt;a href="http://karlprosser.com/coder/2009/01/06/this-is-your-admin-life-you-have-to-script-powershell/" target="_blank"&gt;should be&lt;/a&gt;! Even programmers should find a .NET based command shell useful in many situations where they want to test an assembly or use it in a simple script. I just found out that Channel 9 has a &lt;a href="http://channel9.msdn.com/tags/PSV2/" target="_blank"&gt;PSV2 tag for all of their Powershell V2 videos&lt;/a&gt;, which cover different aspects of Powershell in a short video format. These videos don't appear to have a lot of views or comments, but they are definitely good learning material and could use a bit more exposure. Check out this one on &lt;a href="http://channel9.msdn.com/posts/philpenn/PowerShell-How-To-Variables-Types-and-Operators/" target="_blank"&gt;Variables, Types, and Operators&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt; &lt;center&gt;&lt;object classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" width="640" height="480" codebase="http://www.microsoft.com/Windows/MediaPlayer/"&gt; &lt;param name="Filename" value="http://ecn.channel9.msdn.com/o9/ch9/9/2/8/6/8/4/PowerShellAficionadoPart1_ch9.wmv"&gt; &lt;param name="AutoStart" value="false"&gt; &lt;param name="ShowControls" value="true"&gt; &lt;param name="BufferingTime" value="2"&gt; &lt;param name="ShowStatusBar" value="true"&gt; &lt;param name="AutoSize" value="true"&gt; &lt;embed src="http://ecn.channel9.msdn.com/o9/ch9/9/2/8/6/8/4/PowerShellAficionadoPart1_ch9.wmv" type="application/x-mplayer2" autostart="0" enabled="1" showstatusbar="1" showdisplay="1" showcontrols="1" pluginspage="http://www.microsoft.com/Windows/MediaPlayer/" CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,0,0" width="640" height="480"&gt;&lt;/embed&gt; &lt;/object&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;Also if you are using Powershell, I highly recommend using the now free &lt;a href="http://shelltools.wik.is/PowerShell_Analyzer" target="_blank"&gt;Powershell Analyzer&lt;/a&gt; for creating and editing your scripts. I think that it still runs V1 of Powershell, but it is the best IDE that I have worked with so far. The &lt;a href="http://www.powershellplus.com/" target="_blank"&gt;Powershell Plus&lt;/a&gt; that replaced it just doesn't fit my needs quite as well.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-1551871316033146968?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/UlIVYkasxww" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/UlIVYkasxww/powershell-v2-training-videos-on.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/09/powershell-v2-training-videos-on.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-4931779463218946185</guid><pubDate>Sun, 13 Sep 2009 19:08:00 +0000</pubDate><atom:updated>2009-09-13T13:13:49.570-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">WPF</category><category domain="http://www.blogger.com/atom/ns#">Video</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">XAML</category><category domain="http://www.blogger.com/atom/ns#">Silverlight</category><title>Learn WPF on a Sunday Morning!</title><description>I have been working on a few projects that involve WPF and Silverlight these last few weeks, and I have to say that the learning curve is a bit steeper than I expected. I have worked with Windows Forms and ASP.NET Web Forms for a while and know most of the tricks regarding layout and data binding, but WPF brings a lot of new technology and features into the mix. I had tried to jump straight into Silverlight design using Expressions Blend, but I got lost and overwhelmed in the process. This weekend I took a step back and started with learning WPF, which is the way that applications are designed in Silverlight. There are a lot of great resources, but all I needed to get moving were a few videos from the &lt;a href="http://www.windowsclient.net/"&gt;www.WindowsClient.net&lt;/a&gt; website. Their &lt;a href="http://windowsclient.net/learn/videos_wpf.aspx" target="_blank"&gt;series on WPF&lt;/a&gt; showed the basics for layout and design options in a simple WPF application. Here are some good videos to get you started:&lt;br /&gt;
&lt;br /&gt;
1. &lt;a href="http://windowsclient.net/learn/video.aspx?v=76359" target="_blank"&gt;Creating a simple WPF application&lt;/a&gt; (&lt;em&gt;10:19)&lt;/em&gt;&lt;br /&gt;
2. &lt;a href="http://windowsclient.net/learn/video.aspx?v=76347" target="_blank"&gt;Using XAML in WFP&lt;/a&gt; (&lt;em&gt;10:34&lt;/em&gt;)&lt;br /&gt;
3. &lt;a href="http://windowsclient.net/learn/video.aspx?v=76354" target="_blank"&gt;Overview of the different layout panels in WPF&lt;/a&gt; (&lt;em&gt;14:05&lt;/em&gt;)&lt;br /&gt;
4. &lt;a href="http://windowsclient.net/learn/video.aspx?v=83530" target="_blank"&gt;Simple WPF Data Grid Editing using ListView and GridView&lt;/a&gt; (&lt;em&gt;31:03&lt;/em&gt;)&lt;br /&gt;
5. &lt;a href="http://windowsclient.net/learn/video.aspx?v=124419" target="_blank"&gt;WPF Effects&lt;/a&gt; (&lt;em&gt;11:41&lt;/em&gt;)&lt;br /&gt;
6.&amp;nbsp;&lt;a href="http://windowsclient.net/learn/video.aspx?v=13252" target="_blank"&gt;Host a WPF Control in a Win32 Application&lt;/a&gt;&amp;nbsp;(&lt;em&gt;19:59&lt;/em&gt;)&lt;br /&gt;
&lt;br /&gt;
There is plenty more to learn about WPF (Animations, Styles, Video, etc), but this is a great way to get a start using WPF.&lt;br /&gt;
&lt;br /&gt;
Enjoy!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-4931779463218946185?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/S1JRgfeTqgk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/S1JRgfeTqgk/learn-wpf-on-sunday-morning.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/09/learn-wpf-on-sunday-morning.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-3004715754935366215</guid><pubDate>Wed, 02 Sep 2009 22:25:00 +0000</pubDate><atom:updated>2009-09-02T16:25:12.914-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tips n Tricks</category><category domain="http://www.blogger.com/atom/ns#">XML</category><category domain="http://www.blogger.com/atom/ns#">MSSQL</category><title>Simple Talk article about TSQL Select For XML clause</title><description>&lt;p&gt;I had to do some work today creating a C# web service that would query a MS SQL database and return an XmlDocument with the results. After writing the query I tried loading the data into a DataTable and then using the WriteXML method to turn it into XML, but the layout wasn't exactly what I wanted and the use of a TableAdapter, StringWriter, XMLTextWriter, and XMLDocument seemed a bit excessive. I then remembered that MS SQL 2000, 2005, and 2008 support the &lt;a href="http://msdn.microsoft.com/en-us/library/ms190922.aspx" target="_blank"&gt;For XML clause&lt;/a&gt; on Select statements. I had read an article from Simple Talk a few months ago about the different options and by adding &amp;quot;FOR XML RAW ('LogEntry'), ROOT ('LogEntries')&amp;quot; to the end of the query I was able to get the SQL server to format the data for me and then use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executexmlreader.aspx" target="_blank"&gt;ExecuteXmlReader() method&lt;/a&gt; to create an XmlReader and load the data into an XmlDocument. The article is a great read for anyone that needs to work with XML data from an MS SQL server.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.simple-talk.com/sql/learn-sql-server/using-the-for-xml-clause-to-return-query-results-as-xml/"&gt;http://www.simple-talk.com/sql/learn-sql-server/using-the-for-xml-clause-to-return-query-results-as-xml/&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-3004715754935366215?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/h66PZyEL9Ag" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/h66PZyEL9Ag/simple-talk-article-about-tsql-select.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/09/simple-talk-article-about-tsql-select.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-6106012140418148920</guid><pubDate>Tue, 28 Jul 2009 06:32:00 +0000</pubDate><atom:updated>2009-07-28T00:32:50.892-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JavaScript</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Silverlight</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><category domain="http://www.blogger.com/atom/ns#">DLR</category><category domain="http://www.blogger.com/atom/ns#">HTML</category><title>.NET Dynamic Languages Deep Dive: Bring your scuba gear!</title><description>&lt;p&gt;So I’ve been playing around with &lt;a href="http://codeblog.theg2.net/search/label/IronPython" target="_blank"&gt;IronPython&lt;/a&gt; for a little while now and have been having a lot of fun learning to combine dynamic and static programming techniques. I haven’t tried to do anything too fancy yet, but using an &lt;a href="http://www.resolversystems.com" target="_blank"&gt;IronPython powered spreadsheet&lt;/a&gt; to create a &lt;a href="http://www.theg2.net/rsltexasholdem/" target="_blank"&gt;Texas Holdem Monte Carlo Simulator&lt;/a&gt; did show that you can get reasonably good performance just hacking away at a problem, even when there are a few extra levels of indirection, binding, and code generation added into the mix.&lt;/p&gt;  &lt;p&gt;Lately I’ve been keeping my Google Reader RSS feed full of cartoons, news, and blog posts, and I just barely got around to digesting Bruno Terkaly’s break down of &lt;a href="http://blogs.msdn.com/brunoterkaly/archive/2009/07/23/c-4-0-dynamic-language-runtime.aspx" target="_blank"&gt;C# 4.0 and the Dynamic Language Runtime&lt;/a&gt;. He uses his blog to do presentations, so there usually are a lot of diagrams and a few key paragraphs of text, but if you have been keeping up with the developments then the pictures really help to pull things into perspective.&lt;/p&gt;  &lt;p&gt;This post in particular was expanding on Jim Hugunin’s talk about the use of &lt;a href="http://channel9.msdn.com/pdc2008/TL10/" target="_blank"&gt;Dynamic Languages in Microsoft .NET&lt;/a&gt; from PDC 2008 almost a year ago. I had seen Anders Hejlsberg’s presentation about &lt;a href="http://channel9.msdn.com/pdc2008/TL16/" target="_blank"&gt;The Future of C#&lt;/a&gt;, but I hadn’t had a chance to watch the video about the DLR until today. If anyone is wondering why there is so much hype about the DLR, the new Dynamic type in C#/VB.NET, or the emergence of IronPython and IronRuby, I suggest taking a look at both of these videos, as they show what in my mind is the future of programming. These technologies have been picking up steam over the last year or two, but when .NET 4.0 and VS 2010 ship in the near future, I expect to see a lot more applications taking advantage of this new powerful platform.&lt;/p&gt;  &lt;p&gt;The DLR in particular is quite fascinating, in that it bridges the gap between Dynamic and Static languages, as well as creating a method for connecting .NET code to COM, Javascript, Python, Ruby, and whatever else you want to tie into it with a custom binder. Also, with the DLR being supported in Silverlight, there are a lot of new opportunities for running managed dynamic code directly from a browser. &lt;a href="http://visitmix.com/labs/gestalt/" target="_blank"&gt;Gestalt&lt;/a&gt; for instance is a newly released project hosted at the Microsoft mix online community labs, which has the goal of letting web developers replace or supplement their JavaScript code with &lt;a href="http://channel9.msdn.com/shows/The+Knowledge+Chamber/Gestalt-Nishant-Kothary-and-Joshua-Allen/" target="_blank"&gt;Ruby, Python &amp;amp; XAML&lt;/a&gt; directly embedded into HTML pages using the standard &amp;lt;Script&amp;gt; tags that get parsed by Javascript and Silverlight. Very interesting stuff! &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-6106012140418148920?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/Bz2c51e6TC4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/Bz2c51e6TC4/net-dynamic-languages-deep-dive-bring.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/07/net-dynamic-languages-deep-dive-bring.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-368954743983216714</guid><pubDate>Thu, 09 Jul 2009 22:20:00 +0000</pubDate><atom:updated>2009-07-09T17:02:19.516-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Fun</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>IronPython SpeechSynthesizer Mad Lib!</title><description>I just submitted a &lt;a href="http://www.resolversystems.com/exchange/sheets/73/" target="_blank"&gt;Mad lib Spreadsheet&lt;/a&gt; to the Resolver One Exchange that shows how to use the &lt;a href="http://msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer_members.aspx" target="_blank"&gt;System.Speech.Synthesis.SpeechSynthesizer&lt;/a&gt; class to make a talking Mad Lib. In case anyone else is looking to do Speech Synthesis from IronPython, I will post the code here as well.
&lt;textarea class="brush:python" cols="75" rows="25"&gt;
"""A Self Reading MadLib using the System.Speech.Synthesis.SpeechSynthesizer Object from .NET 3.5.
Usage:
Import the script, change the words or call AutoFill() and then call Speak()"""

import re 
import clr 
clr.AddReference("System.Speech") #Requires .Net 3.5 for Speech Recognition and Synthesis 
from System.Speech.Synthesis import SpeechSynthesizer #See http://msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer_members.aspx

synth = SpeechSynthesizer() 
#synth.SetOutputToWaveFile("c:\MadLib.wav") 

#Setup SSML to speak. See http://www.w3.org/TR/speech-synthesis/ 
#NOTE: use %(index)s for each word, which will get Interpolated in the Speak-Click method 
#Text taken from http://www.redkid.net/cgi-bin/madlibs/littleredriding.pl 
xmlSSML = """&lt;speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US"&gt;&lt;voice name="%(voice)s"&gt; 
&lt;s&gt;One day, Little &lt;emphasis level="strong"&gt;%(2)s&lt;/emphasis&gt; Riding Hood was going through the forest carrying a basket of &lt;emphasis level="strong"&gt;%(5)s&lt;/emphasis&gt; for her grandmother.&lt;/s&gt; 
&lt;s&gt;Suddenly, she met a big &lt;emphasis level="strong"&gt;%(1)s&lt;/emphasis&gt;wolf.&lt;/s&gt; 
&lt;s&gt;&lt;emphasis level="strong"&gt;%(3)s&lt;/emphasis&gt; said the wolf.&lt;/s&gt; 
&lt;s&gt;Where are you going, little &lt;emphasis level="strong"&gt;%(9)s?&lt;/emphasis&gt;&lt;/s&gt; 
&lt;s&gt;"I'm going to my grandmother's house," she said.&lt;/s&gt; 
&lt;s&gt;Then the wolf &lt;emphasis level="strong"&gt;%(4)s&lt;/emphasis&gt; away.&lt;/s&gt; 
&lt;s&gt;When Miss Riding Hood got to her grandmother's house, the wolf was in bed dressed like her grandmother.&lt;/s&gt; 
&lt;s&gt;"&lt;emphasis level="strong"&gt;My&lt;/emphasis&gt;, Grandmother," she said, "What big &lt;emphasis level="strong"&gt;%(6)s&lt;/emphasis&gt; you have."&lt;/s&gt; 
&lt;s&gt;"The better to &lt;emphasis level="strong"&gt;%(10)s&lt;/emphasis&gt; you with," said the wolf.&lt;/s&gt; 
&lt;s&gt;"And &lt;emphasis level="strong"&gt;Grandmother&lt;/emphasis&gt;," she said, "What big &lt;emphasis level="strong"&gt;%(7)s&lt;/emphasis&gt; you have."&lt;/s&gt; 
&lt;s&gt;The wolf said, "The better to &lt;emphasis level="strong"&gt;%(11)s&lt;/emphasis&gt; you with."&lt;/s&gt; 
&lt;s&gt;And then she said, "What big &lt;emphasis level="strong"&gt;%(8)s&lt;/emphasis&gt; you have, Grandmother."&lt;/s&gt; 
&lt;s&gt;But the wolf &lt;emphasis level="strong"&gt;said&lt;/emphasis&gt; nothing.&lt;/s&gt; 
&lt;s&gt;He had just died of &lt;emphasis level="strong"&gt;indigestion&lt;/emphasis&gt;, from &lt;emphasis level="strong"&gt;eating&lt;/emphasis&gt;, Grandmother.&lt;/s&gt; 
&lt;s&gt;Ha Ha Ha&lt;/s&gt; 
&lt;/voice&gt;&lt;/speak&gt;"""

#setup list of voices 
lstVoices = [] 
for aVoice in synth.GetInstalledVoices(): 
    if aVoice.Enabled: 
        print aVoice.VoiceInfo.Name 
        lstVoices.append(aVoice.VoiceInfo.Name)

aVoice = lstVoices[1] #Choose voice

lstWords = range(0,12)
lstWords[1] = "" #Ajective
lstWords[2] = "" #Color
lstWords[3] = "" #Exclamation
lstWords[4] = "" #Past Tense Verb
lstWords[5] = "" #Plural noun #1
lstWords[6] = "" #Plural noun #2
lstWords[7] = "" #Plural noun #3
lstWords[8] = "" #Plural noun #4
lstWords[9] = "" #Silly Word
lstWords[10] = "" #Verb #1
lstWords[11] = "" #Verb #2

#If you are too lazy to fill in the words yourself    
def AutoFill(): 
    lstWords[1] = "stinky" 
    lstWords[2] = "blue" 
    lstWords[3] = "yippie!" 
    lstWords[4] = "el bowed" 
    lstWords[5] = "coolers" 
    lstWords[6] = "hammers" 
    lstWords[7] = "Q-Tips" 
    lstWords[8] = "Sail Boats" 
    lstWords[9] = "scallywag" 
    lstWords[10] = "toast" 
    lstWords[11] = "love" 

def MadLib(): 
    if(lstWords[1] != ""): 
        xmlText = xmlSSML % {"voice":aVoice, "1":lstWords[1], "2":lstWords[2], "3":lstWords[3], "4":lstWords[4], "5":lstWords[5], "6":lstWords[6], "7":lstWords[7], "8":lstWords[8], "9":lstWords[9], "10":lstWords[10], "11":lstWords[11]} 
        print "Finished Mad Lib."
        print re.sub(r'&lt;[^&gt;]*?&gt;', '', xmlText)
    else:
        print "You have to fill in the words or call AutoFill() first!"

def Speak(): 
    if(lstWords[1] != ""): 
        print "Call Stop() to Stop voice"
        MadLib()
        ssml = xmlSSML % {"voice":aVoice, "1":lstWords[1], "2":lstWords[2], "3":lstWords[3], "4":lstWords[4], "5":lstWords[5], "6":lstWords[6], "7":lstWords[7], "8":lstWords[8], "9":lstWords[9], "10":lstWords[10], "11":lstWords[11]} 
        synth.SpeakSsmlAsync(ssml)
    else:
        print "You have to fill in the words or call AutoFill() first!"

def Stop(): 
    synth.SpeakAsyncCancelAll()

&lt;/textarea&gt;

Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-368954743983216714?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/L4gILXig1wA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/L4gILXig1wA/iron-python-speechsynthesizer-mad-lib.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/07/iron-python-speechsynthesizer-mad-lib.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-4029500241582994204</guid><pubDate>Fri, 03 Jul 2009 02:02:00 +0000</pubDate><atom:updated>2009-07-02T20:02:59.541-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tips n Tricks</category><category domain="http://www.blogger.com/atom/ns#">Tools</category><title>Box Selection in Visual Studio: You learn something new every day!</title><description>&lt;p&gt;I was browsing on the &lt;a href="http://blogs.msdn.com/coding4fun/" target="_blank"&gt;Coding4Fun site&lt;/a&gt; and came across this cool video about &lt;a href="http://blogs.msdn.com/coding4fun/archive/2009/06/21/9797162.aspx" target="_blank"&gt;Box Selection in Visual Studio 2010&lt;/a&gt;:&lt;/p&gt;  &lt;p align="center"&gt;&lt;embed src="http://images.video.msn.com/flash/soapbox1_1.swf" width="432" height="364" id="r79btrp3" type="application/x-shockwave-flash" allowFullScreen="true" allowScriptAccess="always" pluginspage="http://macromedia.com/go/getflashplayer" flashvars="player.c=v&amp;player.v=3e57917d-1b92-4188-b898-25a1d64a408e&amp;mkt=en-US&amp;ifs=true&amp;fr=shared"&gt;&lt;/embed&gt;&lt;noembed&gt;&lt;a href="http://video.msn.com/?mkt=en-US&amp;amp;playlist=videoByUuids:uuids:3e57917d-1b92-4188-b898-25a1d64a408e&amp;amp;showPlaylist=true&amp;amp;from=shared" target="_new" title="Box Selection and Multi-Line Editing Demo"&gt;Video: Box Selection and Multi-Line Editing Demo&lt;/a&gt;&lt;/noembed&gt;&lt;/p&gt;  &lt;p&gt;Looks like deleting a box selection has been around for a little while in both Visual Studio and Office (simply hold the alt key while you select the text), I just never knew about it. Heck, only recently learned about using the &lt;a href="http://visualstudiotips.wordpress.com/2006/04/17/tip-clipboard-ring/" target="_blank"&gt;clipboard ring&lt;/a&gt; a few months ago. VS 2010 adds the ability to also do inserts and replaces when doing a box selection, which really would come in handy while coding. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-4029500241582994204?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/bSWbjUIKwb0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/bSWbjUIKwb0/box-selection-in-visual-studio-you.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/07/box-selection-in-visual-studio-you.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-3706857417931846358</guid><pubDate>Tue, 30 Jun 2009 21:14:00 +0000</pubDate><atom:updated>2009-06-30T15:19:10.045-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Watin</category><category domain="http://www.blogger.com/atom/ns#">Testing</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>Export Vonage Call Log using IronPython and WatiN</title><description>&lt;p&gt;Here is another IronPython script that shows how to use the &lt;a href="http://watin.sourceforge.net/" target="_blank"&gt;WatiN&lt;/a&gt; testing framework, which is great for testing web pages in Internet Explorer, and it is starting to support Google Chrome and Firefox too. We use WatiN at work for testing the full stack on an ASP.Net website, and it works very well even for AJAX sites. This example will login to Vonage and export all of a user's call data to a CSV format.&lt;/p&gt;&lt;textarea class="brush:python" rows="25" cols="75"&gt;
"""Sample for getting Watin to work with IronPython
Usage: 
Download the WatiN-2.0.10.928-net-2.0.zip file from http://sourceforge.net/projects/watin/files/
put this script file(WatinExample.py), Interop.SHDocVw.dll, Microsoft.mshtml.dll, and WatiN.Core.dll into a folder called Watin
import the script or run execfile( "c:\\PATHTOFILES\\WatinExample.py") from console
use the Run() method to run the script, or use Reload() to reload the module after making changes."""
import sys
import clr
import re
from System.Reflection import Assembly
#clr.AddReference("d:\My Documents\Resolver\Watin\WatiN.Core.dll") #Only works for IronPython 1.1
sys.path.append("D:\My Documents\Resolver\Watin") #Needed so that WatiN can find the Interop.SHDocVw.dll file
assembly = Assembly.LoadFile("d:\\My Documents\\Resolver\\Watin\\WatiN.Core.dll") #Better way to import the file
clr.AddReference(assembly)
from WatiN.Core import *
from System import DateTime,TimeSpan

def reload():
    """Code used to reload this module. Helpful for when testing from console."""
    print "Reloading..."
    global Vonage
    Vonage.Close()
    execfile( "D:\\My Documents\\Resolver\\Watin\\WatinExample.py")

def run():
    """Code used to run a test script. Helpful for when testing from console."""
    global listActivity
    Vonage.Logon("username","password")
    listActivity = Vonage.ParseActivity("1-(801)-123-4567", DateTime(2008,2,1),DateTime(2008,5,31))
    Vonage.ArrayToCSV("C:\\test.csv",listActivity)
    
class Vonage(object):
    "Static class for working with Vonage website using WatiN"
    IE = None #Instance of IE object used by WatiN
    
    @staticmethod
    def Logon(strUsername, strPassword):
        """Initiates WatiN for use in IronPython to scrape the Vonage website for call activity."""
        print "Vonage.Login: Loading IE and browsing to Vonage.com" #TODO: Setup logging with different levels. Attach to WatiN for click events
        Vonage.IE = IE("http://www.vonage.com")
        Settings.WaitUntilExistsTimeOut = 25 #For development work set the timeout value to 15 seconds instead of default 30 seconds.
        print "Vonage.Login: Login to Vonage.com"
        Vonage.IE.TextField(Find.ByName("username")).TypeText(strUsername)
        Vonage.IE.TextField(Find.ByName("password")).TypeText(strPassword)
        Vonage.IE.Form(Find.ById("logonForm")).Submit()
        Vonage.IE.Link(Find.ByText("Log Out")).WaitUntilExists(15) #Waits up to 15 seconds for IE to login. If fails an exception will be thrown
    
    @staticmethod
    def isAuthenticated():     
        """Returns True if the session is currently logged in or false otherwise."""
        return Vonage.IE.Link(Find.ByText("Log Out")).Exists
    
    @staticmethod
    def ParseActivity(strPhoneNumber, dtStartDate, dtEndDate):     
        """Browses to the Activity section and parses the results.
            strPhoneNumber: Line Number to parse. Must be in 1-(xxx)-xxx-xxxx format. Must append (Fax) or (Virtual) for special lines.
            dtStartDate: Start Date (Inclusive).
            dtEndDate: End Date (Inclusive).
            Returns a list of call details"""
        if not Vonage.isAuthenticated():
            raise "Vonage.ParseActivity Error: User is not authenticated."
        Vonage.IE.Link(Find.ByText("Activity")).Click()
        lstActivityData = [["DateTime", "From", "To", "Duration", "TransactionID","FromCallerID","TransferedTo"]] #Store Activity data as list of row data. First element is header row.
        #Run report for Incoming calls
        Vonage.IE.Link(Find.ByText("Advanced Activity Search")).Click()
        Vonage.IE.SelectList(Find.ByName("didID")).Option(strPhoneNumber).Select() #Select the phone number requested. If phone number does not exist an exception will be thrown.
        Vonage.SetDate("start",dtStartDate)
        Vonage.SetDate("end",dtEndDate.AddDays(1)) #NOTE: Have to set end date + one day to be inclusive
        Vonage.IE.RadioButton(Find.ByValue("Incoming")).Click() #First select incoming and run the report
        Vonage.IE.Form(Find.ByName("activityForm")).Submit()
        while True:
            Vonage.ParsePageData(lstActivityData)
            if Vonage.IE.Link(Find.ByText("Next&gt;&gt;")).Exists:
                Vonage.IE.Link(Find.ByText("Next&gt;&gt;")).Click()
            else:
                break
        #Run report again for outgoing calls        
        Vonage.SetDate("start",dtStartDate)
        Vonage.SetDate("end",dtEndDate)
        Vonage.IE.RadioButton(Find.ByValue("Outgoing")).Click() #First select incoming and run the report
        Vonage.IE.Form(Find.ByName("activityForm")).Submit()
        while True:
            Vonage.ParsePageData(lstActivityData)
            if Vonage.IE.Link(Find.ByText("Next&gt;&gt;")).Exists:
                Vonage.IE.Link(Find.ByText("Next&gt;&gt;")).Click()
            else:
                break
        
        lstActivityData.sort(Vonage.SortData) #Sort data to merge Incoming and Outgoing calls
        return lstActivityData
    
    @staticmethod   
    def ParsePageData(lstData):
        """Parses the call data from a page and appends each row to lstData"""
        print "Vonage.ParsePageData: Parse Page data." #TODO parse total results out of string and display "xx of xx" using table row count
        re.DOTALL = True #Make the . character match newlines in re.search
        for aRow in Vonage.IE.Table("received_calls").TableRows:
            #print aRow.InnerHtml
            if aRow.Index &gt; 1 and aRow.TableCells.Count == 6: #Skip first and second row (header row) and any other row with less than 6 cells
                lstRowData = [] #See Row Data Format above
                lstData.append(lstRowData) #Add row to list
                lstRowData.append(DateTime.Parse(aRow.TableCells[0].Text + aRow.TableCells[1].Text)) #Create DateTime
                lstRowData.append(aRow.TableCells[2].Text.Trim()) #add From
                lstRowData.append(aRow.TableCells[3].Text.Trim()) #add To TODO: Parse Transfer data
                lstRowData.append(TimeSpan.Parse(aRow.TableCells[4].Text)) #add Duration
                lstRowData.append(long(aRow.TableCells[5].Text.Trim())) #add TransactionID
                regEx = re.search("&lt;b&gt;([^/]+)&lt;/b&gt;'",aRow.TableCells[2].InnerHtml) #Get caller ID info
                if regEx and len(regEx.groups()) == 1:
                    lstRowData.append(regEx.group(1))
                else:
                    lstRowData.append(None)
                regEx = re.search("Forwarded to (\d+)'",aRow.TableCells[2].InnerHtml) #Get forward info
                if regEx and len(regEx.groups()) == 1:
                    lstRowData.append(regEx.group(1))
                else:
                    lstRowData.append(None)
                
    
    @staticmethod   
    def SortData(lstA, lstB):
        "Comparer used to sort array data. Rates string datatypes highest, then compares based on datetime"
        if type(lstA[0]) == str:
            return -1
        elif type(lstB[0]) == str:
            return 1
        else:
            return cmp(lstA[0],lstB[0])
        
    @staticmethod   
    def SetDate(strPrefix, dtDate):
        """Used to set the Start and End Dates
            strPrefix: start or end
            dtDate: Datetime (inclusive)"""        
        Vonage.IE.SelectList(Find.ByName(strPrefix+"Month")).Option(dtDate.ToString("MMM")).Select()
        Vonage.IE.SelectList(Find.ByName(strPrefix+"Day")).Option(dtDate.ToString("dd")).Select()
        Vonage.IE.SelectList(Find.ByName(strPrefix+"Year")).Option(dtDate.ToString("yyyy")).Select()
        Vonage.IE.SelectList(Find.ByName(strPrefix+"Time")).Option("Midnight").Select() 
        
    @staticmethod
    def Close():
        """Closes IE instance and cleans up"""
        if Vonage.IE &lt;&gt; None:
            print "Closing IE..."
            Vonage.IE.Close()
            Vonage.IE = None

    @staticmethod       
    def ArrayToCSV(filename, listData):
        """Code used to convert an array of row data into a CSV file."""
        csvFile = open(filename, "w")
        for aRow in listData:
            bFirst = True        
            for aValue in aRow:
                if bFirst:
                    bFirst = False  #Reset first flag
                else:
                    csvFile.write(",") #seperate values with a comma
                #Write data item with special conversions
                if type(aValue) in (int, long, float): #Keep integer types the same. Also DateTime is a special case (See ExcelManager.SetCell)
                    csvFile.write(str(aValue)) #write numbers without quotes
                elif type(aValue) is TimeSpan:
                     csvFile.write(str(aValue.TotalMinutes)) #write value as total minutes
                elif aValue is None:
                    pass #write null entry as nothing (ie: 1,2,,4)
                else: #Cast everything else to a string
                    csvFile.write("\""+str(aValue)+"\"") #Convert everything else to a string and enclose in brackets
            csvFile.write("\n") #New line after each row. Note: \r\n doesnt work correctly on IPY 1.1
        csvFile.close()
&lt;/textarea&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-3706857417931846358?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/u1kKH7RXbgU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/u1kKH7RXbgU/export-vonage-call-log-using-ironpython.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/06/export-vonage-call-log-using-ironpython.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-3204484800355312482</guid><pubDate>Mon, 08 Jun 2009 22:50:00 +0000</pubDate><atom:updated>2009-06-08T16:51:57.306-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">PopUp</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>IronPython Date Selector: Pick a date... any date...</title><description>&lt;p&gt;Another quick IronPython snipet that shows how to use the Windows.Form.MonthCalendar control to create a simple date selector.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_G06mB5h-kvQ/Si2Vl6faDJI/AAAAAAAAA60/bOdIFBFtH0c/s1600-h/image002%5B4%5D.jpg"&gt;&lt;img title="image002" style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" height="269" alt="image002" src="http://lh4.ggpht.com/_G06mB5h-kvQ/Si2VmDri4EI/AAAAAAAAA64/TCL6Um4dNhc/image002_thumb%5B2%5D.jpg?imgmax=800" width="682" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;textarea class="brush:python" rows="25" cols="75"&gt;
"""rslCalendarForm contains the code for creating a Windows Form with a Calendar control to let the user choose a Date value.
Usage:
execfile(dirname(__file__)+"\\rslCalendarForm.py") #use execfile with the full path to the file name to load the module
frmCalendar = CalendarForm("Window Title") #Create and load the form. GUI thread is blocked until the form is closed
dtSelected = CalendarForm.LastDateSelected #Retrieve selected value from the static CalendarForm.LastDateSelected variable.
"""
#NOTE: Form code taken from http://www.voidspace.org.uk/ironpython/presentation.html and was originally written by Michael Foord
import sys
import clr
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Application, Form
from System.Windows.Forms import Button as frmButton
from System.Windows.Forms import (ControlStyles, ContextMenuStrip, DockStyle, FormStartPosition, ImageList, Keys, MenuStrip, MessageBox, MessageBoxButtons, MessageBoxIcon, Panel, TabControl, TabAlignment, TabPage, ToolStrip, ToolStripButton, ToolStripMenuItem,ToolStripLabel, ToolStripItemDisplayStyle, WebBrowser, Padding, FormBorderStyle,SizeGripStyle) 
from System.Windows.Forms import (MonthCalendar, Day)
from System.Drawing import Size,Point
from System import Uri, Exception, DateTime

class CalendarForm(Form):
    "Windows Form that displays a Calendar control. This will run in the main GUI thread."
    LastDateSelected = None #Static value used to store the last date selected
    
    def __init__(self, Name="Calendar",dtStartDate=None):
        "Name is the title of the control. Callback is a method that accepts a Datetime as a parameter and will be called when the form is closed."
        Form.__init__(self)
        CalendarForm.LastDateSelected = None #Clear last date selection
        self.Text = Name
        self.Name = Name
        self.Width = 210
        self.Height = 230
        self.FormBorderStyle = FormBorderStyle.FixedDialog
        self.SizeGripStyle = SizeGripStyle.Hide
        self.MinimizeBox = False
        self.MaximizeBox = False
        self.initMenu()
        self.initCalendar(dtStartDate)
        self.CenterToParent()
        self.ShowDialog()        

    def createToolstripButton(self, name, text, clickHandler=None, keys=None):
        menuItem = ToolStripButton(Name = name, Text = text)
        if keys:
            menuItem.ShortcutKeys = keys
        if clickHandler:
            menuItem.Click += clickHandler
        return menuItem 
    
    def initMenu(self):         
        menuStrip = MenuStrip(             
            Name = "Main MenuStrip",             
            Dock = DockStyle.Bottom        
        )
        mSpacer = ToolStripLabel("               ")
        mBack = self.createToolstripButton('Save', '&amp;Save', self.onSave)
        mSpacer2 = ToolStripLabel("    ")
        mForward = self.createToolstripButton('Cancel', '&amp;Cancel', self.onCancel)
        menuStrip.Items.Add(mSpacer)
        menuStrip.Items.Add(mBack)
        menuStrip.Items.Add(mSpacer2)
        menuStrip.Items.Add(mForward)
        self.Controls.Add(menuStrip)
        
    def initCalendar(self, StartDate=None):         
        "Setup the Calendar Control."
        pCalendar = Panel(Dock = DockStyle.Fill)
        pCalendar.Padding = Padding(25, 10, 25, 10)
        self.mCalendar = MonthCalendar()
        self.mCalendar.Location = Point (10, 10)
        self.mCalendar.FirstDayOfWeek = Day.Sunday 
        self.mCalendar.ShowTodayCircle = False
        self.mCalendar.ShowToday = False
        self.mCalendar.ShowWeekNumbers = False
        self.mCalendar.MaxSelectionCount = 1
        self.mCalendar.DoubleClick += self.onSave
        if StartDate==None:
            self.mCalendar.SetDate(DateTime.Now)
        else:
            self.mCalendar.SetDate(StartDate)
        pCalendar.Controls.Add(self.mCalendar)
        self.Controls.Add(pCalendar)
    
    def onSave(self, _, __):
        "Set the CalendarForm.LastDateSelected to the selected date and then close the form."
        CalendarForm.LastDateSelected = self.mCalendar.SelectionStart
        self.Close()
        
    def onCancel(self, _, __):
        self.Close()&lt;/textarea&gt;  &lt;p&gt;Works well for selecting singe dates, and could be modified to support selecting a date range if desired. I prefer having a Start Date and End Date, and selecting each separately. Full code can be downloaded &lt;a href="http://www.theg2.net/rslpivot/rslCalendarForm.py" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-3204484800355312482?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/DtAs5g3iMp0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/DtAs5g3iMp0/ironpython-date-selector-pick-date-any.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/06/ironpython-date-selector-pick-date-any.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-7673242585006867295</guid><pubDate>Mon, 08 Jun 2009 22:21:00 +0000</pubDate><atom:updated>2009-07-13T16:17:50.326-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Interop</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">Analysis</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>IronPython Excel COM Automation: Pivot this!</title><description>&lt;p&gt;I have been playing around with IronPython recently while creating spreadsheets in &lt;a href="http://www.resolversystems.com/" target="_blank"&gt;Resolver One&lt;/a&gt;. So far I have been &lt;a href="http://blog.theg2.net/2009/05/resolver-one-review-4-months-with-net.html" target="_blank"&gt;having a lot of fun&lt;/a&gt;, but I haven't really been doing anything that would be useful in a work setting. The main reason for this is because most of the spreadsheet work that I do revolves around pivot tables and Auto Filter, which are immensely helpful for visually analyzing data. I thought I might try and use Excel's COM Automation to add Pivot Charts and Auto Filter to any system with IronPython, and here is the code that I have come up with so far:&lt;/p&gt;

&lt;p&gt;UPDATE 7/13/2009: After releasing the initial code, I found that there was a problem with the  HideToolbars function causing the Excel toolbars to be disabled permanently. Also, the code would not work if the user's Region was set to something other than "en-US" due to &lt;a href="http://support.microsoft.com/kb/320369" target="_Blank"&gt;this known bug.&lt;/a&gt; I updated the code to disable the HideToolbars function and use Reflection and the InvokeMember method to force the Culture to be "en-US". If you want to view the old "en-US" only code, you can download it &lt;a href="http://www.theg2.net/rslpivot/ExcelManager.en-us_only.py" target="_Blank"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;textarea class="brush:python" rows="25" cols="100"&gt;
"""ExcelManager contains code for interacting with an Excel spreadsheet.
This code should work with both IronPython 1.1 and IronPython 2.0

NOTE: Microsoft Excel must be installed on the machine for this to work. Code should be compatible with Office 2003 or Office 2007
If you get an error message about "IOError: Could not add reference to assembly Microsoft.Office.Interop.Excel" then 
you need to install the Primary Interop Assemblies for Microsoft Office, which can be downloaded from:
Office 2003 PIA: http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad&amp;displaylang=en
Office 2007 PIA: http://www.microsoft.com/downloads/details.aspx?familyid=59DAEBAA-BED4-4282-A28C-B864D8BFA513&amp;displaylang=en
Install from Office Setup CD: http://msdn.microsoft.com/en-us/library/aa159923(office.11).aspx#officeprimaryinteropassembliesfaq_after

The original code gave an Error: 0x80028018 "Old Format or Invalid Type Library" when trying to set worksheet values (Name, Cell.Value2, etc) 
This is a known issue when the computer's region is set to something other than en-us: http://support.microsoft.com/kb/320369
The ExcelManager.SetProperty method was added as a workaround to this issues. It uses the Reflection and the InvokeMember method
to ensure that the CurrentCulture is set to en-US. This method should be used whenever you set a property value to ensure
that the code will work in any culture. 

More info at http://www.ironpython.info/index.php/Interacting_with_Excel

"""
import sys
import clr
clr.AddReference("Office")
clr.AddReference("Microsoft.Office.Interop.Excel")
from Microsoft.Office.Interop import Excel
from System.Reflection import Missing, BindingFlags
from System.Threading import Thread
from System.Globalization import CultureInfo
from System import Array, DateTime, DayOfWeek

def reload():
    """Helper method to reload this script when testing or debuging"""
    print "Reloading..."
    global ExcelManager
    ExcelManager.CloseExcel(True) #Force Excel to close
    execfile( "D:\\My Documents\\Resolver\\RslPivot V1.4\\ExcelManager.py")

def run():
    """Sample method for how to use the Excel Manager"""
    global SheetData
    SheetData = [['a','b','c'],[1,2,3],[4,5,6],[7,8,9]] #Data should be packed row by row in a multi-dimentional array. First Row is Header Row.
    ExcelManager.OpenExcel(True) #Open Excel but do not show the window yet
    ExcelManager.NewBlankWorkbook("My Autofilter")
    ExcelManager.LoadSheetData(SheetData)
    ExcelManager.CreatePivotTable("My Pivot Table")
    ExcelManager.CreatePivotChart("My Pivot Chart")
    ExcelManager.HideToolbars(lstExcept=["PivotTable Field List", "Standard", "FormulaBar"]) #Disable all the toolbars except the Pivottable, Standard toolbar and FormulaBar
    ExcelManager.ShowWindow()

class ExcelManager(object):
    """Static class for managing the Excel application. 
    See http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel(office.11).aspx for more details."""
    
    ExcelApp = None #Excel Application Interop Object
    ExcelWorkbook = None #Excel Workbook Interop Object
    ExcelWorksheet = None #Excel Worksheet Interop Object
    PivotTable = None 
    PivotChart = None 
    LocalShortDateFormat = Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern #used to format from OADate to correct format

    @staticmethod
    def SetProperty(target, name, value):
        """Used to set properties using the en-US culture, which is the safest way to do Excel COM integration.
        See: http://support.microsoft.com/kb/320369"""
        try:
            args = Array[object]([value])
            return target.GetType().InvokeMember(name, BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.Public, None, target, args, CultureInfo(1033))
        except:
            print "Error setting Property: " + name
            print sys.exc_info()
            raise

    @staticmethod
    def OpenExcel(ShowWindow=False):
        """Opens a new Excel Application.
        ShowWindow: True means the window will be visible, otherwise the window will be hidden.
        """
        #print "ExcelManager: Opening Excel"
        ExcelManager.ExcelApp = Excel.ApplicationClass()
        if ShowWindow:
            ExcelManager.ShowWindow()
        else:
            ExcelManager.HideWindow()

    @staticmethod
    def ShowWindow():
        ExcelManager.ExcelApp.Visible = True
        
    @staticmethod
    def HideWindow():
        ExcelManager.ExcelApp.Visible = False
    
    @staticmethod
    def CloseExcel(ForceClose=False):
        """Closes the Excel application. If ForceClose=True then the user will not be prompted to save any changes."""
        if ExcelManager.ExcelApp &lt;&gt; None and ExcelManager.ExcelWorkbook &lt;&gt; None:
            print "Quitting Excel..."
            if ForceClose and ExcelManager.ExcelApp.Workbooks.Count &gt; 0:
                ExcelManager.SetProperty(ExcelManager.ExcelWorkbook, "Saved", True)                
            ExcelManager.ExcelApp.Quit()
            
    @staticmethod
    def NewBlankWorkbook(SheetName="Worksheet"):
        """Opens a new blank workbook in Excel with one worksheet with the given Name."""
        #print "ExcelManager: NewBlankWorkbook"
        ExcelManager.ExcelWorkbook = ExcelManager.ExcelApp.Workbooks.Add()
        #NOTE: use Item.__getitem__(index) to be compatable with both IronPython 1.1 and IronPython 2.0
        ExcelManager.ExcelWorkbook.Worksheets.Item.__getitem__(3).Delete() #workbook starts with 3 blank worksheets. Delete the second and 3rd.
        ExcelManager.ExcelWorkbook.Worksheets.Item.__getitem__(2).Delete()   
        #ExcelManager.ExcelWorkbook.Worksheets.Item.__getitem__(1).Name = SheetName  #Threw error whenever the computer's region was set to something other than en-us. Use SetProperty method instead.
        ExcelManager.SetProperty(ExcelManager.ExcelWorkbook.Worksheets.Item.__getitem__(1), "Name", SheetName)
        ExcelManager.ExcelWorksheet = ExcelManager.ExcelWorkbook.Worksheets.Item.__getitem__(1)
        
    @staticmethod    
    def SetCell(RowIndex, ColIndex, Value):
        #print "Loading Cell(" + str(RowIndex) + str(ColIndex) +  ") with " + str(Value)
        aCell = ExcelManager.ExcelWorksheet.Cells.Item.__getitem__(ColIndex).Item.__getitem__(RowIndex)
        if type(Value) == DateTime:
            #aCell.Value2 = Value.ToOADate() #Threw exception when culture was not en-us. Use SetProperty instead
            ExcelManager.SetProperty(aCell, "Value2", Value.ToOADate())
            ExcelManager.SetProperty(aCell, "NumberFormat", ExcelManager.LocalShortDateFormat)
        else:
            ExcelManager.SetProperty(aCell, "Value2", Value)
    
    @staticmethod
    def SetRow(RowIndex, ArrayValues):
        #print "Loading Row " + str(RowIndex) + " with " + str(ArrayValues)
        intColIndex = 0
        for aValue in ArrayValues:
            intColIndex += 1
            ExcelManager.SetCell(RowIndex,intColIndex, aValue)

    @staticmethod
    def GetCommandBar(strName):
        """Helper method used to get a Commandbar. This way the code works with both IronPython 1.1 and IronPython 2.0"""
        if hasattr(ExcelManager.ExcelApp.CommandBars, "Item"):
            return ExcelManager.ExcelApp.CommandBars.Item(strName) #IronPython 2.0
        else:
            return ExcelManager.ExcelApp.CommandBars[strName] #IronPython 1.1

    @staticmethod            
    def LoadSheetData(SheetData):
        """Loads data into the Excel WorkSheet.
           SheetData should contain an object for each row, with each object containing data for that row."""
        intRow = 0
        for aRow in SheetData:
            intRow +=1
            ExcelManager.SetRow(intRow,aRow)
        ExcelManager.ExcelWorksheet.UsedRange.AutoFilter(1, Missing.Value, Excel.XlAutoFilterOperator.xlAnd, Missing.Value, True) #Enable Autofilter 
     
    @staticmethod
    def CreatePivotTable(strName="Pivot Table"):
        """Creates a Pivot Table.
        See http://www.eggheadcafe.com/community/aspnet/2/10050513/solved--export-data-from.aspx for more info."""
        NewSheet = ExcelManager.ExcelWorkbook.Worksheets.Add()
        ExcelManager.SetProperty(NewSheet, "Name", "Pivot Table")
        ExcelManager.ExcelWorkbook.PivotTableWizard(Excel.XlPivotTableSourceType.xlDatabase, ExcelManager.ExcelWorksheet.UsedRange, NewSheet.UsedRange, strName, True, True, True, False, Missing.Value, Missing.Value, False, False, Excel.XlOrder.xlDownThenOver, 5, Missing.Value, Missing.Value)
        ExcelManager.ExcelWorkbook.ShowPivotTableFieldList = True
        ExcelManager.GetCommandBar("PivotTable").Visible = False
        ExcelManager.PivotTable = NewSheet
    
    @staticmethod    
    def CreatePivotChart(strName="Pivot Chart"):
        """Creates a Pivot Chart.
        See http://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.chart_properties(VS.80).aspx for more info.
        Example code: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/c7b0f6dd-8890-41c7-a5e0-e18f70686f8c"""
        ExcelManager.PivotChart = ExcelManager.ExcelWorkbook.Charts.Add(Missing.Value, Missing.Value, Missing.Value, Missing.Value)
        #ExcelManager.PivotChart.ChartWizard(ExcelManager.ExcelWorksheet.UsedRange, Excel.XlChartType.xlColumnClustered, Missing.Value, Excel.XlRowCol.xlColumns, Missing.Value, Missing.Value, True, "Pivot Chart Name", Missing.Value, Missing.Value, Missing.Value) #This method threw an 0x800A03EC error message, so set the values seperately
        ExcelManager.SetProperty(ExcelManager.PivotChart, "ChartType", Excel.XlChartType.xlColumnClustered)
        #ExcelManager.PivotChart.SetSourceData(ExcelManager.ExcelWorksheet.UsedRange, Excel.XlRowCol.xlColumns) #Threw error... but seems to work fine without it. Must assume that it is a pivot chart
        ExcelManager.SetProperty(ExcelManager.PivotChart, "HasLegend" , True)
        ExcelManager.SetProperty(ExcelManager.PivotChart, "HasTitle", True) #Show chart title and set it's text
        ExcelManager.SetProperty(ExcelManager.PivotChart.ChartTitle, "Text", strName)
        ExcelManager.SetProperty(ExcelManager.PivotChart, "Name","Pivot Chart") #Set Tab name
        
    @staticmethod
    def HideToolbars(lstExcept=["PivotTable Field List", "Standard", "FormulaBar"]):
        """Hides all the toolbars and only shows the worksheet and charts. If the toolbar's name is in lstExcept then it will remain visible.
           NOTE: May cause tool bars to be perminantly disabled if the worksheet is saved! It is advised not to use this method, needs to be reworked."""
        #for aBar in ExcelManager.ExcelApp.CommandBars:
        #    if lstExcept.Contains(aBar.Name):
        #        aBar.Enabled = True
        #    else:
        #        aBar.Enabled = False #disable
        #ExcelManager.ExcelApp.DisplayFormulaBar = lstExcept.Contains("FormulaBar")
        pass
        
        
&lt;/textarea&gt;  &lt;p&gt;The code should be pretty straight forward. The Reload() method is helpful for reloading the whole module when testing from a console. The Run() method shows the steps to load a new spreadsheet. The ExcelManager static class is the core of the logic and provides an entry point for interacting with the spreadsheet. &lt;/p&gt;&lt;p&gt;There is not a lot of debuging code, so if something goes wrong it is just going to throw an exception, but this should be enough to help get things started. I did fix some funky problems with importing DateTime, where they kept getting converted into integers. Should work fine now, but anything other than Datetime, numerical types or strings will probably not get imported correctly.&lt;/p&gt;&lt;p&gt;If anyone else needs to do Excel Interop with IronPython, feel free to use the code, which can be downloaded &lt;a href="http://www.theg2.net/rslpivot/ExcelManager.py" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-7673242585006867295?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/1IiY9Rr8aQM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/1IiY9Rr8aQM/ironpython-excel-com-automation-pivot.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/06/ironpython-excel-com-automation-pivot.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-7335932737242734696</guid><pubDate>Mon, 01 Jun 2009 20:44:00 +0000</pubDate><atom:updated>2009-06-01T14:44:05.913-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">XML</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><category domain="http://www.blogger.com/atom/ns#">MSSQL</category><title>Simple-Talk article about SQL FOR XML usage</title><description>&lt;p&gt;I read a great article from Simple-Talk today about &lt;a href="http://www.simple-talk.com/content/article.aspx?article=720" target="_blank"&gt;how to use the FOR XML option in Microsoft SQL server&lt;/a&gt;. I usually would passively post these to a shared RSS reader feed or star them for future reference, but I found the article through the &lt;a href="http://www.simple-talk.com/newsletter-archive/Default.aspx" target="_blank"&gt;Red Gate Newsletter&lt;/a&gt; and I don't really want to add the entire feed just to share one article. I do however suggest &lt;a href="http://www.simple-talk.com/community/user/CreateUser.aspx" target="_blank"&gt;signing up for the newsletter&lt;/a&gt; if you are interested in MSSQL, .NET, or Exchange as they often have a lot of good articles about coding in or managing these systems.&lt;/p&gt;  &lt;p&gt;Simple-Talk is a service from Red Gate, which creates tools for Exchange, SQL Server and .NET including the &lt;a href="http://www.red-gate.com/products/reflector/index.htm" target="_blank"&gt;.NET Reflector&lt;/a&gt;, which is an invaluable tool for anyone using the .NET framework. I use it all the time to help with testing and debugging or when using .NET libraries that have poor user documentation. It even includes add-ins for &lt;a href="http://www.codeproject.com/KB/msil/reflexil.aspx" target="_blank"&gt;changing code in .NET assemblies&lt;/a&gt; or adding an &lt;a href="http://www.simple-talk.com/dotnet/.net-tools/methodist-make-.net-reflector-come-alive-with-ironpython/" target="_blank"&gt;embedded IronPython console&lt;/a&gt; for playing around with objects and methods. Very handy indeed!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-7335932737242734696?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/jdxuI_QYhFI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/jdxuI_QYhFI/simple-talk-article-about-sql-for-xml.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/06/simple-talk-article-about-sql-for-xml.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-2759125129251059739</guid><pubDate>Wed, 20 May 2009 23:23:00 +0000</pubDate><atom:updated>2009-05-20T17:27:18.836-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Over Complicated</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>IronPython programming can be harder than it looks!</title><description>&lt;p&gt;After playing around with IronPython for a few months, I definitely like how easy it is to manipulate objects. Everything is truly open, and if you want to attach one object to another or pass a function around as a variable then &amp;quot;it just works&amp;quot;. I have mainly been using IronPython for fun, but right now I would be a bit scared to use such a fluid language for a structured large scale production application: The lack of static typing and compile time checks would make we wary of using IronPython for &amp;quot;real code&amp;quot; instead of just scripting. I stumbled on a video of &lt;a href="http://channel9.msdn.com/posts/Dan/Giles-Thomas-ResolverOne-Combining-a-Spreadsheet-with-a-Programming-Language/" target="_blank"&gt;Giles Thomas on Channel 9&lt;/a&gt; (posted in March 2008 but mystically appeared in my RSS reader this afternoon) and it sounds like Resolver Systems had similar concerns but combined IronPython with &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank"&gt;Test Driven Development&lt;/a&gt; to build a solid foundation for &lt;a href="http://www.resolversystems.com/" target="_blank"&gt;Resolver One&lt;/a&gt;. That way they get plenty of up front testing and don't need to second guess the dynamic nature of programming in python. Seems to have worked well so far, as Resolver One is a rock solid product from my experience.&lt;/p&gt;&lt;p&gt;Usually when somebody says that &amp;quot;it just works&amp;quot;, the phrase comes with an asterisk and a long line of small text at the bottom of the page. In my experience with IronPython this is still the case, as there are a few things that are much harder to do than they should be. Michael Foord, another Resolver Systems developer, co-wrote &lt;a href="http://www.ironpythoninaction.com/" target="_blank"&gt;the book on IronPython&lt;/a&gt;, and today wrote an article about a case when IronPython code ends up being &lt;a href="http://www.voidspace.org.uk/python/weblog/arch_d7_2009_05_16.shtml#e1090" target="_blank"&gt;a bit tricky.&lt;/a&gt; If you ever need to get the docstrings from an arbitrary IronPython object, or just want to see a detailed explanation of some of the inner workings of python, the &lt;a href="http://www.voidspace.org.uk/python/weblog/index.shtml" target="_Blank"&gt;Techie Blog&lt;/a&gt; is a great read!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-2759125129251059739?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/DegFEGaXAbQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/DegFEGaXAbQ/ironpython-programming-can-be-harder.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/05/ironpython-programming-can-be-harder.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-4089816718267262529</guid><pubDate>Fri, 08 May 2009 17:58:00 +0000</pubDate><atom:updated>2009-10-01T22:17:16.859-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Over Complicated</category><category domain="http://www.blogger.com/atom/ns#">WTF</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>Installing Windows 7 on ASUS-P6T with IHC10R RAID Array</title><description>&lt;p&gt;I recently purchased &lt;a href="http://blog.theg2.net/2009/05/lucky-7s-gb7-core-i7-and-windows-7.html" target="_blank"&gt;a new computer,&lt;/a&gt; and I decided to go with the following components:&lt;/p&gt;  &lt;p&gt;Motherboard: ASUS P6T LGA 1366 Intel X58 ATX &lt;/p&gt;  &lt;p&gt;CPU: INTEL Core i7 920 2.66G quad core with Hyper Threading (4 cores, 8 threads)&lt;/p&gt;  &lt;p&gt;RAM: 3x2GB DDR3 1600&lt;/p&gt;  &lt;p&gt;Hard Drive: 2x250GB Seagate Barracuda 7200.10 ST3250310AS setup as RAID 1 Mirror&lt;/p&gt;  &lt;p&gt;Video Card: MSI N9400GT-MD512H 9400GT RTL with passive cooling design&lt;/p&gt;  &lt;p&gt;Case: APEVIA X-ALIEN MX-ALIEN-BK Black Steel ATX Full Tower &lt;/p&gt;  &lt;p&gt;The build went fine, but I got stuck trying to install Windows 7 64Bit RC, as I could not get it to load the drivers for either the JMicron JMB363 or Intel ICH10R SATA controllers. The SATA Port 0 and 1 are controlled by the JMicron JMB363 controller, which can be setup as a special Speed or Backup mode using Intel Drive Xpert technology. I couldn't find any information about what these actually were (I assume Raid 0 and Raid 1, but not sure), so I decided to try and setup the drives on the ICH10R controller as a standard RAID 1 array instead. After updating the bios using the built in ASUS EZ Flash 2 feature (very cool!), I setup the ICH10R controller in RAID mode in the BIOS, disabled the quick boot and the Floppy drive (was causing Windows 7 setup to be incredibly slow trying to loading drivers from a floppy drive that didn't exist), and pressed CTRL+i to setup the drives in mirror mode.&lt;/p&gt;  &lt;p&gt;Windows 7 setup still couldn't detect any of the drives. The motherboard came with a driver disk, but I couldn't get any of the SATA drivers for Intel or JMicron on it to work. Even after breaking the raid and installing one drive on each controller, and changing from RAID to AHCI, it still couldn't find them. I tried downloading 3 different versions of the ICH10R driver, even the ones that said they were Windows 7 compatible. I final found a driver that worked for the JMicron controller on the motherboard driver disk tucked away in an install directory in an AMD64 directory. This wasn't what I wanted, but at least I was able to get Windows installed. It took a long time and I thought that it stalled on the &amp;quot;Completing Installation&amp;quot; section, but after an hour or so it changed to a message saying that the installation will continue after rebooting (which I force to reboot after 10 minutes of waiting). Looks like they still haven't fixed any of the &lt;a href="http://sdsync.com/2008/12/27/26-useless-windows-7-beta-1-notifications/" target="_blank"&gt;useless notifications during windows 7 installation&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;After Windows loaded up, I downloaded and installed the latest drivers and ran Windows update, which updated the drivers again. A few reboots, and everything looks great, although it still is running off of the JMicron controller and is not in RAID 1 like I wanted. I switched the drives over to the ICH10R controller, but then it wouldn't load into windows. I was about to cry, but then I noticed that there were two drives listed in the boot sequence, and one of them was still a blank drive. I switched the order of the drives so that the one with Windows was on the lowest SATA port, and then after rebooting it loaded into Windows again (crisis adverted!). Now the drives were on the correct controller, which was still setup in RAID mode in the bios. Unfortunately you can't create a RAID array in the boot loader from an existing disk without loosing all of the data, but by downloading and installing the Intel Matrix Storage Console I was able to &lt;a href="http://h10025.www1.hp.com/ewfrf/wc/document?docname=c01386632&amp;amp;lc=en&amp;amp;cc=no" target="_blank"&gt;convert an existing disk to a RAID 1 array&lt;/a&gt;. The process failed the first time, but I rebooted, tried again, and after 2 hours (SATA 3.0GB/sec my ass....) I had everything working just how I wanted.&lt;/p&gt;  &lt;p&gt;A bit of a pain, but at least I got it to work. It might be that there is a special driver for the ICH10R SATA RAID mode that is hidden somewhere, but I couldn't find anything that worked. Best bet if you are installing Windows 7 64-bit on ASUS-P6T is to connect a drive to Port 0 or 1 and load the JMicron drivers from the install/AMD64 directory. You can then move over to the Intel controller after updating all the drivers in Windows and build whatever type of RAID array you want using the Intel Matrix Storage Console.&lt;/p&gt; 
&lt;p&gt;Update 10/1/2009: &lt;a href="http://codeblog.theg2.net/2009/10/windows-7-issues-with-jmicron-jmb36x.html"&gt;More issues with JMicron controller and IDE drive.&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-4089816718267262529?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/JAH6VRvl-xE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/JAH6VRvl-xE/installing-windows-7-on-asus-p6t-with.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">14</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/05/installing-windows-7-on-asus-p6t-with.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-1553497645113339291</guid><pubDate>Fri, 13 Mar 2009 23:19:00 +0000</pubDate><atom:updated>2009-03-13T18:35:10.636-06:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">PowerShell</category><title>PowerShell Script for Processing TimeManagment CSV Data</title><description>&lt;p&gt;If you are a code geek I highly suggest looking at the &lt;a href="http://www.anappaday.com" target="_blank"&gt;An App A Day&lt;/a&gt; site to see some cool open source projects that were designed and created in less 24 hours. I have been using the &lt;a href="http://www.anappaday.com/downloads/2006/09/day-2-time-management.html" target="_blank"&gt;TimeManagment&lt;/a&gt; program to create my time cards for a few years now, although because of it's lack of analysis tools I haven't been able to do much else with the data. If you are interested in tracking and analyzing time spent on your computer, &lt;a href="http://www.rescuetime.com" target="_blank"&gt;RescueTime&lt;/a&gt; is much more stable and has many, many more features, but TimeManagment is a great way to create an audit log and do customized tracking.&lt;/p&gt;  &lt;p&gt;Even something as simple as creating a time card can be a bit of a pain, since all of the data is stored in a single CSV file. You end up having to open the file in Excel and scan through thousands of lines like these to find what you were doing at any given time:&lt;/p&gt;  &lt;p&gt;&lt;textarea class="brush: plain;"&gt;
03/04/2009,10:31:46,Idle,,0.334114583333333
03/04/2009,10:32:06,javaw,GmailAssistant,0.166666666666667
03/04/2009,10:32:16,explorer,,0.1671875
03/04/2009,10:32:26,chrome,Gmail - Google Chrome,0.0833333333333333
03/04/2009,10:32:31,chrome,Gmail - Inbox (4) - Google Chrome,0.166666666666667
03/04/2009,10:32:41,chrome,Gmail - New Issues and a Top Priority list - Google Chrome,0.0833333333333333
03/04/2009,10:32:46,chrome,Gmail - Total Protection Service Summary Report - Google Chrome,0.25
03/04/2009,10:33:01,chrome,Gmail - Search results - Google Chrome,0.0833333333333333
03/04/2009,10:33:06,chrome,Gmail - McAfee Registration Details - Google Chrome,0.0833333333333333
&lt;/textarea&gt; &lt;/p&gt;  &lt;p&gt;I finally got fed up with it and created a PowerShell script to do the job for me (including removing 1 hour each day for lunch). Now I can click a button and out pops a nice little report listing my hours for any given date range:&lt;/p&gt;  &lt;p&gt;
&lt;textarea class="brush: plain;"&gt; 
Start processing file:  TimeManagement 2009MAR03.csv
Start processing file:  TimeManagement.csv
Fill empty days from 3/13/2009 to 3/15/2009
Force Change data From:  3/3/2009 11:53:11 AM 3/3/2009 1:18:12 PM 01:25:01 to 10:00 AM 6:00 PM
Force Change data From:  3/13/2009 11:56:26 AM 3/13/2009 5:59:43 PM 06:03:17 to 9:30 AM 6:00 PM
Total Processing time 6.28 seconds for 16,619 valid csv entries and 623 unknown entries.

    Start Timecard

03/01/2009 -  
03/02/2009 07:38:19 Hours 10:50 AM-7:28 PM 1 HR lunch
03/03/2009 07:00:00 Hours 10:00 AM-6:00 PM 1 HR lunch
03/04/2009 05:31:47 Hours 10:32 AM-5:03 PM 1 HR lunch
03/05/2009 06:29:37 Hours 10:39 AM-6:09 PM 1 HR lunch
03/06/2009 05:16:34 Hours 10:29 AM-4:45 PM 1 HR lunch
03/07/2009 -  
03/08/2009 -  
03/09/2009 08:20:59 Hours 10:26 AM-7:47 PM 1 HR lunch
03/10/2009 06:25:30 Hours 10:08 AM-5:33 PM 1 HR lunch
03/11/2009 07:14:26 Hours 11:00 AM-7:14 PM 1 HR lunch
03/12/2009 05:45:33 Hours 11:17 AM-6:02 PM 1 HR lunch
03/13/2009 07:30:00 Hours 9:30 AM-6:00 PM 1 HR lunch
03/14/2009 ?  
03/15/2009 ?  

Total Time this period is 67.2 hours for 10 days. Average 6.7 hours per day.
Projected: Total Hours 70.6, Total Pay $1,764.33, Take Home $1,369.12

    End Timecard
&lt;/textarea&gt;&lt;/p&gt;  &lt;p&gt;You can see that it is not perfect (It still things that I plan on coming in and working a few hours this weekend. Fat Chance!), but if you are interested here is a link to &lt;a href="http://powershell.com/cs/media/p/1862.aspx"&gt;the PowerShell script file&lt;/a&gt;. Should come in handy for anyone else using the TimeManagment program or just interested in processing CSV data files using PowerShell.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-1553497645113339291?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/myqkDJSY67M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/myqkDJSY67M/powershell-script-for-processing.html</link><author>noreply@blogger.com (Greg Bray)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/03/powershell-script-for-processing.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-7198995335456824055</guid><pubDate>Tue, 17 Feb 2009 21:14:00 +0000</pubDate><atom:updated>2009-02-17T14:14:31.288-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Tools</category><category domain="http://www.blogger.com/atom/ns#">.NET</category><category domain="http://www.blogger.com/atom/ns#">PowerShell</category><category domain="http://www.blogger.com/atom/ns#">IronPython</category><title>Programs for reading and writing code in different languages</title><description>&lt;p&gt;Just a quick post to keep things going. I end up having to read more code than I write, mainly because even when I write code I am usually pulling bits and pieces from old projects. When writing code I always use a full IDE, since I have become dependent on features such as code completion, breakpoints/debugging, and visual designers. For reading code these features are not as important, but code syntax highlighting and region/section collapsing are still very useful. For writing code I use all of the standard IDEs: &lt;a href="http://www.microsoft.com/Express/" target="_blank"&gt;Visual Studio 2005/2008&lt;/a&gt; for .NET, SQL Management Studio for MS SQL, &lt;a href="http://shelltools.wik.is/PowerShell_Analyzer" target="_blank"&gt;PowerShell Analyzer&lt;/a&gt; or &lt;a href="http://www.idera.com/Content/Show65.aspx" target="_blank"&gt;PowerShell Plus&lt;/a&gt; for PowerShell, and &lt;a href="http://www.codeplex.com/IronPythonStudio" target="_blank"&gt;IronPython Studio&lt;/a&gt; for IronPython. For reading code, rather than loading a bulky IDE I have started to use a free program called Notepad++, which supports multiple tabs, region collapsing, and syntax highlighting for a myriad of languages. It works a lot better than reading code in notepad and loads much faster than Visual Studio. Here is a screenshot: &lt;/p&gt;  &lt;p&gt;&lt;img src="http://lh6.ggpht.com/_G06mB5h-kvQ/SZslGetxiyI/AAAAAAAAA4Q/ty906V0f0HE/s720/2009FEB17 Notepad++ Screenshot.JPG" /&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-7198995335456824055?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/Py3A2DdPp_w" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/Py3A2DdPp_w/programs-for-reading-and-writing-code.html</link><author>noreply@blogger.com (Greg Bray)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_G06mB5h-kvQ/SZslGetxiyI/AAAAAAAAA4Q/ty906V0f0HE/s72-c/2009FEB17" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/02/programs-for-reading-and-writing-code.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6011603498138679949.post-4981787036830433889</guid><pubDate>Thu, 05 Feb 2009 23:01:00 +0000</pubDate><atom:updated>2009-02-05T16:44:36.676-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">JavaScript</category><category domain="http://www.blogger.com/atom/ns#">Cookies</category><category domain="http://www.blogger.com/atom/ns#">PopUp</category><category domain="http://www.blogger.com/atom/ns#">CSS</category><category domain="http://www.blogger.com/atom/ns#">HTML</category><title>JavaScript and CSS based popup for changing Google Analytics User Segment cookie</title><description>&lt;p&gt;I use &lt;a href="http://www.google.com/analytics/" target="_blank"&gt;Google Analytics&lt;/a&gt; on all of the sites that I work on for tracking page views and traffic sources. It has great reporting features, but I always have problems with traffic from my office computer or home laptop skewing the results. Most of the computers that I use have dynamic IP addresses, so a static IP filter does not work. Instead you have to setup a &lt;a href="http://catbirdanalytics.wordpress.com/2009/01/03/excluding-visitors-from-google-analytics-via-cookie/" target="_blank"&gt;cookie based filter&lt;/a&gt;. The problem is then how do you setup the cookie and monitor if your traffic is currently being tracked or not? I created a small JavaScript and CSS based popup for setting and clearing the cookie that I can then add somewhere to the site. The first section is the JavaScript code. Place this block somewhere in your HTML or template:&lt;/p&gt;
&lt;textarea rows="10" class="brush:js"&gt;
&lt;script language="JavaScript"&gt; 
&lt;!-- 
//Code from http://www.netlobo.com/javascript_get_element_id.html
function returnObjById( id ) 
{ 
    if (document.getElementById) 
        var returnVar = document.getElementById(id); 
    else if (document.all) 
        var returnVar = document.all[id]; 
    else if (document.layers) 
        var returnVar = document.layers[id]; 
    return returnVar; 
}

//Code from http://www.quirksmode.org/js/cookies.html
function createCookie(name,value,days) {
 if (days) {
  var date = new Date();
  date.setTime(date.getTime()+(days*24*60*60*1000));
  var expires = "; expires="+date.toGMTString();
 }
 else var expires = "";
 document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
 var nameEQ = name + "=";
 var ca = document.cookie.split(';');
 for(var i=0;i &lt; ca.length;i++) {
  var c = ca[i];
  while (c.charAt(0)==' ') c = c.substring(1,c.length);
  if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
 }
 return null;
}

function eraseCookie(name) {
 document.cookie = name +'=; expires=Thu, 01-Jan-70 00:00:01 GMT;';
}

//--&gt; 
&lt;/script&gt;
&lt;/textarea&gt;
&lt;p&gt;The second section is the DIV/CSS popup that contains a few links that you can click on. Again just place this anywhere in your HTML or template (it uses fixed positioning and will always appear in the middle of the screen):&lt;/p&gt;
&lt;textarea rows="10" class="brush:html"&gt;&lt;div id="divPopup" style="position:absolute; left:50%; top:40%; width:250px; height:200px; margin-left:-125px; margin-top:-100px;z-index:1;visibility:hidden;background-color: LightGrey;border: medium solid black;padding: 5px;"&gt; &lt;br /&gt;  &lt;div style="font-weight:bold;margin: 5px 0px 25px 0px;"&gt;Google Analytics Settings:&lt;/div&gt;&lt;br /&gt;  &lt;div style="text-align: center; line-height: 2"&gt;&lt;br /&gt; &lt;a style="display:block;" href="#" onclick="alert('Custom Segment cookie __utmv value: ' + readCookie('__utmv'));"&gt;Check if Custom Segment is set&lt;/a&gt;&lt;br /&gt; &lt;a style="display:block;" href="#" onclick="pageTracker._setVar('NoTracking');alert('Custom Segment cookie __utmv set to NoTracking.');"&gt;Set Custom Segment to NoTracking&lt;/a&gt;&lt;br /&gt; &lt;a style="display:block;" href="#" onclick="eraseCookie('__utmv');alert('Custom Segment cookie __utmv cleared.');"&gt;Clear Custom Segment&lt;/a&gt;&lt;br /&gt; &lt;/div&gt;&lt;br /&gt;  &lt;a style="position: absolute; bottom: 5px; right: 10px;" href="#" onclick="returnObjById('divPopup').style.visibility = 'hidden';"&gt;Close&lt;/a&gt; &lt;br /&gt;&lt;/div&gt;&lt;/textarea&gt;

&lt;p&gt;The final section is a link that can be placed somewhere on your page. Clicking the link will display the popup:&lt;/p&gt;
&lt;textarea rows="10" class="brush:html"&gt;Put this link wherever you want users to &lt;br /&gt;&lt;a onclick="returnObjById('divPopup').style.visibility = 'visible';" href="#"&gt;click&lt;/a&gt; to open the popup.&lt;/textarea&gt;
&lt;p&gt;I use a period for the link text and hide it somewhere on the page. This way I can click the hidden link from any computer to disable tracking for that browser. This is an example of what the end result looks like:&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_G06mB5h-kvQ/SYt4g5LG1CI/AAAAAAAAA3w/1yz2bOJswaE/s1600-h/Example.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 278px;" src="http://3.bp.blogspot.com/_G06mB5h-kvQ/SYt4g5LG1CI/AAAAAAAAA3w/1yz2bOJswaE/s320/Example.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5299461893030073378" /&gt;&lt;/a&gt;&lt;p&gt;For some reason Google Chrome does not let your clear the __utmv cookie using JavaScript. It works in IE and it works in Chrome on a localhost page, but it doesn't work on the live blog. A bit strange, but you can always clear the cookie manually in the browser. Oh, and don't forget to setup the filter in Google Analytics to exclude the traffic (see link above)&lt;/p&gt;&lt;p&gt;The next time I work on this I will probably change it so that the tracking status is displayed on the actual link itself using red "__ TRACKING DISABLED __" text if your page views were not being tracked or a normal period to anyone who's traffic was being tracked.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6011603498138679949-4981787036830433889?l=codeblog.theg2.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TheG2NetCode/~4/nIlGL6OZAIM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/TheG2NetCode/~3/nIlGL6OZAIM/javascript-and-css-based-popup-for.html</link><author>noreply@blogger.com (Greg Bray)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_G06mB5h-kvQ/SYt4g5LG1CI/AAAAAAAAA3w/1yz2bOJswaE/s72-c/Example.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://codeblog.theg2.net/2009/02/javascript-and-css-based-popup-for.html</feedburner:origLink></item></channel></rss>
