Scott Hanselman

Hanselminutes Podcast 114 - Website Scaling War Stories with Richard Campbell

May 27, 2008 Comment on this post [12] Posted in Podcast
Sponsored By

richard_headshot_web My one-hundred-and-fourteenth podcast is up. In this slightly unusual episode, I sit down with my good friend Richard Campbell and we share stories about scaling large websites over the years. I thought this was a really good show, if a little long and I'm thinking to have Richard on as a regular thing, if he's interested.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

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

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Vista 64-bit Blue Screens with INTERNAL_POWER_ERROR Immediately After Installing VMWare Player

May 21, 2008 Comment on this post [29] Posted in Bugs | Musings
Sponsored By

I hope this helps someone because it totally freaked me out this evening. I rebooted this evening, the first reboot since March, in fact, and blue-screened (BSOD) upon startup. At this point I was in a blue screen "loop" with the ominous message "INTERNAL_POWER_ERROR" on the blue screen. I started cussing Vista out and panicking, but this machine has been exceedingly stable since I built it last year and I reboot only every few months. I built it to be stable and I trust the machine.

Working backwards, the last and only interesting thing I installed was VMWare Player for Windows. I had some trepidation at the time of the install because I am not a fan of the way that VMWare adds virtual network devices that are listed in Network Connections, but it came highly recommended from respected power users I know and I needed it to install a prepared Suse VM from the Mono folks.

However, when it's installed my 64-bit machine blue screens, and it's very difficult to get uninstalled, actually. Needless to say this scared the crap out of me.

I looked all over and checked out the VMWare Forums and no one at VMWare has acknowleded the problem in a Googl-eable way. I can tell you this, however. I am using a Quad-proc machine with an MSI motherboard with the latest BIOs and a buttload of USB devices. The only way I could get the system to boot up was to remove ALL the USB devices. ALL of them, to be clear, save one wired USB Keyboard that I used to log in and remove VMWare.

My guts says that this is a bug in the VMWare USB bridging code (the stuff in VMWare that lets you use USB devices inside a VM) or it's somewhere in the USB drivers in Windows. I have the Crash Dumps if you work for VMWare and you're interested. I'll WinDBG them later this week.

I hope this post helps someone having this same issue.

UPDATE: Installed Windows Debugging Tools (WinDbg.exe) and analyzed the crash dump and it's the VMWare Keyboard Driver, of all things. Perhaps VMWare doesn't like my Wireless USB Keyboard? Mental note, relearn WinDbg'ing.

BugCheck A0, {101, 7, fffffa6001dc8b10, 0} 

*** ERROR: Module load completed but symbols could not be loaded for VMkbd.sys
Page 9bda8 not present in the dump file. Type ".hh dbgerr004" for details
Probably caused by : VMkbd.sys ( VMkbd+15da )

Followup: MachineOwner
---------

1: kd> !analyze -v
*******************************************************************************
*                        Bugcheck Analysis                                    *
*******************************************************************************

INTERNAL_POWER_ERROR (a0)
The power policy manager experienced a fatal error.
Arguments:
Arg1: 0000000000000101, Unhandled exception occured while processing a system power event.
Arg2: 0000000000000007
Arg3: fffffa6001dc8b10, ExceptionPointer.  To debug this, in the debugger type:
    'dt nt!_EXCEPTION_POINTERS <argument>'.  Then type:
    '.cxr <value of context record from the previous command>'.
    All subsequent debugger commands will show you the actual
    source of the error.  Start with a stack trace by typing 'kb'.
Arg4: 0000000000000000

Debugging Details:
------------------
Page 9bda8 not present in the dump file. Type ".hh dbgerr004" for details
BUGCHECK_STR:  0xA0
DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT
PROCESS_NAME:  System
CURRENT_IRQL:  0
EXCEPTION_RECORD:  fffffa6001dc99a8 -- (.exr 0xfffffa6001dc99a8)
ExceptionAddress: fffff80002477af1 (nt!IofCallDriver+0x0000000000000051)
   ExceptionCode: c0000005 (Access violation)
   ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000000
   Parameter[1]: 00000000000000e0
Attempt to read from address 00000000000000e0
---------

Weird.

Technorati Tags: ,,

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

The Weekly Source Code 27 - Suck Less Libraries

May 21, 2008 Comment on this post [10] Posted in Programming | Source Code
Sponsored By
I've been getting more and more interested in how folks extend their applications using plugins and things. In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you twenty-sixth (half a year!) in a infinite number of posts of "The Weekly Source Code."

Now that I've been working with the .NET Base Class Library (BCL) for just about six years, I've got a pretty good sense of the classes I like, the ones that work well, and the ones that don't "feel" right. I'm learning LINQ and the various extension methods that can make code feel more elegant. I've got ideas on how I might fix/patch/improve the framework, but really, who has the time? Well apparently these guys. This week's Weekly Source Code is dedicated to the people who create libraries with the goal of making other libraries suck less.

Umbrella

The folks at http://www.nventive.net/ have created a project called Umbrella that is a series of helpers over the .NET BCL that aims to "reduce friction and increase predictability of the API." They plan to launch additional accelerators over Unity, the Entity Framework, WCF and the Enterprise Library.

It is exceedingly broad and includes literally hundreds of new methods and helpers. However, I don't think you're expected to "learn" Umbrella as they hope you'll stumble into it...in a good way. It's like the concept of The Pit of Success. There's little easier than just falling, and the idea is that if you've designed an API correctly folks will just fall into success. 

Do check out the project, it's really fun reading. Here's some cool examples:

Here's a few extensions to ICollection.

namespace nVentive.Umbrella.Extensions
{
public static class CollectionExtensions
{
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
items.ForEach(collection.Add);
}

public static void Remove<T>(this ICollection<T> collection, Func<T, bool> predicate)
{
collection.Where(predicate).ToArray().ForEach(item => collection.Remove(item));
}

public static ICollection<U> Adapt<T, U>(this ICollection<T> collection)
{
return Adapt<T, U>(collection, Funcs<U, T>.Convert, Funcs<T, U>.Convert);
}

public static ICollection<U> Adapt<T, U>(this ICollection<T> collection, Func<U, T> from, Func<T, U> to)
{
return new CollectionAdapter<T, U>(collection, from, to);
}

public static void ReplaceWith<T>(this ICollection<T> collection, IEnumerable<T> items)
{
collection.Clear();
AddRange<T>(collection, items);
}

public static IDisposable Subscribe<T>(this ICollection<T> collection, T item)
{
collection.Add(item);

return Actions.Create(() => collection.Remove(item)).ToDisposable();
}

public static void AddDistinct<T>(this ICollection<T> collection, T item)
{
AddDistinct<T>(collection, item, Predicates<T>.Equal);
}

public static void AddDistinct<T>(this ICollection<T> collection, T item, IEqualityComparer<T> comparer)
{
AddDistinct<T>(collection, item, comparer.Equals);
}

public static void AddDistinct<T>(this ICollection<T> collection, T item, Func<T, T, bool> predicate)
{
if (collection.None(collectionItem => predicate(collectionItem, item)))
{
collection.Add(item);
}
}
}
}

Ones like AddRange() are simple enough to make you wonder why there weren't there before, but ones like Remove() that includes a predicate indicating which items to remove are clever and clean, as in this example that removes numbers that are evenly divisible by two.

[Fact]
public void Remove()
{
collection.AddRange(new int[] { 1, 2, 3, 4 });

collection.Remove(item => item % 2 == 0);

Assert.Equal(2, collection.Count);
Assert.Equal(1, collection.ElementAt(0));
Assert.Equal(3, collection.ElementAt(1));
}

Another fun example is their ReflectionExtensions that make Reflection a little cleaner. Here's a test:

[Fact]
public void Instance()
{
Foo foo = new Foo();

IReflectionExtensionPoint fooReflection = foo.Reflection();

Assert.Equal(foo.I, fooReflection.Get("i"));

fooReflection.Set("i", 2);

Assert.Equal(2, foo.I);

Assert.Equal(2, fooReflection.Get("I"));

fooReflection.Set("I", 3);

Assert.Equal(3, foo.I);

Assert.Equal(3, fooReflection.Get("GetI"));

fooReflection.Set("SetI", 4);

Assert.Equal(4, foo.I);
}

Again, this just scratches the surface of Umbrella. It's huge.

Ukadc.Diagnostics

Even the team knows it as they say "Great logging, terrible name."  The Ukadc.Diagnostics library, also hosted on Codeplex, is a library of extensions to System.Diagnostics. Why? From Josh Twist:

Colleagues from Microsoft's UK Application Development Consulting (UKADC) team. The project was born out of a conversation with Morgan Skinner when I mentioned that I tended to use log4net, nlog or Enterprise Library logging over the stuff that ships out of the box (OOB) with .NET 2+.

I am the same way as I was a log4net guy for years. Check out their Reference Example or the Complete Source. The reference shows the smtpTraceListener and the sqlTraceListener. It includes a nice example of how to use the Trace.CorrelationManager to do context tracing through an entire HTTP request lifecycle.

The library includes a better base class for TraceListener, CustomTracelistener, that makes creating your own trace listeners easy with just two methods to override. I encourage you to check it out.

However, the gem I found while reading the source wasn't actually directly related to the library's purpose. Rather, it's the implementation of a Fast Property Getter. What's that you say? Well, sometimes when you're using Reflection to get properties from an object, you'll realize that asking for, then using the PropertyInfo object directly can be slow. Most folks will at least cache the PropertyInfo, which will save you from the initial hit but you'll still pay a little when using it to access the object's value.

This DynamicPropertyReader takes a CLR type as a string and a property name as a string. Rather than using Reflection each time, which would be slower, it uses this FastPropertyGetter. We did this at Corillian (my last job) in a number of places where we wanted the flexibility of Reflection but near-native speeds.

public DynamicPropertyReader(string sourceType, string propertyName)
{
if (string.IsNullOrEmpty(sourceType))
throw new ArgumentNullException("sourceType");
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException("propertyName");

// Attmpt to get the type, and throw a TypeLoadException if not found
Type type = Type.GetType(sourceType, true);

_fastPropertyGetter = new FastPropertyGetter(propertyName, type);

if (_fastPropertyGetter.PropertyType == typeof (string))
{
_comparator = StringComparator.Instance;
}
else if (typeof (IConvertible).IsAssignableFrom(_fastPropertyGetter.PropertyType) &&
typeof (IComparable).IsAssignableFrom(_fastPropertyGetter.PropertyType))
{
_comparator = NumericComparator.Instance;
}
else
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
Resources.DoesNotImplementRightInterfaces,
propertyName, sourceType));
}
}

What does it do? It's long, but clever. I think it could actually be tightened up a bit, but basically it generates a method at runtime that is tailored to retrieve a property from an object. That getter is then cached and called to retrieve the property. One of these DynamicMethods is generated per property. Remember that DynamicMethod is one of the magical things that enables IronPython and the DLR. I heard that this kind of technique could be WAY cleaner using the DLR in the near future. Perhaps Harry can expand on that. There's a good article on CodeProject about this kind of specialized code generation for speeding up reflection.

public class FastPropertyGetter
{
private delegate PropertyResult GetData(object data);

private GetData GDDelegate;

public Type PropertyType { get; private set; }

public FastPropertyGetter(string propertyName, Type type)
{
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException("propertyName");
if (null == type)
throw new ArgumentNullException("type");

PropertyInfo propertyInfo = type.GetProperty(propertyName);

if (propertyInfo == null || !propertyInfo.CanRead)
throw new ArgumentException(
string.Format(CultureInfo.CurrentCulture, Resources.NoReadableProperty, propertyName, type));

MethodInfo methodInfo = propertyInfo.GetGetMethod();
PropertyType = methodInfo.ReturnType;

DynamicMethod dm = new DynamicMethod("FastGetProperty",
typeof (PropertyResult),
new Type[] {typeof (object)}, typeof (FastPropertyGetter));

ILGenerator il = dm.GetILGenerator();

il.DeclareLocal(typeof (PropertyResult));
LocalBuilder lb = il.DeclareLocal(type);

il.Emit(OpCodes.Newobj, typeof (PropertyResult).GetConstructor(new Type[0] {}));
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Isinst, type);

// branch if IS an instance of type
Label isInstance = il.DefineLabel();
il.Emit(OpCodes.Brtrue_S, isInstance);

{
// load the GetterResult
il.Emit(OpCodes.Ldloc_0);

// Create a 'false' bool
il.Emit(OpCodes.Ldc_I4_0);

// Set result code to GetterResultCode.ObjectNotExpectedType
il.Emit(OpCodes.Callvirt, typeof (PropertyResult).GetProperty("ObjectMatched").GetSetMethod());

// reload the GetterResult and return it
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
}

// isInstance:
// object IS expected instance
il.MarkLabel(isInstance);

{
// load the GetterResult
il.Emit(OpCodes.Ldloc_0);

// load the passed object
il.Emit(OpCodes.Ldarg_0);

if (type.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, type);
il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Ldloca_S, lb.LocalIndex);
}

if (methodInfo.IsFinal)
{
// Call the property get method
il.Emit(OpCodes.Call, methodInfo);
}
else
{
// Call the property get method
il.Emit(OpCodes.Callvirt, methodInfo);
}

// box if necessary
if (methodInfo.ReturnType.IsValueType)
{
il.Emit(OpCodes.Box, methodInfo.ReturnType);
}

// Set data to result of query
il.Emit(OpCodes.Callvirt, typeof (PropertyResult).GetProperty("Data").GetSetMethod());

// reload the GetterResult and return it
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
}
GDDelegate = (GetData) dm.CreateDelegate(typeof (GetData), null);
}

public PropertyResult GetValue(object data)
{
return GDDelegate(data);
}
}

IIS7 Hostable Web Core

CarlosAg has written a nice wrapper around IIS7's core hwebcore.dll library that lets you host your own IIS7 instance INSIDE your process. This isn't HttpListener, nor is it out-of-process. This is IIS7, running in your process. This is a really powerful thing that is as simple as:

internal class Program { 
private static void Main(string[] args) {
int port = 54321;
int siteId = 1;

WebServer server = new WebServer(@"d:\Site", port, siteId);
server.Start();
Console.WriteLine("Server Started!... Press Enter to Shutdown");

Console.ReadLine();

Console.WriteLine("Shutting down");
server.Stop();
}
}

This is a nice alternative to HttpListener and it's more powerful than Visual Web Developer/Cassini. Carlos also muses about this possibility:

"Another scenario might include something like a "Demo/Trial CD" where you can package your application in a CD/DVD that users then can insert in their machine and suddenly get a running/live demo of your Web Application without requiring them to install anything or define new applications in their real Web Server."

It's also very very simple:

namespace HWCServer {
internal class WebServer : IDisposable {

private string _appHostConfigPath;
private string _rootWebConfigPath;

public WebServer(string physicalPath, int port, int siteId) {
string appPoolName = "AppPool" + port.ToString();
_appHostConfigPath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".config");
_rootWebConfigPath = Environment.ExpandEnvironmentVariables(@"%windir%\Microsoft.Net\Framework\v2.0.50727\config\web.config");

string appHostContent = Resources.AppHostAspNet;
//string appHostContent = Resources.AppHostStaticFiles;

File.WriteAllText(_appHostConfigPath,
String.Format(appHostContent,
port,
physicalPath,
@"%windir%\Microsoft.NET\Framework\v2.0.50727",
siteId,
appPoolName));
}

~WebServer() {
Dispose(false);
}

public void Dispose() {
Dispose(true);
}

private void Dispose(bool disposing) {
if (disposing) {
GC.SuppressFinalize(this);
}

Stop();
}

public void Start() {
if (!HostableWebCore.IsActivated) {
HostableWebCore.Activate(_appHostConfigPath, _rootWebConfigPath, Guid.NewGuid().ToString());
}
}

public void Stop() {
if (HostableWebCore.IsActivated) {
HostableWebCore.Shutdown(false);
}
}

#region Hostable WebCore
internal static class HostableWebCore {

private static bool _isActivated;


private delegate int FnWebCoreActivate([In, MarshalAs(UnmanagedType.LPWStr)]string appHostConfig, [In, MarshalAs(UnmanagedType.LPWStr)]string rootWebConfig, [In, MarshalAs(UnmanagedType.LPWStr)]string instanceName);
private delegate int FnWebCoreShutdown(bool immediate);

private static FnWebCoreActivate WebCoreActivate;
private static FnWebCoreShutdown WebCoreShutdown;

static HostableWebCore() {
// Load the library and get the function pointers for the WebCore entry points
const string HWCPath = @"%windir%\system32\inetsrv\hwebcore.dll";
IntPtr hwc = NativeMethods.LoadLibrary(Environment.ExpandEnvironmentVariables(HWCPath));

IntPtr procaddr = NativeMethods.GetProcAddress(hwc, "WebCoreActivate");
WebCoreActivate = (FnWebCoreActivate)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(FnWebCoreActivate));

procaddr = NativeMethods.GetProcAddress(hwc, "WebCoreShutdown");
WebCoreShutdown = (FnWebCoreShutdown)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(FnWebCoreShutdown));
}

public static bool IsActivated {
get {
return _isActivated;
}
}

public static void Activate(string appHostConfig, string rootWebConfig, string instanceName) {
int result = WebCoreActivate(appHostConfig, rootWebConfig, instanceName);
if (result != 0) {
Marshal.ThrowExceptionForHR(result);
}

_isActivated = true;
}

public static void Shutdown(bool immediate) {
if (_isActivated) {
WebCoreShutdown(immediate);
_isActivated = false;
}
}

private static class NativeMethods {
[DllImport("kernel32.dll")]
internal static extern IntPtr LoadLibrary(String dllname);

[DllImport("kernel32.dll")]
internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);
}
}
}
}

What a clean wrapper class! Have fun, and keep reading source to be a better coder!

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Hanselminutes Podcast Catchup

May 20, 2008 Comment on this post [13] Posted in Podcast
Sponsored By

image I usually like to announce each Hanselminutes Podcast here on my blog, as well as over at the Hanselminutes site (have you seen the show archives?), but at some point over the last few months I've gotten slow, lagging by a day or more, and now I'm officially 3 shows behind!

Here's the rollup of what's been published since I announced Show 110 on Spec#, because these are three pretty good shows, and they are representative of the kind of info I'm trying to get out there.

  • Show 111 - ASP.NET Model View Controller, MVCContrib and MonoRail - Scott sits down with Phil Haack, ASP.NET Microsoft PM, Dru Sellers, Contributor to the Castle Project, and Jeffrey Palermo, of the MVCContrib project and talks about the ASP.NET MVC Project and Microsoft's changing attitudes towards Open Source.
  • Show 112 - The Past, Present and Future of .NET Unit Testing Frameworks - Scott gets a rare chance to sit down in person with developers from three .NET Unit Testing Frameworks. Charlie Poole from NUnit, Jeff Brown from MbUnit, Brad Wilson from xUnit.NET as well as Roy Osherove, the author of the upcoming "Art of Unit Testing."
  • Show 113 - Beyond Continuous Integration: Continuous Monitoring with Owen Rogers - Scott sits down with Owen Rogers, one of the original authors of CruiseControl.NET, and hears about his ideas around a hardware and software platform that extends Continuous Integration with Continuous Monitoring.

Let me take a few sentences here and sell you on the show. It's a shortish (usually under 40 min, often even less) commute-time podcast. I do my very best to not waste your time. They are usually more technical than DotNetRocks and while I do cover a lot of Microsoft stuff, I try to mix it up with a show on Digital Photography, Distributed Source Control, Eclipse, An Interview with Martin Fowler and DHH, and building the Ultimate PC with Jeff Atwood.

If you'd like the feed for the COMPLETE MP3 Archive it's here. We're also on Zune and iTunes. If you'd like a nice, simple podcast downloader that just gets the files and puts them in a folder with no muss nor fuss, I recommend the FREE FeedStation.

I hope you continue to enjoy the show and perhaps subscribe. If you have cool ideas for topics, email them to me or follow me on Twitter!

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

11 Top Tips for a Successful Technical Presentation

May 17, 2008 Comment on this post [42] Posted in Speaking
Sponsored By

image Over five years ago I posted Tips for a Successful MSFT Presentation. Yesterday I watched the video of my Mix Presentation all the way through. It's always very painful to hear one's own voice but it's even worse to watch yourself. I never listen to my podcast and I avoid watching myself. It's like watching a person in parallel universe and it inspires self-loathing. However, if you are someone who values continuous improvement - and I am - you need to do the uncomfortable.

Here's my five-years-later Updated Tips for a Successful Technical Presentation.

1. Have a Reset Strategy (One-Click)

If you're going to give a talk, you'll probably have to give it more than once. If you have demonstrations of any kind, have a "one-click" way to reset them. This might be a batch file or Powershell script that drops a modified database and reattaches a fresh one, or copies template files over ones you modify during your demo.

Personally, I'm sold on Virtual Machines. I have seven VMs on a small, fast portable USB drive that will let me do roughly 12 different presentations at the drop of a hat. You never know when you'll be called upon to give a demo. With a Virtual Machine I can turn on "Undo Disks" after I've prepared the talk, and my reset strategy is to just turn off the VM and select "Delete Changes." A little up-front preparation means one less thing for you to panic about the day of the talk.

2. Know Your Affectations (Ssssssseriously)

I have a bit of a lisp, it seems. I also hold my shoulders a little higher than is natural which causes my neck to tighten up. I also pick a different word, without realizing it, and overuse it in every talk. This is similar to how Microsoft Employees overuse the word "so" (which is actually Northwestern Americans, not MSFTies) too much.

It's important to know YOUR affectations so you can change them. They may be weakening your talk. Don't try to remember them all, though. Just pick two or three and focus on replacing them with something less detracting. Don't overanalyze or beat yourself up, though. I've spoken hundreds of times over the last 15 years and I'm always taking two-steps forward and one step back. The point is to try, not to succeed absolutely.

3. Know When To Move and When To Not Move (Red light!)

One of the most powerful tips I ever received was this: "When you move, they look at you. When you stop, they look at the screen." Use this to your advantage. Don't pace randomly, idley or unconsciously. Don't rock back and forth on your heels. Also, empty your pockets if you tend to fiddle with lose change or your keys.

4. For the Love of All That Is Holy, FONT SIZE, People (See that?)

It just tears me up. It physically makes me ill. To give a presentation and utter the words "um, you probably won't be able to see this" does everyone in the room a disservice.  Do NOT use the moment of the presentation as your time to do the font resizing.

Lucida Console, 14 to 18pt, Bold.  Consider this my gift to you.  This is the most readable, mono-spaced font out there.  Courier of any flavor or Arial (or any other proportionally spaced font) is NOT appropriate for code demonstrations, period, full stop.  Prepare your machine AHEAD OF TIME.  Nothing disrespects an audience like making them wait while you ask "Can you see this 8 point font? No? Oh, let me change it while you wait."  Setup every program you could possibly use, including all Command Prompt shortcuts, before you begin your presentation.  That includes VS.NET, Notepad, XMLSpy, and any others, including any small utilities.

I've found that the most readable setup for Command Prompts is a Black Background and with the Foreground Text set to Kermit Green (ala "Green Screen."  Yes, I was suspicious and disbelieving also, but believe it or not, it really works.)  I set Command Prompts to Lucida Console, 14 to 18pt, Bold as well, with much success.

Also, set the font size to LARGEST in Internet Explorer and remember that there are accessibility features in IE that allow you to include your own Large Font CSS file for those web pages that force a small font via CSS.

Learn how to use ZoomIt and practice before-hand. It can be an incredibly powerful tool for calling out sections of the screen and making it so even the folks way in the back can see what's going on.

For simplicities' sake, I like to keep a separate user around call "BigFonty" (choose your own name).  He's an Administrator on the local machine and he exists ONLY for the purposes of demonstrations.  All the fonts are large for all programs, large icons, great colors, etc.  It's the easiest way to set all these settings once and always have them easily available.

5. Speak their Language (Know the Audience)

When I was in Malaysia for TechEd, I spent 3 full days exclusively with locals before the talk, I learned snippets of each of the languages, tried to understand their jokes and get an idea about what was important to people in Malaysia.  American analogies, much humor, and certain "U.S. specific" English colloquialisms just didn't make any sense to them.  When it came time to give the presentations, I better understood the Malaysian sense of timing, of tone and timbre, and I began each of my presentations by speaking in Bahasa Malaysia.  I changed aspects of my slides to remove inappropriate content and add specific details that would be important to them.

I've used this same technique in a half-dozen countries with success. While this is an extreme example, the parallels with any audience are clear.  If you're speaking to a room full of IT guys who work in the Automotive field, or the Banking industry, the fact that we are all programmers only gives you a small degree of shared experience.  Remember no matter the technical topic, try to get into the mind of the audience and ask yourself, why are they here and what can I tell them that will not be a waste of their time.  What would YOU want to hear (and HOW would you like to hear it) if you were sitting there?

6. Be Utterly Prepared (No excuses)

Short of an unexpected BSOD (and even then, be ready) you should be prepared for ANYTHING.  You should know EVERY inch of your demos and EXACTLY what can go wrong.  Nothing kills your credibility more than an error that you DON'T understand.  Errors and screw-ups happen ALL the time in Presentations.  They can even INCREASE your credibility if you recover gracefully and EXPLAIN what happened.  "Ah, this is a common mistake that I've made, and here's what you should watch for."  Be prepared with phrases that will turn the unfortunate incident around and provide them useful information.

7. CONTENT, CONTENT, CONTENT (Have some)

Every move, phrase, mistake, anecdote and slide should actually contain content.  It should be meaningful.  Your mistakes should teach them, your demos should teach them; even your shortcut keys, utilities and menu layout should teach them.  A presentation isn't an opportunity to read your slides.  I'll say that again. Don't READ your slides. I can read faster than you can talk.

Remember that most people can read silently to themselves 5 to 10 times faster that you can read to them out loud.  Your job as a presenter is to read in between the lines, and provide them structure.  Your slides should be treated as your outline – they are structure, scaffolding, nothing more.  If you jam your slides full of details and dozens of bullets, you might as well take your content and write an article.  It's difficult to listen to someone talk and read their slides at the same time – remember that when you design your content. YOU are the content, and your slides are your Table of Contents.

8. System Setup (Be unique, but don't be nuts)

When you a presenting, remember that you are looked upon as an authority.  Basically, you are innocent until proven guilty.  It's great to have a personality and to be unique, but don't let your personal choice of editors or crazy color scheme obscure the good information you're presenting.  I appreciate that you may like to use VI or emacs to view text files, but let's just say that sometimes Notepad has a calming effect on the audience. 

I give Microsoft talks, usually, so I tend towards Visual Studio, but 99% of my talks use a limited number of tools. Basically Visual Studio, Notepad, the Command Prompt and a Browser.

Remember that while you may prefer things a certain way while your face is a foot away from the screen, it's very likely the wrong setup when 500 people are more than 100 feet away.

I really like to get Toolbars and things out of the way. I use F11 (Fullscreen) in the Browser a lot, as well as Visual Studio's Shift-Alt-Enter shortcut to FullScreen. Turn off unneeded flair and toolbars. Also, turn on line-numbering so you can refer to lines if you're presenting code.

9. Speaking (Um…)

"Volume and Diction," my High School Drama teacher said to me.  Speak clearly, authoritatively, project your voice to the back of the room.  The best speakers don't even need microphones.  If you have a speaking affectation (I had a lisp growing up) or you tend to say, um, etc, or find yourself overusing a specific phrase ("a priori", "fantastic", "powerful", etc) take it upon yourself to NOTICE this mannerism and avoid it.

Practice multi-tasking.  It seems silly to say, but although we can all multitask to a certain degree, when we hit a real snag in a presentation, many of us tend to freeze.  Silence is deadly.  Remember, since all eyes are on you, complete silence and apparent introspection says "I don't know know what I'm doing."  When you need to get to a particular file, don't make the audience wait for you while you putter through explorer.  Have shortcuts ready (and explain when you use them).  Move fast and efficiently, but annotate your actions.  You should continue to "color-commentate" your actions like a sports announcer.  Don't allow "dead-air," unless it's silence for effect.

10. Advancing Slides (No lasers!)

I always used to hate slide-advancers, you know, those little remotes with forward and backward buttons. Then I tried one and I'm hooked. I use the Microsoft Presenter Mouse 8000 and totally recommend it. It isn't just a great Bluetooth mouse, but flip it over and it's a great Powerpoint slide advancer. 

Take a look at Al Gore's excellent presentation in "An Inconvenient Truth." It's seamless and flows. Now imagine him running over to his laptop to hit the spacebar each time he wanted to advance a slide. My presentations have gotten better as I've started incorporating this technique.

11. Care (deeply)

I really avoid presenting on topics that I don't care about. I avoid it like the Plague and I encourage you to do so as well. There's nothing more important that truly caring about your topic. If you care, it'll show. If you eschew all the other tips, at the very least care.


What are YOUR tips, Dear Reader? What tips, mantras or preparations have you used to make your presentations that much better?

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

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