Saturday, December 25, 2010

How to solve “My PC Randomly Wakes up from Sleep”

Whenever your PC wakes up, Windows keeps a log of why. To view, open a command line and run:

 C:\> powercfg -lastwake
Wake History Count - 1
Wake History [0]
  Wake Source Count - 1
  Wake Source [0]
    Type: Wake Timer
    Owner: [PROCESS] \Device\HarddiskVolume3\Windows\System32\services.exe
    Owner Supplied Reason: Windows will execute '\Microsoft\Windows\Media Center\mcupdate_scheduled' scheduled task that requested waking the computer.

As you can see, my computer woke up because of a scheduled task. Open the Task Scheduler: image And navigate to the task in question (\Microsoft\Windows\Media Center\mcupdate_scheduled, in my case). On the Conditions tab, uncheck wake: image

Friday, December 24, 2010

Why Developers Always Need to use UTC

Assert.AreEqual(new DateTime(2010, 11, 07, 06, 0, 0, DateTimeKind.Utc).ToLocalTime(),
new DateTime(2010, 11, 07, 07, 0, 0, DateTimeKind.Utc).ToLocalTime());

Because when we fall back from Daylight Saving Time, the hour of 1am is repeated, making it ambiguous. Which is why the above test code passes in Central time, since 6am and 7am UTC are both 1am, one 1am CDT, the other 1am CST.

Monday, December 13, 2010

Using XML Namespaces in PowerShell

$xpath = @{
    Start="//e:data[@name = 'BootStartTime']/text()"
    End="//e:data[@name = 'BootEndTime']/text()"
}

$ns = New-Object Xml.XmlNamespaceManager $xml.NameTable
$ns.AddNamespace( "e", "http://schemas.microsoft.com/win/2004/08/events/event" )

[DateTime]$Start = $xml.SelectSingleNode( $xpath.Start, $ns ).Value
[DateTime]$End   = $xml.SelectSingleNode( $xpath.End, $ns ).Value

($End - $Start).ToString() # Displays: 00:03:11.7917783

Via.

Wednesday, December 08, 2010

Full IIS Mode at Windows Azure

One of the nice new features in the December 2010 release 1.3 of the Azure tools is Full IIS Mode, the ability to run multiple web sites in a single Azure web role. The documentation is a bit sparse still, but the short answer is to add multiple <site/> tags in the ServiceDefinition.csdef.

Here's a good post on the Azure blog, and here's some documentation at MSDN.


<Site name="<web-site-name>" physicalDirectory="<directory-path>">
   <Bindings>
      <Binding name="<name-of-the-binding>" endpointName="<endpoint-identifier>" hostHeader="<url-of-the-website>" />
   </Bindings>
</Site>

Tuesday, November 30, 2010

Task Scheduler Engine

This past weekend I published a small open source project at CodePlex, Task Scheduler Engine. It is a simple cron-like scheduling API with a clean fluent interface (also supports XML config, if you prefer typing out assembly qualified names). Use it when you need a simple, in-memory scheduler and when you need tasks to execute at a specific second (in other words, if you start doing math to compute the duration of your timer so that it fires at a specific time, use this instead). If you have multiple services load balanced to execute tasks, this isn’t for you.

Here’s all that’s required to schedule a task (write console output) to execute every ten seconds:

var s = new Schedule()
    .AtSeconds(0, 10, 20, 30, 40, 50)
    .WithLocalTime()
    .Execute<ConsoleWriteTask>();

SchedulerRuntime.Start(s);

Creating your own tasks is just as easy—implement ITask, which has an Initialize method and a Handle method that is called at the scheduled time.

It compiles to an 18KB assembly, has no external (non-framework) dependencies, and is just over 250 lines of code. Add clean, simple scheduling to your .NET application.

Sunday, November 14, 2010

Travis Cooks

I started a new blog over at www.traviscooks.com. Imagine me with a cameraphone uploading quick summaries of what I'm cooking.

On the subject of food, I run Kefirpedia.org, a site where I drop all of my knowledge and research about kefir. If you don't know what kefir is, it's a wonderful probiotic fermented milk beverage—imagine a super yogurt.

Wednesday, September 15, 2010

Learning a new Keyboard Layout

A friend of mine asked me about how I learned Colemak and I sent him this email; thought I’d flesh it out and share.

  • Decide on layout
    • Colemak was the best I’ve found given I already touch-typed QWERTY
    • Go here, paste in a bunch of text that you’ve typed, and then look over the analysis on how far your fingers would have to move in order to type it: http://patorjk.com/keyboard-layout-analyzer/
    • For this email (minus this bullet), Colemak is the best mainstream layout (32.68meters of finger travel), Dvorak 2nd (33.39m) and QWERTY the worst (51.86m). Again, for me, given the amount of similarity to the QWERTY layout, Colemak became the obvious choice for me.
    • Do your own research and look for some of the ergonomic studies that are out there.
  • Typing tutor software to help you learn
  • Making the switch
    • I practiced with TypeFaster in the evenings until I could type with mid 80s% accuracy and ~20wpm. That took a month, maybe more.
    • Then, I went cold turkey. It was painful. I couldn’t really type in either Colemak or QWERTY. My thoughts got stuck and couldn’t get out of brain and into the keys.
    • You will get here, you will feel the emotional agony, and you must move forward. Stick with it.
    • If you are thinking about they layout as a “letter-to-key” lookup map (which is naturally how you start), you need to switch to thinking about “speaking with your fingers.” It’s hard to explain, but as the thoughts form as words in your mind, you can’t think letter by letter—the thoughts and phones must naturally express themselves as finger movements, just as the thoughts and phones naturally become mouth and tongue movements when you speak. (Inspired by this post.)
  • Nice keyboards – learn about the various key switch technologies - http://hothardware.com/cs/blogs/mrtg/archive/2009/03/08/mechanical-key-switch-keyboards-demystified.aspx
  • If you want to find some REAL nerdy keyboard stuff, this forum is the place: http://geekhack.org/

Tuesday, September 14, 2010

Colemak, II

I’ve been typing full-time on Colemak now for a few months and it’s really going quite well. I stumble and make a few typos, but it is continually getting better. I just ran a test and scored 67wpm @ 99.6% accuracy. (That’s an upper end test; I am probably closer to mid-50s on average.) I’m declaring victory.

Sunday, September 05, 2010

ASP.NET MVC No Caching Attribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Application
{
    /// <summary>
    /// Add this attribute to your Actions and they will have a "Cache-Control: private, max-age=0" header,
    /// ensuring that the responses are not cached by the user's browser. 
    /// </summary>
    public class NoCachingAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
            filterContext.HttpContext.Response.CacheControl = "private";
            filterContext.HttpContext.Response.Cache.SetMaxAge(TimeSpan.FromSeconds(0));
        }
    }
}

Monday, August 30, 2010

Regular Expressions in SQL 2008 R2

At last! Supported, official regular expression support in SQL Server! It’s a bit of a hack, so I may have to redact the “supported” comment. But here are the fully-documented scripts you get when you install Master Data Services on SQL 2008 R2.

Here’s how to extract them and use them on your own database (only tested on R2, but I suspect any edition of SQL server that supports the CLR would work with these; you will need R2 to install MDS, however):

  • Install MDS from D:\MasterDataServices\x64\1033_ENU
  • Run the Configuration Manager and set up a new MDS database. You will be copying from here and into your own database.
  • Script the Microsoft.MasterDataServices.DataQuality assembly (right click / Script as / Create)
    image
    image
  • Change the AUTHORIZATION to db_datareader
  • Find the functions you need (most under scalar, some under table), and right click, script, create:
    image
    image
  • Delete the USE block, and change the namespace to dbo, or one of your own.
    image
  • Run all of the scripts on your own database, starting with the assembly.

Saturday, August 21, 2010

Space Pen

You know that frustrating feeling when you pick up a pen and it doesn’t write? You scribble and shake it, but it doesn’t do much.

I decided a while ago to try one of those “space pens” to see if its pressurized ink cartridge would solve that problem, and it 100% does. If you want an inexpensive pen that reliably writes the first time, every time, with a continuous, even flow, check these guys out. I went with this model, which fits in my pocket when closed and opens to a comfortable writing size. It’s still just a ballpoint pen and writes like one, but it has a nice weight and balance. All for under $11. Worth every penny.

Fisher Space Pen, X-Mark Bullet Space Pen, Matte Black (SM400BWCBCL)

Thursday, July 15, 2010

How to modify Commerce Server 2009 Web Parts

If you’re running Commerce Server 2009 in SharePoint, you’ve likely wanted to modify an out-of-the-box CS web part. This post will show you a shortcut. The normal way to do this is to open the CS extensibility kit (C:\Program Files\Microsoft Commerce Server 2007\Microsoft Commerce Server 2009\Sdk\Samples\CommerceSharePointExtensibilityKit), resign all of the assemblies with your own SNK, and then update every reference everywhere to be aware of your SNK’s public key token. Here’s a forum post that explains this in more detail. When I tried this I missed some references in config files and the site blew up. If you’re working in a production environment, proceed with caution!

The shortcut is to create a new web part that inherits from the base Commerce Server web part and set the UserControlVirtualPath with your own ASCX (copied from the extensibility kit). This obviously limits your options compared to cracking open the full source, but it is a vastly simpler deploy experience that will allow you to at least customize the markup for your creative team.

Take a look at the screenshots below; there shouldn't be too many surprises. One gotcha to bear in mind is that if your control has a <%@ Register Src="ReadOnlyAddressDetail.ascx" ...> directive, you have to add the dependant ASCX files—the web part won’t render without it, and it doesn’t seem to “know” to fall back to the OOB markup.

Once you deploy the web part, you can add yours in place of the stock Commerce Server one. Piece of cake.

Blog

Saturday, July 10, 2010

Home Server Drive Balancer

Check out this great utility for your Windows Home Server, Drive Balancer. It’s designed to rebalance the storage across your pool. It came in handy in my case because I added a new 2TB drive (formerly 4x500GB, now 3x500+1x2TB). I kept waiting for the new drive to start getting files, but that never happened. Then I ripped a Blu Ray and the stupid thing started telling me that there wasn’t enough space to duplicate the new file...grrr...just move some files around and there’s plenty of room!! That’s what this utility does, it solves the literally only gripe I’ve found with this otherwise excellent product.

Be sure to read the readme and walkthrough before you get started. Interestingly, it doesn’t move the files, it just adds blank files in a way that, when triggered by the utility, the built-in file mirroring ends up rebalancing. Definitely add it to your toolkit.

Wednesday, June 16, 2010

Colemak

I’m slowly learning a new keyboard layout, Colemak. It was invented in around 2005 with the goal of being more efficient than QWERTY and Dvorak, and be easier to learn for QWERTY typists. It keeps ZXCVAQW in the same place for common shortcuts, as well as most punctuation. The hardest part about it is that my fingers can’t keep pace with my thoughts, and that is paralyzing for the writing process! If you’re interested in learning more, visit Colemak.com. No special hardware or software is required, just install the layout for your operating system and start training!

Monday, May 10, 2010

Pointing Stick USB Keyboard Roundup Review

Samsung top, center; Lenovo on bottom; Unicomp up topTrackpoint, pointing stick, eraser head mouse, nipple mouse—whatever you call it, if you’re like me and you love it, you don’t want to use a computer without one.

After a chiropractor urged me to stop stooping to look down at my laptop display (which is giving me “military neck,” or a flattening of the curve in the neck), I decided to take my laptop ergonomics more seriously.

First up was raising the laptop display to an appropriate height. I chose the 3M Vertical Notebook Riser (LX550), as it seemed to get the display to the most appropriate height (most competing products raise the body of the laptop at a much shallower angle and/or don't have full freedom of adjustability). While it’s not the most travel-friendly (Logitech’s Notebook Riser wins that award), I chose function over form. Besides, a few reams of paper or a shoebox can serve as a laptop stand in a pinch.

The Keyboards

Now on to the good stuff: USB Keyboards with Pointing sticks. This is a very small product category, and you have to get rid of a lot of your wishes: a natural curve, wireless/bluetooth—none of those products exist with a pointing stick. I found three products meeting my requirements—quite simply, a USB keyboard with a pointing stick:

Samsung, Lenovo and Unicomp, top to bottom
The Samsung Q1: The Bad

Samsung and Lenovo A small and tidy keyboard that even comes with a travel pouch! I was the most excited about this keyboard, and the most disappointed. The keys feel flimsy, the back wasn’t perfectly flat so it wobbled when I typed, and worst of all, the pointing stick just isn’t very good. It has a weird acceleration thing going on, where the center is fairly numb but as you push harder and farther from center, it accelerates non-linearly. Thumbs down for the keyboard, thumbs way down for the mouse.

Other negatives: The WIN key is in the bottom-right, which I can live with. But Home and End require FN modifiers (FN + PgUp = Home), which is a big problem for someone who spends a lot of time in Visual Studio.

The redeeming graces? It’s teeny without feeling teeny. From the left of ‘A’ to the right of ‘;’ it measures 7 1/4”—just 1/4 inch shorter than a regular full-sized keyboard. That and they shave off some more size with narrower Caps Lock, Shift and Enter keys.

If you need an external keyboard occasionally and you need a small & portable model, this keyboard might be for you. But if you’re looking for a full-time keyboard, the Lenovo is still pretty tidy for travel and has a much better feel (plus it’s cheaper). Verdict: not recommended.

Lenovo ThinkVantage ThinkPad USB Keyboard with TrackPoint: The Best All-Around

Best keyboard layout of the group When I unplugged the Samsung and plugged in the Lenovo, I knew I was never going back. The feel of the keys are sturdy. Don’t let the “regular” laptop keyboard look fool you, it’s even better than the keyboard on my Toshiba, as well as my girlfriend’s modern Lenovo laptop. The keys have a buttery softness to them, a firm response, and they’re quiet.

Oh and the pointing stick. It’s perfect. Perfect. Sensitive and responsive, without a dead zone in the center like the Samsung, and it stops on a dime. Perfect.

A lot of reviewers on Amazon have complained that this keyboard suffers from a lag that leads to double-presses or delayed shift-releases. I can say with confidence that the model I got does not suffer from that. I type in the 70 to 90 WPM range, so I’m pretty confident that if the problem existed I’d see it.

If you install the drivers from Lenovo [see footnote 1], you’ll enable the center button+TrackPoint to scroll, plus media keys/volume controls that are very useable.

As for the layout, it’s full-sized (7 1/2” from left of ‘A’ to right of ‘;’), Home and End are actual keys, WIN is in the bottom-left. The only thing is FN is in the far bottom-left corner, where I prefer CTRL, but it’s a minor adjustment that’s well worth it.

Size: it’s slim and sleek. The wrist rest is nice, something I’m used to in a laptop keyboard. It slips into my laptop bag alongside the laptop without any trouble.

Great response, great feel, perfect mouse, acceptably portable, reasonable price: highly recommended—buy now.

Unicomp EnduraPro: The Best to Type On

Lenovo and Unicomp, with their feet extended First a bit of history on Unicomp. They make the only “real” clickety-clackety keyboards, having bought the “buckling spring” patent from IBM/Lexmark some years ago. (Here’s an interesting NPR piece on Unicomp.) Allegedly, buckling spring keyboards are faster than modern “blister” keyboards (referring to the switch underneath the key). These keyboards are supposed to be easier on your hands than modern keyboards, too: when you type on a blister keyboard (including the Lenovo), you don’t get tactile feedback until you push all the way through the key, which is to say, it’s as if you’re hammering away on a hard surface. With a buckling spring, you type until the spring buckles, but not when the movement stops, so it’s gentler. Make sense? And does it live up to the hype?

DSC_5765Without a doubt, it is the best keyboard to type on. The key action is crisp, fast, the keys snap back instantly, and it’s precise. After typing a couple of long-winded emails and much of this review on it, I quickly got over the learning curve of the different “throw” of this type of keyboard over the typical laptop keyboard I’m used to. As promised, the key press registers after about 2mm of pressing, but the bottom of the keywell isn’t for another 1 or 2 mm. Definitely a different and better typing experience than laptop keyboards I’ve grown used to over the past few years.

The pointing stick, however, is another matter. It is on a very long pole, and it’s moderately sensitive. The Lenovo’s pointing stick doesn’t really move, it just senses the pressure you apply to it. The Unicomp’s pointing stick is more like a joystick: you have to wiggle it around and move it in the direction you want. Couple its loose wiggling with a dead zone in the center and only 2 buttons that are hard to click, and it didn’t pass muster. Better than the Samsung, but not in the same league as the Lenovo.

Other notes: top-notch build quality (it weighs nearly 5lbs) and I enjoyed using a full-sized desktop layout, but missed the multimedia keys and volume controls that I quickly found to love in the Lenovo.

Side By Side Typing Speed

I ran through two iterations of this Aesop Fables typing test on each keyboard, in the opposite order the second time, taking the average.

  • (Model): (Min)/(Max) (Average)
  • Samsung: 76/88 82
  • Lenovo: 86/95 90.5
  • Unicomp: 90/95 92.5

While this isn’t a perfect science experiment, it does show that the Unicomp and the Lenovo are fast, topping out for me at 95 WPM. The low initial Lenovo score came because I was used to typing on the Unicomp and switched back to the short-throw laptop-style keyboard and my fingers just didn’t know what to do!

Conclusions and Recommendations

If this review were about keyboards, I’d give the best and fastest typing experience to the Unicomp. But since this review is about pointing stick keyboards, the award goes to the Lenovo. It is a great keyboard, and has a perfect pointing stick. Overall usability goes to the Lenovo, too: with its media keys, middle mouse button with scrolling, and forward & back buttons, it’s the best to use for everyday computing. Typing on it is very good, too, even though it has a traditional (but sturdy) laptop keypress mechanism. If I lived my life on a Bash or Powershell prompt and rarely reached for the pointing stick, I would keep the Unicomp in a heartbeat. Even though I write a lot of code and emails and would benefit from a great typing experience, I really need a great pointing stick to find my way around a modern OS and development tools like Visual Studio.

Maybe someday a perfect keyboard with the right tactile response and the perfect 3-button pointing stick will come to market. Maybe it will even have a gentle ergonomic curve and bluetooth and still be tidy enough to travel with. Maybe someday.

Buy the Lenovo keyboard here at Amazon.com

P.S. This page is full of associate links on Amazon. If you appreciate this review and decide to purchase one of these products from Amazon, please support this site by following the links when you add to your shopping cart.

[1] The drivers install a startup program called skd8855.exe in HKLM\Software\Microsoft\Windows\CurrentVersion\Run that doesn’t seem to do anything. I left ltpPoint because it seems to be responsible for the extra features tab in the Mouse control panel.

Wednesday, May 05, 2010

CryptographicException during SharePoint Configuration Wizard

(Re)installing MOSS 2007 on Server 2008 R2 I got this error:

Calling SPServiceInstance.Provision for instance Microsoft.Office.Excel.Server.ExcelServerSharedWebServiceInstance, service Microsoft.Office.Excel.Server.ExcelServerSharedWebService
Task services has failed with an unknown exception
Exception: System.Security.Cryptography.CryptographicException: Object already exists.

   at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
   at System.Security.Cryptography.Utils._CreateCSP(CspParameters param, Boolean randomKeyContainer, SafeProvHandle& hProv)
   at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
   at Microsoft.SharePoint.Utilities.CertificateManager.CreateSelfSignedSslCertificate(CspParameters parameters, X500DistinguishedName name, DateTime expiresAfter)
   at Microsoft.SharePoint.Administration.SPProvisioningAssistant.ProvisionIisWebSite(String serverComment, String[] serverBindings, String[] secureBindings, AuthenticationMethods authenticationMethods, String[] authenticationProviders, String path, AccessFlags accessFlags, String applicationName, String applicationPoolId, String[] scriptMaps, String sslCertificateSubjectName)
   at Microsoft.SharePoint.Administration.SPMetabaseManager.ProvisionIisWebSite(String serverComment, String[] serverBindings, String[] secureBindings, Int32 authenticationMethods, String[] authenticationProviders, String path, Int32 accessFlags, String applicationName, String applicationPoolId, String[] scriptMaps, String sslCertificateSubjectName)
   at Microsoft.Office.Server.Administration.SharedWebServiceInstance.Synchronize()
   at Microsoft.Office.Excel.Server.ExcelServerSharedWebServiceInstance.Synchronize()
   at Microsoft.Office.Server.Administration.SharedWebServiceInstance.Provision()
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.InstallServiceInstanceInConfigDB(Boolean provisionTheServiceInstanceToo, String serviceInstanceRegistryKeyName, Object sharepointServiceObject)
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.InstallServiceInstances(Boolean provisionTheServiceInstancesToo, String serviceRegistryKeyName, Object sharepointServiceObject)
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.InstallServices(Boolean provisionTheServicesToo)
   at Microsoft.SharePoint.PostSetupConfiguration.ServicesTask.Run()
   at Microsoft.SharePoint.PostSetupConfiguration.TaskThread.ExecuteTask()

This is actually a file permission error. Bring up properties for the folder C:\Users\all users\Microsoft\Crypto\RSA\MachineKeys, Advanced, Auditing tab, add Full Control for Everyone on the local machine for both failures and successes.

Run the configuration wizard again. It will still fail, but now you’ll know which file has the permissions error.

Bring up the Event Viewer, Security log. Compare the timestamp from the log to the failure audit: there’s your file. Correct permissions (probably take ownership and give yourself full control), run the Wizard again, it will succeed (at least for this step).

When you’re done, turn off the file auditing.

Wednesday, April 28, 2010

On Organization

I have spent too much time organizing the wrong parts of my life.

I used to keep my inbox in Outlook immaculate—zero unread items, everything meticulously categorized and filed. But I rarely went back and looked for items by categories of folders, I almost always searched for it. So I stopped. Now I keep a “Recent Unread” folder that is a view on the items still requiring attention that have come in during the last week or so. If it doesn’t make it into an action item by that time, then it falls out of scope, and I don’t have to care.

I used to store my receipts immaculately. Scan them all in, and then shred the paper, giving them proper file names so they’d sort by date. But I never looked back on them. Now I scan them batches every few months, still grouped by debtor, sort of lazily dumped in a folder.

Same with my business reimbursement expenses. They’re almost always PDF attachments on emails (hotels, airfare, etc), and I used to save them off and rename them into a convention. But for what? Now I copy the whole email into a folder by expense period—much less work, and still easily retrievable when the occasional audit comes through.

If I need to look back, yes, it will take a little more effort, but I so rarely look back. It’s worth the net savings to have to work a little harder when I look back than it is to immaculately organize something I’ll so rarely need to take advantage of. That time is better spent elsewhere, like posting on my blog.

What do you over-organize? Where could you shift the time burden to lookup instead of storage, and net time savings?

Wednesday, April 07, 2010

United's IVR

I called United's 1K-only 800 number today from my cell phone. It went like this:

  • (Recorded voice): Hello and thank you for calling United. Is this ...Travis?
  • (Me): Yes
  • (Recorded voice): Is this about your reservation ...Monday April 12th...to...[Location].
  • (Me): Yes
  • (Recorded voice): What is this regarding? [Listed options]
  • (Me): [One of the options]
  • (Recorded voice): Thank you. I'll connect you with an agent to help you with that.
  • A human answered immediately. She helped me quickly and effortlessly.

Phenomenal. I love good service. And never once did I need to enter my member number, a confirmation number, or anything: I just dialed from my phone and it knew.

Tuesday, April 06, 2010

Google Public DNS

I just configured my router to use Google's Public DNS (8.8.8.8 and 8.8.4.4) and pass those IPs down to my clients. Allegedly it'll be faster as they proactively cache and have the infrastructure to handle the scale of "the Internet." Worth a test, eh?

Monday, March 22, 2010

Ripping and Transcoding Movies

I use MakeMKV to rip DVDs and Blu Rays to an archive format. I typically rip the main video title, the primary audio track, and all subtitles. I rip the videos to \\SERVER\Videos\Incoming, which is a share residing on my Windows Home Server. I have the script below running as a service (using SrvAny.exe and Any Service Installer), although running it as a service is totally optional. The script below watches that Incoming folder and when it finds a new file, it verifies that it's not still being written (that its size doesn't change in 5 seconds), and then it kicks off two transcode jobs using HandBrake, one for an iPhone and one for an archive format.

Once you get this job set up, all you have to do is rip your movie into \\SERVER\Videos\Incoming\[MOVIE NAME]\title00.mkv and the transcodes will be dumped into \\SERVER\Videos\Movies\[MOVIE NAME]\iPhone.m4v and Archive.mp4. In other words, one-click transcoding.

Write-Output ("Setting process priority to Idle."); [System.Diagnostics.Process]::GetCurrentProcess().PriorityClass = [System.Diagnostics.ProcessPriorityClass]::Idle; $incomingDir = "\\SERVER\Videos\incoming"; # Loop forever while(1) { $mkvs = get-childitem $incomingDir -recurse -filter *.mkv; if(!($mkvs)) { Write-Output ("No file found."); } else { # Force into an array if only one element found if(!($mkvs.Count)) { $mkvs = ,$mkvs; } Write-Output ("Found $($mkvs.Count) files"); foreach($mkv in $mkvs) { Write-Output ("Processing $($mkv.Directory.Name)"); #if($mkv.Directory.Name -notmatch "There Will Be Blood") #{ # continue; #} Write-Output ("Checking to see if file is still being written..."); $info1 = Get-Item $mkv.FullName; start-sleep 5; $info2 = Get-Item $mkv.FullName; Write-Output ("."); if($info1.Length -ne $info2.Length) { Write-Output ("Skipping!"); continue; } $outputDir = "\\SERVER\Videos\movies\$($mkv.Directory.Name)"; $outputFilePrefix = "\\SERVER\Videos\movies\$($mkv.Directory.Name)\$($mkv.Directory.Name)"; if(!(test-path $outputDir)) { mkdir $outputDir; } # Kick off two transcode jobs $psI = [Diagnostics.Process]::Start("C:\Program Files\Handbrake\HandBrakeCLI.exe", "-i ""$($mkv.FullName)"" -t 1 -o ""$outputFilePrefix - iPhone.m4v"" -f mp4 -X 480 -e x264 -q 20 -a 1 -E faac -6 dpl2 -R 48 -B 128 -D 0.0 --markers=""C:\Documents and Settings\Administrator\Local Settings\Temp\2\iPhone-1-chapters.csv"" -x cabac=0:ref=2:me=umh:bframes=0:subq=6:8x8dct=0:trellis=0:weightb=0 -v 1"); #2>"$outputFilePrefix - iPhone - Error.txt" > "$outputFilePrefix - iPhone.txt"; $psA = [Diagnostics.Process]::Start("C:\Program Files\Handbrake\HandBrakeCLI.exe", "-i ""$($mkv.FullName)"" -t 1 -o ""$outputFilePrefix - Archive.mkv"" -f mkv --strict-anamorphic -e x264 -q 20 -a 1 -E ac3 -6 auto -R Auto -B 32 -D 0 --markers=""C:\Documents and Settings\Administrator\Local Settings\Temp\2\archive-1-chapters.csv"" -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v"); #$psI = & "C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "$($mkv.FullName)" -t 1 -o "$outputFilePrefix - iPhone.m4v" -f mp4 -X 480 -e x264 -q 20 -a 1 -E faac -6 dpl2 -R 48 -B 128 -D 0.0 --markers="C:\Documents and Settings\Administrator\Local Settings\Temp\2\iPhone-1-chapters.csv" -x cabac=0:ref=2:me=umh:bframes=0:subq=6:8x8dct=0:trellis=0:weightb=0 -v 1 2>"$outputFilePrefix - iPhone - Error.txt" > "$outputFilePrefix - iPhone.txt" #$psA = & "C:\Program Files\Handbrake\HandBrakeCLI.exe" -i "$($mkv.FullName)" -t 1 -o "$outputFilePrefix - Archive.mkv" -f mkv --strict-anamorphic -e x264 -q 20 -a 1 -E ac3 -6 auto -R Auto -B 32 -D 0 --markers="C:\Documents and Settings\Administrator\Local Settings\Temp\2\archive-1-chapters.csv" -x ref=2:bframes=2:subq=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0 -v 2>&1 #> "$outputFilePrefix - Archive.txt" $psI.WaitForExit(); $psA.WaitForExit(); mv $mkv.FullName "$outputFilePrefix - Original.mkv"; if($psI) { #echo "in it"; #$psI.WaitForExit(); #Wait-Process -InputObject $psI; #Wait-Process -InputObject $psA; #mv $mkv.FullName "$outputFilePrefix - Original.mkv"; } else { #Write-Output ("Error processing $($mkv.Directory.Name)"); } #break; } } # Wait one minute, and then try again. start-sleep 60; }

Thursday, March 11, 2010

How to access the Targeting Context from within a Commerce Server Basket Pipeline

I fixed a bug yesterday where an order-level discount targeted against Targeting Context.Subtotal had an incorrect value—it was set in code before running the basket pipeline, but the subtotal was inaccurate before running the pipeline (newly added items to the basket had a price of zero prior to the pipeline execution, for example).

The solution was to update the subtotal in the targeting context during pipeline execution, after fetching the latest pricing data from the catalog and before running the OrderDiscount pipeline component. Here’s the code to get at the targeting context from within a pipeline:

public int Execute(object pdispOrder, object pdispContext, int lFlags)
{
    IDictionary context = (IDictionary)pdispContext;
    Decimal subtotal = (decimal)((Microsoft.CommerceServer.Interop.Profiles.IProfileObject)context["ContextProfile"]).Fields["Subtotal"].Value;
}

Tuesday, January 26, 2010

Announcing ePubLib

I have published a project on CodePlex, ePubLib. ePub is quickly becoming the defacto standard for e readers, and after getting my hands on a (used and cheap) Sony Pocket Reader I wanted to be able to create documents to put on the device.

The format isn't particularly complicated, but there are a lot of little things that have to line up. This library makes it extremely easy. Create a Book object. Create 1 or more Chapter objects. Add the Chapter to Book.Chapters. Call Book.Save(). You can do the same thing for images as of the commit last night. The only knowledge that's required is basic XHTML skills and .NET to use the library.

I also wrote a utility to log me into The Economist's web site (I'm a paying subscriber) and scrape the Print Edition. It works great, a proper TOC, all of the articles and all of the images. I don't think I can upload that source to CodePlex due to perceived copyright concerns, but drop me a comment if you're interested.