Scott Hanselman

DIY: Making a Very Wide Angle Webcam on the Cheap

February 17, '10 Comments [23] Posted in Remote Work | Reviews
Sponsored By

imageAfter I made my Webcam Cart and blogged about it a package I'd forgotten about arrived. It was a cheap "Zeikos ZE-WA37S 37mm 0.45X Wide Angle Lens." Only $10. I've looked all over for wide-angle webcams and they just don't exist. Over the counter webcams have a very narrow field of view.

I started with my favorite webcam, an amazing value, the Lifecam Cinema HD. I've got 4 of these. Now, the wide angle lens has a large opening, about an inch and a half, while the Lifecam is maybe an inch in diameter. I needed something to build up the diameter in such a way that it'd hold the wide angle lens in position while avoiding ruining the camera itself.

How? Electrical tape. Lots of it. I wrapped it around and around until it could offer enough outward tension to keep the lens on tightly.

Zeikos ZE-WA37S 37mm 0.45X Wide Angle Lens Lifecam with Wide Angle Zeikos Lens

Here's a still shot taken with the Lifecam Cinema HD with the lens it came with.

Lifecam HD Sample Photo

Here's a still shot taken with the same Lifecam Cinema HD with the cheap Zeikos Wide-Angle lens attached. Note the blurriness in the periphery and the slight fish-eye warping in the shelves.

Lifecam HD with Zeikos Wide-Angle Lens attached

The Lifecam is ideal for this kind of hack because it has a built in AutoFocus that REALLY works hard to keep things focused. I'll be using this for meetings and "getting a sense of the room" since I can't afford a $3000 "Roundtable" camera. I haven't measured it, but I fell I'm getting at least 100 degrees or more of field of view (my gut) so I think it's a good tradeoff of visual acuity for seeing a LOT more of the room for only $10.


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

Building an Embodied Social Proxy or Crazy Webcam Remote Cart Thing

February 17, '10 Comments [22] Posted in Coding4Fun | IIS | Microsoft | Remote Work
Sponsored By

Channel 9 Video on Embodied Social Proxies As a remote worker I'm always looking to find better ways to work with the team that don't involve actually going to Seattle. As much as I love/hate Microsoft, I'm not moving. However, this always puts me at a disadvantage. There's only so many places (and only so far) i can go as a remote worker.

When Phil and I made the "HanselPortal," essentially a persistent always-on Skype Chat, that gave folks a place to drop by and chat (at least those two lazy to just call me via Office Communicator) but there's already two people in Phil's office, I can't move (I'm a desktop computer) and my field of view is very small. Phil has a small inside office and I can't exactly hold meetings. It's a start, but it's not perfect.

I stumbled upon the Embodied Social Proxies project at Microsoft Research and got a tour from their team. While their system costs about $3000 to $4000 (While I'd love an Axis 213 PTZ camera I can't afford the $1300 and I'm still trying to convince the boss.) and has a great cart, monitor and camera, I figured I could at least do a proof of concept on the cheap. And by proof of concept, I mean, in the same way my 1963 Ford Falcon was a proof of concept; I kept driving it until it stops, then started walking.

The Idea

While the name "Embodied Social Proxy" is very PHDy and very Researchy, the idea is that you want a physical stand-in for yourself. Sure, people can call me and contact me in any of a dozen ways and honestly, it's one click at Microsoft. I'm in the address list, I'm on chat, and I've even got a 5 digit phone extension. I've done all this and more to integrate with headquarters. However, out of sight, out of mind is really true. People subconsciously or not like to associate something physical with you. So, until I can get a 6 foot tall mobile video conferencing robot a $20 cart with a laptop super-glued to it might help. I'll set it up in an office in Building 5 so folks can "stop by." I can be "brought" to meetings where perhaps setting up a RoundTable isn't feasible. Maybe it'll work, perhaps not. But I'm going to continue to try.Network Diagram

The Problems

The researches have done many iterations and discovered many things. You want "eye gaze" to be natural so you can tell when folks are looking at you and they can tell when you're looking at them. They recognize that you need to "look around" and watch whiteboards, so being able to pan and zoom around is important.

Security is important also. We don't want a domain-logged-in real user on a mobile cart wandering around Microsoft. However, as a remote person I need to be able to start up the camera without having to ask a person to do it. I need to control as much of the cart as possible remotely.

The General Solution

I've got Office Communicator "corporate chat" on my side, so that makes things easier. If you wanted to generalize this solution you could use Skype or other things. I also have Exchange so my free/busy details are available programmatically. Again, this could be Google Calendar, or whatever.

I'll have a laptop mounted (not movable) to a cart. It'll include an HD Webcam at a fixed position (no zoom or pan) and a second IP camera that allows Pan/Tilt/Zoom (PTZ). This should let me look around a bit. This is an IP camera because there are no good pan/tilt/zoom USB cameras on the market. PTZ cameras can be $200 or up to $3000 and more. Mine's $200.

I need the laptop to have both wired and wireless. Here's where things get a little weird. The camera will have one IP and the laptop will have another. However, the laptop will have a security certificate that will allow it to get on the network while the camera will not only not be reliable, but it'll be hard to find from a DNS perspective. I would like to be able to access both the camera and the machine as a unit, reliably. I solve that below, in what I think is a pretty clever way.

The (Cheap) Hardware

The hardware for my build is beyond cheesy cheap.

The Software

There's a custom WPF-based .NET client written by the MS Research Team. I'm gonna continue to bug them to let me release the code or Open Source it or something. I don't think the software is the important part, it's the idea. The software is a little tricky and cobbled, but workable.

Talking to Office Communicator

The machine is running on a local account that isn't Administrator. It's set to log in automatically, but the account has access to nothing. There's another Non-User Domain Account called "hanselcart" but while this account is in the Active Directory, but also has no access to resources or anything. That account has had Office Communicator access turn on so I can chat with it. Communicator is set to start up automatically as well. It's that ability to chat (really "address") the cart that makes it reasonably seamless.

You'll see that if I'm not currently visible on the screen, the program makes a call to Exchange Web Services and uses the Office Communicator Presence information to show where I am and what I'm doing generally, as well as a way to call me.

Screenshot of the Social Proxy Software

There's an Office Communicator SDK so you can automate and listen to Communicator:

this.messenger = new Messenger();
this.messenger.OnSignin += new DMessengerEvents_OnSigninEventHandler(messenger_OnSignin);
this.messenger.OnContactStatusChange += new DMessengerEvents_OnContactStatusChangeEventHandler(messenger_OnContactStatusChange);
this.messenger.OnIMWindowCreated += new DMessengerEvents_OnIMWindowCreatedEventHandler(messenger_OnIMWindowCreated);
this.messenger.OnIMWindowDestroyed += new DMessengerEvents_OnIMWindowDestroyedEventHandler(messenger_OnIMWindowDestroyed);
this.messenger.OnMyStatusChange += new DMessengerEvents_OnMyStatusChangeEventHandler(messenger_OnMyStatusChange);

The code is very COM-ish, which is unfortunate, but it's easy enough to write to. If I chat "Start Video" to the cart, the program sees it and calls me back:

void StartVideo()
IMessengerAdvanced advanced = (IMessengerAdvanced) this.messenger;
object result = advanced.StartConversation(CONVERSATION_TYPE.CONVERSATION_TYPE_VIDEO,, null, null, "1", null);

// Float a "hang up" window on top
if(hangupWindow == null) {
hangupWindow = new HangupWindow(MachineName);
hangupWindow.Closed += new EventHandler(hangupWindow_Closed);
hangupWindow.Owner = this;

// put the hang up window top-right corner
hangupWindow.Top = 0;
hangupWindow.Left = System.Windows.SystemParameters.PrimaryScreenWidth - hangupWindow.Width;

// Set the video to full-screen

The FullScreen part is a horrific SendKeys hack to press F5 for me until I talk to the OC team and figure out how to do this programmatically.

How to Address the IP Camera - "It's a WebFarm of WebCams with IIS's AAR"

I'm rather proud of this hack. Let's say the cart is called http://hanselcart. I'd like to be able to address the WebCam reliably even though it's not technically a managed-object on the MS network. Essentially, if the cart itself is on and online, I'd like to use the cart to get to the camera.

Then I remember that IIS (Internet Information Services, our Web Server) has an insanely powerful free module you can download called Application Request Routing or ARR. Regardless of what you think of the name IIS ARR, it really takes IIS to the next level. Think about it next time you are trying to do something tricky with IIS. It adds a bunch of features, but I figured I needed a Reverse Proxy, which ARR can do.

Instead, I made my local IIS a WebFarm with one node, the WebCam. ;) I put the Webcam on a local network "behind" the laptop (192.168.x.x) and told my Laptop's instance of IIS to route all traffic to the Webcam. In fact, ARR smartly did it for me when i used the Add WebFarm Wizard. Whole thing took 5 minutes, counting download time.

A Web Farm of Web Cams

NOTE: I did also try a tool called WebcamXP, and while it's amazingly cool for other things and has some really diverse features around Webcams, especially IP webcams, it used about 30% CPU for what I wanted, while IIS's ARR used 1-2%.

So now, I can just hit the cart by name and I'll get the IP Webcam. This Webcam has its own HTTP server and includes a quasi-RESTful API for Pan/Tilt/Zoom so I can video chat via Office Communicator and look around with the web interface of the IP Cam.


Here's a few shots of the cart itself. I'll be driving it up to Seattle for testing and installation this week.

HanselCart Full Body Shot Close Up of IP Cam

Thanks to Gina and John and especially Peter Provost for helping me (virtually from Dallas) build it. Wish me luck!

Related Links 

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 200 - Jon Skeet!

February 16, '10 Comments [3] Posted in Podcast
Sponsored By

jonskeet My TWO-HUNDREDTH podcast is up. It's show 200, and we've got Jon Skeet. Jon writes Java at Google, but he's also got a new book out called C# in Depth, Second Edition. Jon is also well-known for his answers on StackOverflow, gaining him the title "The Chuck Norris of Programmers." Listeners can get 40% off with code "HanselC40" at until March 15th. Someone even made an Ask Jon Skeet search engine!

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Download: MP3 Full Show

Links from the Show

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.

I want to add a big thanks to Telerik. Without their support, there wouldn't be a Hanselminutes. I hope they, and you, know that. Someone's gotta pay the bandwidth. Thanks also to Carl Franklin for all his support over these last 4 years!

Telerik is our sponsor for this show.

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface and developer tools, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET AJAX,MVC,Silverlight, Windows Forms and WPF. Enjoy developer tools like .NET reporting, ORM, Automated Testing Tools, TFS, and Content Management Solution. And now you can increase your productivity with JustCode, Telerik’s new productivity tool for code analysis and refactoring. Visit

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

Back to Basics: C# 4 method overloading and dynamic types

February 12, '10 Comments [30] Posted in Back to Basics | Learning .NET | Programming | VS2010
Sponsored By

C# 3.0 introduced the implicit type "var". I've explained var as saying:

"I'm too lazy to tell you the type of this variable, so you figure it out, compiler."

However, it's more useful than just promoting terseness or laziness:

var i = 10; // implicitly typed
int i = 10; //explicitly typed

Although var is a great way to start arguments about coding standards at your work, there are times when it is required around anonymous types. Here's an example from MSDN:

/ Example: var is required because
// the select clause specifies an anonymous type
var custQuery = from cust in customers
where cust.City == "Phoenix"
select new { cust.Name, cust.Phone };

// var must be used because each item
// in the sequence is an anonymous type
foreach (var item in custQuery)
Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);

C# 4 (not 4.0, the marketing folks say it's .NET 4, etc.) adds the dynamic keyword. I've explained this saying:

"There's no way for you or I to know the type of this now, compiler, so let's hope that the runtime figures it out."

Here's how this looks from an Intellisense point of view. Here I'm hovering over the dynamic keyword:


And here is the tooltip after pressing "." after "calc."


Now, to the interesting question of the day. Christoff Turner asked this question, essentially:

"I noticed the following while doing some research within C# 4.0:"

using System;
namespace ConsoleApplication1
class Program
static void f(Int32 x) { }
static void f(dynamic x) {}
static void f(Int32 x, dynamic y) {}
static void f(dynamic x, Int32 y) {}
static void f(Int32 x, dynamic y, Int32 z) {}
static void f(dynamic x, Int32 y, dynamic z) {}
static void Main(string[] args)
f(10); // Works - obvious
f(10, 10); // Ambiguous - obvious
f(10, 10, 10); // Ambiguous - not so obvious - since it should be possible to resolve

"Looking at f(10,10,10), what is the reasoning behind this call being ambiguous?"

I stared it it a while longer, then realized what is happening, and called Mads Torgersen to confirm. Mads says this.

In short, the behavior is totally by design:

  • dynamic in method signatures doesn’t come into it: it behaves like System.Object does.
  • Given that, neither of the ternary signatures is better because each fits better than the other on some arguments (Int32 fits 10 better than object does)

The key point here, in bold, because it's significant is: having the type dynamic means “use my runtime type for binding”.

The problem in the context of method calls is that you can't use the runtime type of something until, um, runtime. ;) Binding with dynamic expressions (dynamic binding) happens at runtime.  In this case, we're compiling against method signatures that are known at compile type and we're compiling with a (mostly) static language, so there's no dynamic method dispatching happening that could select a different method overload at runtime.

The dynamic type is statically-typed as dynamic. The compile-time type is "dynamic" (but really it's object, hence the method overloading trouble.)

Another way to look at this is with Reflector. This C# code:

static void f(Int32 x, dynamic y, Int32 z) {}

is essentially this, from a method signature point of view:

static void f(int x, [Dynamic] object y, int z) {}
and if there was a method that returned dynamic, it'd look like this:
[return: Dynamic]
private static object GetCalculator() {}

So, given how dynamic works as a type, how the DLR works in the context of method dispatching, etc, you can see why things didn't work like Christoff thought they would.


Related Links

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

The Weekly Source Code 49 - SmallBasic is Fun, Simple, Powerful Programming for Kids and Adults

February 9, '10 Comments [20] Posted in Learning .NET | MSDN | Programming | Silverlight | Source Code
Sponsored By

While the boys are only 2 and 4, I'm always keeping an eye out on new ways to teach them programming. Certainly I hope they'll be more well-rounded and I and spend more time outside, but a even a basic background in programming and logic, I think, produces a more empowered individual.

Created by Vijaye Raji, Small Basic is a simple (only 15 keywords) but powerful environment for getting started programming. Great for kids and non-technical spouses, but powerful enough even for the professional game developer. In fact, Small Basic is probably the fastest and simplest way I've seen yet to produce and publish Silverlight-based games. Read on to see why.

Small Basic is part of MSDN DevLabs and just released version 0.8. It's the eighth installment, but I suspect they are too modest to call it 8.0. ;) It's even internationalized in English, Chinese, French, German, Italian, Japanese, Jorean, Russian, Spanish, Brazilian Portuguese and if you know a computer teacher, you might tell them about this!

Take a look at Small Basic Tetris, for example. You can run it in the browser with Silverlight, right here. The full Small Basic source code for the app is listed right on the page. There's a bunch of great sample Small Basic apps here also.

It has a nice friendly IDE (Integrated Development Environment) with a clever take on Intellisense as seen below. The IDE goes out of its way to give you as much information and context as possible not only with the intellisense "arc" but also context-sensitive help in the right doc.

The Small Basic IDE

Even more clever, I think, is the "Graduate" button that will convert your Small Basic program into Visual Basic for use directly in Visual Studio.

Here's what a Small Basic text mode application would look like:

number = 100
While (number > 1)
number = number / 2

Here's a SmallBasic Windows app:

GraphicsWindow.BackgroundColor = "Black"
GraphicsWindow.Width = 200
GraphicsWindow.Height = 160
GraphicsWindow.PenColor = "Blue"
For i = 1 To 10
GraphicsWindow.PenWidth = i
GraphicsWindow.DrawLine(20, i * 15, 180, i * 15)

For those of us old enough to remember learning to program with LOGO and its ubiquitous Turtle, Small Basic includes a Turtle object built in! Remember this?

sides = 50
length = 400 / sides
angle = 360 / sides
Turtle.Speed = 9
For j = 1 To 20
For i = 1 To sides

Which gives us this image. See the turtle inside?

The LOGO Turtle drawing Circles in SmallBasic

The most amazing part from a learning perspective is the ability to publish your game directly to the Small Basic website and play it or give it to your friends. I hit Publish for this Turtle app and Small Basic - in one click - gave me this link: Now I can send my friends or students to that link.  They can play the game LIVE, see the source listing right there, or even embed it on their own website with included HTML.

I'm really impressed with the amount of though that was put into this app and how easy it was. I hope other folks at Microsoft check it out and appreciate the simplicity.

Related Links

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.