Scott Hanselman

A vCard Preview Handler using the Coding4Fun DevKit

August 12, '07 Comments [5] Posted in Coding4Fun | Programming
Sponsored By

ExplorerForm I sat down with the Coding4Fun Developer Kit and immediately noticed the Preview Handler stuff. I got addicted to Preview Handlers back when Tim wrote one for PDFs. They are darned useful and it seems to me that any application that adds a new file type should add a preview handler for it. They are used in the Vista Explorer, in Outlook 2007 and in Windows Desktop Search. If you or your company makes an explorer replacement, you can also host a Preview Control and add Preview functionality to your own File Explorer application.

I wanted to make a vCard Preview Handler so I could see what's inside a vCard on systems that don't have Outlook. Here's the process to create your own Preview Handler in no time (keeping in mind that the kit is BETA).

  • After installing the C4F Developer Kit, make new Class Library project and add a reference to the PreviewHandlerFramework.
  • Create a new class like below and add the [PreviewHandler] attribute with a name for your project, the extension or extensions (like .foo;.bar), and another Guid for the COM Stuff.
    • You can get new GUIDs either via GuidGen.exe included with the Windows SDK or online at http://www.guidgen.com/ or in PowerShell via [Guid]::NewGuid().ToString()
  • Also, include a ProgId for your new class. I just used the namespace.classname.
  • Notice that I derived from FileBasedPreviewHandler. You'll need to override CreatePreviewHandlerControl and return a new instance of your own Control that is derived from FileBasedPreviewHandlerControl. The boilerplate is below. It's inside Load() where you create whatever WinForms controls you need to and add them to the this.Controls collection.
using C4F.DevKit.PreviewHandler.PreviewHandlerFramework;

namespace C4F.DevKit.PreviewHandler.PreviewHandlers
{
    [PreviewHandler("Hanselman Silly vCard Preview Handler", ".vcf", "{42810C0B-FEA8-4dbf-A711-5634DFBA9F3B}")]
    [ProgId("C4F.DevKit.PreviewHandler.PreviewHandlers.vCardPreviewHandler")]
    [Guid("D193B258-AC07-4139-B334-C20F18F4FC7C")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComVisible(true)]
    public sealed class vCardPreviewHandler : FileBasedPreviewHandler
    {
        protected override PreviewHandlerControl CreatePreviewHandlerControl()
        {
            return new vCardPreviewHandlerControl();
        }

        private sealed class vCardPreviewHandlerControl : FileBasedPreviewHandlerControl
        {
            public override void Load(FileInfo file)
            {
//ADD STUFF HERE } } } }

vCards are funky things, and there's multiple versions of the format. The general format is like this:

BEGIN:VCARD
VERSION:2.1
N;LANGUAGE=en-us:Hanselman;Scott
FN:Scott Hanselman
ORG:Microsoft
TITLE:Senior Program Manager
TEL;WORK;VOICE:+1 (503) 766-2048
TEL;HOME;VOICE:+1 (503) 766-2048
TEL;CELL;VOICE:+1 (503) 766-2048
ADR;WORK;PREF:;;One Microsoft Way;Redmond;WA;11111;United States of America
LABEL;WORK;PREF;ENCODING=QUOTED-PRINTABLE:One Microsoft Way=0D=0A=
Redmond, WA  11111
ADR;HOME:;;5 Main Street;Main Town;OR,;12345;United States of America
LABEL;HOME;ENCODING=QUOTED-PRINTABLE:5 Main Street=0D=0A=
Main Town, OR, 12345
URL;WORK:
http://www.hanselman.com
EMAIL;PREF;INTERNET:firstname@lastname.com
REV:20070810T050105Z
END:VCARD

But there's a million extensions to this format and things can get very complex very fast. I set myself a goal of getting something passable working in a few hours, so I decided to preview the vCard in a DataGrid. That made Load() look like this:

public override void Load(FileInfo file)
{
    DataGridView grid = new DataGridView();
    grid.DataSource = ConvertVCardToDataTable(file);
    grid.ReadOnly = true;
    grid.Dock = DockStyle.Fill;
    grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
    Controls.Add(grid);
}

Next, I took the FileInfo and spun through it, breaking up each line and sticking it into a static DataTable, the format most friendly to the DataGridView.

private static DataTable ConvertVCardToDataTable(FileInfo file)
{
    DataTable table = new DataTable();
    table.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
    table.TableName = file.Name;

    using (StreamReader sr = file.OpenText())
    {
        table.Columns.Add("Data");
        table.Columns.Add("Value");

        string line;
        while ((line = sr.ReadLine()) != null)
        {
            if (line.Length > 3)
            {
                string[] parts = ProcessVCardLine(line);
                if (parts != null && parts.Length == 2)
                {
                    table.Rows.Add(parts);
                }
            }
        }
    }
    return table;
}

ProcessVCardLine just returns a string array of "name,value" given a single vCard line. Again, I never said it was pretty, I just said it worked.

private static string[] ProcessVCardLine(string line)
{
    //This is by no means a complete or even passable parsing of the fairly complex vCard format.
    List<string> nameValue = new List<string>();

    if (line.StartsWith("BEGIN:VCARD")) return null;
    if (line.StartsWith("VERSION:")) return null;
    string[] parts = line.Split(':');
    if (parts.Length == 2)
    {
        AddVCardLine(parts, ref nameValue, "TZ", "TimeZone");
        AddVCardLine(parts, ref nameValue, "NICKNAME", "Nickname");
        AddVCardLine(parts, ref nameValue, "N", "Name");
        AddVCardLine(parts, ref nameValue, "FN", "Friendly Name");
        AddVCardLine(parts, ref nameValue, "ORG", "Organization");
        AddVCardLine(parts, ref nameValue, "TITLE", "Title");
        AddVCardLine(parts, ref nameValue, "TEL", "Phone");
        AddVCardLine(parts, ref nameValue, "ADR", "Address");
        AddVCardLine(parts, ref nameValue, "URL", "Website");
        AddVCardLine(parts, ref nameValue, "EMAIL", "Email");
        AddVCardLine(parts, ref nameValue, "X-MS-IMADDRESS", "IM");
    }

    return nameValue.ToArray();
}

private static void AddVCardLine(string[] parts, ref List<string> nameValue, string name, string friendlyName)
{
    if (parts[0].StartsWith(name) && parts[1] != null)
    {
        nameValue.Add(friendlyName);
        nameValue.Add(parts[1].Replace(";", ",").Trim().Trim(','));
    }
}

Registry Editor Because this is a .NET assembly that will be called by an app expecting a COM dll, you'll need to put it in the GAC and run Regasm on it.

I made this easier during development by adding these two lines to the Post-build event command line. You may need to search your system to find where Gacutil.exe and Regasm.exe are on your system, or you can download the .NET Framework 2.0 SDK.

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\Gacutil.exe" /i "$(TargetPath)"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\Regasm.exe" /codebase "$(TargetPath)"

Once registered, the new vCard Preview Handlers is available all over Windows to any app that cares to use it.

I've looked at this code a couple of times, not just because it's poopy, but because I felt there must be at least a few clean ways I could have made the code cleaner/terser using some of the new C# 3.0 features like Anonymous Types, and yield. Any ideas?

Here's the real tragedy. After I wrote this very sad little "just barely good enough" vCard parser, I discovered that the Coding4Fun DevKit already included a very complete vCard parsing implementation.

Curse my metal body! The vCard sample is in the Contacts project within C4FDevKit and it's scrumptious. Well, live and learn. Anyway, I had fun and it took less than an hour to get a useful (to me) PreviewHandler working. The C4FDevKit includes samples and compiled PreviewHandlers for CSV, generic binary, Icons, XML files via IE, MSIs, PDFs, Resx and Resources, SNK (keys) and Zip Files. Sweet.

You can more easily test your Preview Handlers using the PreviewHandlerHost control on a simple WinForms app, or even easier by using the already-written PreviewHandlerHost at Coding4Fun\C4FDevKit2008v1\Preview Handlers\Samples\VB\PreviewHandlerHostSample as seen in the screenshot above.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Reading to Be a Better Developer - The Coding4Fun DevKit

August 12, '07 Comments [5] Posted in Coding4Fun | Learning .NET | Programming
Sponsored By

Coding4Fun Logo I've written a number of articles for Coding4Fun, in fact, there's a whole category for them on my Blog here. Dan Fernandez runs Coding4Fun and there's a LOT of Coding4Fun writers, so I can't keep track of all the cool stuff that's being done on the project.

I was looking around for some really good Source Code to read. You know the whole Be a Better Developer in 6 Months thing? We did a podcast on it, and it's being discussed in the forums. One of the things that I thought was the most important was reading other people's code. I postulated that writers don't become better just be writing, but by reading.

Anyway, I stumbled on a treasure trove of source to read. Recently released, and comparatively quietly, was the Coding4Fun Developer Kit 2008 Vol 1 (BETA) (whew!) that I will refer to as the C4F DevKit because that name is crazy long.

The "Vol 1" designation is cool because it implies it'll be a series of projects. Here's the kinds of stuff it includes (very DIY (Do It Yourself) friendly):

  • Bluetooth – Serial Port, File Transfer and Object Push; plus Device Discovery and Service Discovery
  • Windows Vista Contacts – abstraction of the Windows Contacts API 
  • Messaging – Better APIs for SMTP and POP3
  • Power Management – Access Windows Vista Power Management features like rebooting, hibernating and locking a computer; get battery status on a laptop too
  • Windows Desktop Search – Easy API to Search
  • Windows Vista Picture Acquisition – Acquire pictures and videos from common devices like digital cameras
  • Preview Handler – Resolve predefined file types such as Microsoft Word , Visual Basic and Visual C# source files, images and many others in their own applications.
  • SoundRecorder - record audio sounds and play them back information with Windows Vista's API
  • RSS ScreenSaver - WPF RSS ScreenSaver 
  • P2P Picture Share - share your pictures with family and friends

C4F Toolbox There's a LOT of source here - a bunch of it I could use in some of my on-the-side projects. Some of it is "mashups," brining different APIs together in interesting way, while much of it is very clean abstractions of COM or P/Invoke APIs for useful things like Image Acquisition and Source Recording. These are the kinds of APIs that it'd be nice to see pushed back into the BCL/platform. It also serves as a good primer on how to create a managed API on top of an unmanaged one. I think I'll do some posts on it. The Preview Handler on is very nice.

The other thing that's cool about these "components" is that a bunch of them are done as controls that live in the Visual Studio 2008 toolbox (and they all work on the Express SKUs) so in many cases using them is just a drag-and-drop operation with a Smart Tag. Apparently the plan is to add as many Smart Tags as possible.

While I was able to run the installer and compile most of the code on Windows XP, many of the projects are Vista specific. I think in the future there will be an option to select the projects that are specific to your OS. If you've got Visual Studio 2008 or the C#/VB Express version, you'll be fine. The Express 2008 SKU runs very fast under my XP SP2 VM and I've been very happy with it.

I wanted to see how fast I could get something new written with some of this source, so I set off to create a vCard Preview Handler. Remember what a Preview Handler is? It's those little in-proc plugins that can be used by Outlook or the Vista Explorer to show you what a file looks like without opening the host application. Tim Heuer made a PDF Preview Handler using some code from the obscenely talented Stephen Toub (here's a list of all his articles on MSDN).

My next post will talk about writing a vCard Preview Handler using the code in the C4F DevKit. I wanted to see just how quick and easy (or totally not at all) it would be, considering all the COM Interop and what-not.

I've really enjoyed reading the code in this kit. Nothing makes me realize what a crap programmer I am like reading a good programmer's code.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Coming Tuesday - dasBlog 2.0 and Medium Trust

August 12, '07 Comments [4] Posted in ASP.NET | DasBlog
Sponsored By

Well, the plan was to get dasBlog running on Medium Trust and 2.0 and releasing quickly.

Of course, the best laid plans of mice and men, right?

We've set the date for the dasBlog 2.0 Medium Trust Release for this coming Tuesday. Personally, I'm compiling it with Visual Studio 2008 with no problems, and I've recently got it dasBlog compiling and running on IIS7 on Vista 64 with very little trouble. It's Not Scary™.

Tony Bunce has a fine write-up on the issues we ran into with dasBlog on Medium Trust. Here's some highlights:

"The goal of medium trust is for hosting providers to provide functional ASP.NET 2.0 hosting while also protecting against rogue or malicious applications. Unfortunately that protection comes at the cost of application flexibility. ...There are a few features that are limited in a medium trust environment: SMTP on alternative ports and Mail to Weblog via POP3...dasBlog will let you know that you don't have these privileges by displaying warnings on the configuration page.

There is some good news though, these limitations won't affect most users.  Many hosting providers that run limited trust environments don't run in the default medium trust, but rather a "modified full trust".  In that case you may already have all the permissions you need for all of the features to work."

Go check out his post for more details. The most interesting issue we bumped into was that you aren't supposed to be able to call out via HTTP on the server side to any other connections unless they match your originURL in your web.config. In other words, my blog at www.hanselman.com can't call to any other site that isn't hanselman.com. However, you can set you originUrl to a regular expression like ".*" and then you can connect anywhere. Phil Haack noticed this and got the fix from Cathal Connollys.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 76 - F# with Robert Pickering

August 10, '07 Comments [6] Posted in Learning .NET | Podcast | Programming
Sponsored By

My seventy-sixth podcast is up. In this show, I chat with Robert Pickering, author of the very fine Foundations of F#. We ask the question 'Why F#?' and talk about functional languages and some of the features of F# that make it a great introduction to FP for .NET programmers.

NOTE: If you can, while listening to this show, be sure to visit this explanatory post on Robert's blog. It includes the code samples and syntax techniques that he talks about in this interview. Reading the code while listening will help you enjoy this particular show that much more.

Additional Production Note: Check out this post on Sound Quality at Carl Franklin's blog for short before and after samples of Robert's audio track and an explanation of one of the many ways that Carl and his team at Pwop makes the sound quality of this podcast so nice.

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Links from the Show

Examples - Robert Pickering's Blog Post on the F# Show on Hanselminutes (rr0)
F# - Microsoft Research (rr2)
Robert Pickering's F# Blog (rr4)
Book: Foundations of F# - Robert Pickering (rr1)
Robert Pickering's F# Resources (rr3)
MSDN Video on F# (rr5)

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Check out their UI Suite of controls for ASP.NET. It's very hardcore stuff. One of the things I appreciate about Telerik is their commitment to completeness. For example, they have a page about their Right-to-Left support while some vendors have zero support, or don't bother testing. They also are committed to XHTML compliance and publish their roadmap. It's nice when your controls vendor is very transparent.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Changes in the .NET BCL between 2.0 and 3.5

August 10, '07 Comments [8] Posted in Learning .NET | Programming
Sponsored By

(Actually between the BCL Version 2.0.50727.42 and 2.0 (Version 2.0.50727.1378)

API Changes from org2.0 to 2.0 - Windows Internet ExplorerI was thinking that while folks are blogging about all the new stuff in .NET 3.5 and VS2008 (or VS3.508 as I think to think of it) there must be other fixes here and there in the Base Class Library itself.

I googled around and couldn't find a list of what's changed in the BCL. I'm sure it's out there somewhere and I've missed it and the second I post this someone will post a better list in the comments, but anyway...

First, I look in C:\windows\assembly with Explorer. Remember that this is a "lie" - what you're seeing is a namespace extension's representation of the Global Assembly Cache, although a very useful one. Here's the new 3.5 stuff, sorting by version. This stuff is near all new. New assemblies, etc.

assembly

Nothing in here appears to have "rev'ed" like moving from 2.0 to 3.5 and kept the old version. One might expect to see System.Web 2.0 and then System.Web 3.5, but that's not the case from what I can see.

There is, however, a large amount of new (what I would call) BCL stuff in the new System.Core assembly. Remember that namespaces can exist across assemblies, so releasing a new assembly is a pretty decent way to get sweeping additive changes across a few dozen namespaces in a very compatible way.

Reflector says that System.Core includes new things in System.Threading, System.IO, System.Security, System.Diagnostics, and more. I would encourage you (as I do everyone who will listen) to download Reflector and do this:

  • Run Reflector
  • Hit the Home key on your keyboard
  • Hold down Delete until Reflector's window is clear
  • Press Ctrl-L, then Enter

...and you'll get this dialog. Reflector is smart enough to prompt you to fill up your empty assembly list, and the defaults are so useful that I usually just delete everything and pick one of these.

Start Default Assembly List

As you move around in Reflector, notice the "Location:" arrea at the bottom that tells you where the assembly is (although there are copies in the GAC).

image

Look at all the assemblies in the .NET 3.5 list and you'll see which ones live in the 2.0 directory, the 3.0 directory and the 3.5 directory.

While 3.5 is huge conceptually, on disk it's very small, consisting of the new compilers and basically these three assemblies:

  • System.Core
  • System.Data.Linq
  • System.Xml.Linq

There are other assemblies for MSBUILD improvements and such, but it's still very compact, from a "redistributable" point of view.

I would personally recommend that anyone who hasn't moved their 1.1 shop over to 2005, or who is starting out with .NET to just start with 2008/3.5. The multi-targeting stuff is very slick (I'll do a dissection soon, more detailed that ScottGu's post)

Has Anything Changed?

I wanted to find out what's changed between a standard Windows XP SP2 machine - totally fresh - with just the 2.0 runtime distributable installed, and my Vista machine with 3.5 on it.

There's a really great, but largely unknown, tool called Libcheck that you can download for free, that'll compare two versions of an assembly and show you the differences in a report. It'll look only at the public (inter)face of the assembly. In this case, that's exactly what I want.

It doesn't look to have been changed since 2005, so first I need to download and compiled it and hope it works. Fortunately it comes with source code and rather than spending time converting it to 2008, I just run the included nmake.bat that builds the three supporting libraries it needs and spits out libcheck.exe. Nice and easy (and lazy). There's a couple of obsolete warnings, but they're obsolete, not dead.

First, I brought up my 2.0 XP SP2 VM (again, fresh) and ran the .NET 2.0 Redistributable Package on it. This would be version 2.0.50727.42.

I went to the Libcheck folder and ran this command:

libcheck -store all org2.0

...and libcheck created a database of all the schmutz in 2.0.

Then I ran the same thing on my Vista machine with 3.5 - remembering that it's just going to look at the 2.0 Framework stuff on my system. This version of 2.0 was 2.0.50727.1378.

libcheck -store all 2.0

Notice that one was "org2.0" and the other '"2.0." I then copied all the org2.0 folder off my VM and onto my main machine, then ran:

libcheck -compare org2.0 2.0

The Report appeared in a folder called org2.0to2.0. Then I copied the report up to my blog, and it's available here.

Note: You can modify the text files in /RefFiles and use LibCheck on your own framework internal to your company. That's what we did at Corillian. There is apparently a much better version of this tool (this one is 3 years old) internal to Microsoft. I'll see what I can do to free it.

The percentage of churn was in the single digit percentages. Personally I find the report a fascinating read. You can see what was breaking, what was just added. You can see where new enums appeared and where overrides became virtuals and all sorts of things. Check it out, it's not that scary.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.