Scott Hanselman

Videos of talks from the 2012 BUILD Conference - Angle Brackets and Curly Braces

November 5, '12 Comments [14] Posted in ASP.NET | Azure | Speaking
Sponsored By

It was an insane week at BUILD. Much of my schedule was my own fault as I continue to treat Microsoft Outlook as if it were a game of Tetris, franticly packing appointments ten-deep.

The "Angle Brackets" team (ASP.NET, Azure, and Web Tools) had a good showing and lots of fun. We chose to create a little two day mini-conf by scheduling our talks on Thursday and Friday and I think it worked great. There was a Day 1 and Day 2 Keynote. I had a small 10 minute coding segment before ScottGu in the Day 2 Keynote. I kicked if off on Day 3 (Thursday) with an un-keynote at 8:30am called Angle Brackets, Curly Braces, One ASP.NET and the Cloud. Then the team had their talks on Thursday and Friday and finally Jon Galloway and I ended the show with the very LAST talk  on Friday afternoon called "Bleeding edge ASP.NET."

Here's video of my talks, as well as links to all the talks our team did! Remember that you can download these talks in various formats and watch them at your leisure!

Angle Brackets, Curly Braces, One ASP.NET and the Cloud

I'm very happy with how this talk turned out and I hope you enjoy it. If you do, let me know and share it with your friends.

Downloads:


Bleeding edge ASP.NET: See what is next for MVC, Web API, SignalR and more…

I played code monkey in this talk with Jon Galloway. We had great fun, showed lots of demos and generally picked on each other throughout.

Downloads


Talks from the Web Team

There were some amazing talks this year.

See how we're BUILDing stuff? Each of these talks is code-heavy and focused on getting you working and building great stuff and hopefully having fun while you do it.

Be sure to check out all the BUILD talks. They are up on http://channel9.msdn.com/Events/Build/2012 in their entirety, with both speaker cameras via Picture-in-Picture and high-def video. Hope you enjoy them!

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

Podcast Update with Guest Spots and a New Show - October 2012

October 30, '12 Comments [5] Posted in Podcast
Sponsored By

I've been on a podcasting kick lately. Not for any particular reason, but a number of things have come together that have found me as a guest on a number of podcasts. I've also had the good fortune to have a number of great guests on Hanselminutes lately.

Lots of folks who listen to podcasts are doing it while commuting. I hope you enjoy these additional podcasts and perhaps they'll edutain you during your daily commute.

I hope you take a few minutes and download a few of these shows.


imageStackExchange Podcast #35

Just last week my buddy Joel Spolsky had me on the 35th episode of the new StackExchange Podcast. I've complained about podcasts that are "just talk" before and brought my prejudice to Joel's show, but we have so much fun just beating each other up that I have to admit defeat. Not ever podcast has to be dense with information and content - and this episode is no exception. ;)

I hope they'll have me back soon.


ratchetandthegeeksquareAnnouncing - Ratchet and The Geek #1

Just a few days ago I launched my third podcast as a collaboration with my good friend Luvvie. Luvvie is a social media consultant and popular humor blogger that I've known for years. We've been kicking around the idea of a podcast since early this Spring. We have such fun when we call each other on the phone, why don't we start recording our calls? (and adding a little structure.)

Luvvie has blogging, social media and marketing expertise, while I'm a coder and teacher. We both like the same music, pop culture, TV shows, movies, gadget and technology so we have mashed it all together into Ratchet and The Geek.

We'll be doing the show late late on Thursday nights every two weeks.


image

Fanboy Radio #616

I've been REALLY getting into Digital Comics via Comixology over the last year and blogged about it in some detail (with animated gifs!) and earlier this year I was a guest on an episode of Fanboy Radio.

Fanboy Radio (or 'FbR') is a radio talk show all about pop culture and entertainment from the fan's perspective. It's also broadcast on the radio in Fort Worth, Texas.

We had a great chat, covering the rise of digital comics, Comixology, GuidedView technology and lots more. The guys were a lot of fun and it was an opportunity for me to geek out about something that isn't programming or computers. (I DO have other interests, you know.)


imageSimple Mobile Review (SMRPodcast) #136

Last month I was on Simple Mobile Review at the invitation of Chris Ashley. We talked about phones and NFC technology and if it will ever take off. We discussed the new iPhone 5 and teased Robb for sticking with his BlackBerry.

It was a great time and we spent a bunch of time teasing each other, which is an important part of any good podcast.


dramaThis Developer's Life - Drama

Some of you may have missed the most recent episode of This Developer's Life from last month. Rob and I asked ourselves where does drama come from? How do we react to it? How much drama can be created by simple semicolon? We explore The Great JavaScript Semicolon Affair with guests like

  • Peter Cooper Friendly publisher, programmer and author
  • Derick Bailey Consultant and aspiring microprenuer
  • H. Alan Stevens Father, Geek & Speaker
  • Dave Ward Software developer focusing on jQuery and web application usability.
  • Sara Chipps Just a girl, standing in front of a compiler, asking it to love her.
  • Tenderlove When I'm not trimming my beard, I'm hanging out with my lady.

This Developer's Life is sponsored out of kindness by the epic win that is DevExpress.


Hansel-Minutes-LogoHanselminutes Podcast Rollup

If I may be so bold as to say Hanselminutes has been pretty good lately. I've had some great guests - many suggested by listeners! - and some great conversations. Here's just this month:

This week's show has a special offer for listeners from DNSimple, my DNS service of choice. Four months free at http://dnsimple.com/hm. Did you miss one of these shows perhaps? Why not subscribe now so you don't miss another show?


Sponsor: Big thanks to this week's sponsor. Check them out, it's a great program, I've done it and spoken to actual live humans who help you get started writing an app! Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today. Your Idea. Your App. 30 Days.

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

Cloud-Controlled Remote Pan Tilt Zoom Camera API for a Logitech BCC950 Camera with Azure and SignalR

October 23, '12 Comments [33] Posted in Hardware | Lync | Open Source | Remote Work
Sponsored By

I like my giant blog post titles. Nyah.

Logitech BCC950 ConferenceCam, HD 1080p Video at 30 fps, 78deg. Field of View, USB 2.0 CompliantAs a remote worker for almost 5 years now, I live in video conferences. I feel really strongly about the power of seeing someone's face rather than just being a voice on a scratchy speaker phone. I've build an AutoAnswer Kiosk for Lync with some friends that you can get for free at http://lyncautoanswer.com (and read about the code here), I've got a BusyLight so the kids know I'm on a call, and the Holy Grail for the last few years has been a reliable Pan Tilt Zoom camera that I could control remotely.

Related Reading

A few years ago I super-glued a LifeCam camera to an Eagletron TrackerPod and build a web interface to it. I wanted to do this on the cheap as I can't afford (and my boss is into) a $1500 Panasonic IP Camera.

The Solution...er, the Problem

I have found my camera and built my solution. The Logitech BCC950 Conference Cam is the best balance between cost and quality and it's got Pan Tilt and (digital) Zoom functionality. The Zoom is less interesting to me than the motorized Pan Tilt.

Let's think about the constraints.

  • A Logitech BCC950 PTZ camera is installed on a Windows machine in my office in Seattle.
  • I'm anywhere. I'm usually in Portland but could be in a hotel.
    • I may or may not be VPN'ed into work. This means I want to be able to communicate with the camera across networks, traverse NATs and generally not worry about being able to connect.
  • I want to be able to control the camera in a number of ways, Web API, whatever, but ideally with cool buttons that are (or look) integrated with my corporate instant messaging system.

There's three interesting parts here, then.

  1. Can I even control the camera's PTZ functions programmatically?
  2. Can I relay messages across networks to the camera?
  3. Can I make a slick client interface easily?

Let's figure them out one at a time.

Can I even control the camera's PTZ functions programmatically?

I looked all over and googled my brains out trying to find an API to talk to the Logitech camera. I emailed the Logitech people and they folks me that the camera would respond to DirectShow APIs. This means I can control the camera without any drivers!

MSDN showed me PROPSETID_VIDCAP_CAMERACONTROL which has an enumeration that includes things like:

This lead me to this seven year old DirectShow .NET library that wraps the hardest parts of the DirectShow COM API. There's a little utility called GraphEdt.exe (GraphEdit) that you can get in the Windows SDK that lets you look at all the DirectShow-y things and devices and filters on your system.

GraphEdit

This utility let me control the camera's Zoom but Pan and Tilt were grayed out! Why?

GraphEdit showing Pan and Tilt grayed out

Turns out that this Logitech Camera supports only relative Pan and Tilt, not absolute. Whatever code that creates this Properties dialog was never updated to support a relative pan and tilt but the API supports it via KSPROPERTY_CAMERACONTROL_PAN_RELATIVE!

That means I can send a start message quickly followed by a stop message to pan. It's not super exact, but it should work.

Here's the C# code for my move() method. Note the scandalous Thread.Sleep call.

private void MoveInternal(KSProperties.CameraControlFeature axis, int value)
{
// Create and prepare data structures
var control = new KSProperties.KSPROPERTY_CAMERACONTROL_S();

IntPtr controlData = Marshal.AllocCoTaskMem(Marshal.SizeOf(control));
IntPtr instData = Marshal.AllocCoTaskMem(Marshal.SizeOf(control.Instance));

control.Instance.Value = value;

//TODO: Fix for Absolute
control.Instance.Flags = (int)CameraControlFlags.Relative;

Marshal.StructureToPtr(control, controlData, true);
Marshal.StructureToPtr(control.Instance, instData, true);
var hr2 = _ksPropertySet.Set(PROPSETID_VIDCAP_CAMERACONTROL, (int)axis,
instData, Marshal.SizeOf(control.Instance), controlData, Marshal.SizeOf(control));

//TODO: It's a DC motor, no better way?
Thread.Sleep(20);

control.Instance.Value = 0; //STOP!
control.Instance.Flags = (int)CameraControlFlags.Relative;

Marshal.StructureToPtr(control, controlData, true);
Marshal.StructureToPtr(control.Instance, instData, true);
var hr3 = _ksPropertySet.Set(PROPSETID_VIDCAP_CAMERACONTROL, (int)axis,
instData, Marshal.SizeOf(control.Instance), controlData, Marshal.SizeOf(control));

if (controlData != IntPtr.Zero) { Marshal.FreeCoTaskMem(controlData); }
if (instData != IntPtr.Zero) { Marshal.FreeCoTaskMem(instData); }
}

All the code for this PTZDevice wrapper is here. Once that library was working, creating a little console app to move the camera around with a keyboard was trivial.

var p = PTZDevice.GetDevice(ConfigurationManager.AppSettings["DeviceName"], PTZType.Relative);
while (true)
{
ConsoleKeyInfo info = Console.ReadKey();
if (info.Key == ConsoleKey.LeftArrow)
{
p.Move(-1, 0);
}
else if (info.Key == ConsoleKey.RightArrow)
{
p.Move(1, 0);
}
else if (info.Key == ConsoleKey.UpArrow)
{
p.Move(0, 1);
}
else if (info.Key == ConsoleKey.DownArrow)
{
p.Move(0, -1);
}
else if (info.Key == ConsoleKey.Home)
{
p.Zoom(1);
}
else if (info.Key == ConsoleKey.End)
{
p.Zoom(-1);
}
}

Also easy was a simple WebAPI. (I put the name of the camera to look for in a config file in both these cases.)

[HttpPost]
public void Move(int x, int y)
{
var p = PTZDevice.GetDevice(ConfigurationManager.AppSettings["DeviceName"], PTZType.Relative);
p.Move(x,y);
}

[HttpPost]
public void Zoom(int value)
{
var p = PTZDevice.GetDevice(ConfigurationManager.AppSettings["DeviceName"], PTZType.Relative);
p.Zoom(value);
}

At this point I've got the camera moving LOCALLY. Next, I mail it to Damian (my office buddy) in Seattle and he hooks it up to my office computer. But I need something to control it running on THAT machine...and talking to what?

Can I relay messages across networks to the camera?

Here's the architecture. Since I can't talk point to point via TCP between wherever I am and wherever the camera is, I need a relay. I could use a Service Bus Relay which would be great for something larger but I wanted to see if I could make something even simpler. I'd like to use HTTP since it's, well, it's HTTP.

A Diagram showing my laptop talksk via SignalR through Azure to the camera in Seattle

Since Azure lets me have 10 free websites and automatically supports SSL via a wildcard cert for sites at the *.azurewebsites.net domain, it was perfect for what I needed. I want to use SSL because it's the best way to guarantee that my traffic not be affected by corporate proxy servers.

There's three parts. Let's start in the middle. What's the Relay look like? I'm going to use SignalR because it will let me not only call methods easily and asynchronously but, more importantly, it will abstract away the connection details from me. I'm looking to relay messages over a psuedo-persistent connection. 

So what's the code look like for a complex relay system like this? ;)

using System;
using SignalR.Hubs;

namespace PTZSignalRRelay
{
public class RelayHub : Hub
{
public void Move(int x, int y, string groupName)
{
Clients[groupName].Move(x, y); //test
}

public void Zoom(int value, string groupName)
{
Clients[groupName].Zoom(value);
}

public void JoinRelay(string groupName)
{
Groups.Add(Context.ConnectionId, groupName);
}
}
}

Crazy, eh? That's it. Clients call JoinRelay with a name. The name is the name of the computer with the camera attached. (More on this later) This means that this single relay can handle effectively any number of clients. When a client calls to Relay with a message and group name, the relay then broadcasts to clients that have that group name.

Can I make a slick client interface easily?

I created a super basic WPF app that's just a transparent window with buttons. In fact, the background isn't white or black, it's transparent. It's a SolidColorBrush that is all but invisible. It's not totally transparent or I wouldn't be able to grab it with the mouse!

<SolidColorBrush x:Key="NotQuiteTransparent" Color="#01000000"></SolidColorBrush>

The buttons use the .NET SignalR library and call it like this.

HubConnection connection = null;
IHubProxy proxy = null;
string remoteGroup;
string url;

private void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}

private async void MoveClick(object sender, RoutedEventArgs e)
{
var ui = sender as Control;
Point p = Point.Parse(ui.Tag.ToString());
await proxy.Invoke("Move", p.X, p.Y, remoteGroup);
}

private async void ZoomClick(object sender, RoutedEventArgs e)
{
var ui = sender as Control;
int z = int.Parse(ui.Tag.ToString());
await proxy.Invoke("Zoom", z, remoteGroup);
}

private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
url = ConfigurationManager.AppSettings["relayServerUrl"];
remoteGroup = ConfigurationManager.AppSettings["remoteGroup"];
connection = new HubConnection(url);
proxy = connection.CreateProxy("RelayHub");
await connection.Start();
await proxy.Invoke("JoinRelay", remoteGroup);
}

The client app just needs to know the name of the computer with the camera it wants to control. That's the "GroupName" or in this case, from the client side, the "RemoteGroup." Then it knows the Relay Server URL, like https://foofooserver.azurewebsites.net. The .NET client uses async and await to make the calls non-blocking so the UI remains responsive.

Here's a bunch of traffic going through the Relay while I was testing it this afternoon, as seen by the Azure Dashboard.

Traffic as shown in a graph on the Azure Dashboard

The client calls the Relay and the Relay broadcasts to connected clients. The Remote Camera Listener responds to the calls. We get the machine name, join the relay and setup two methods that will respond to Move and Zoom.

The only hard thing we ran into (Thanks David Fowler!) was that the calls to the DirectShow API actually have to be on a UI thread rather than a background thread, so we have to get the current SynchronizationContext and post our messages with it. This results in a little indirection but it's not too hard to read. Note the comments.

private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var deviceName = ConfigurationManager.AppSettings["DeviceName"];
device = PTZDevice.GetDevice(deviceName, PTZType.Relative);

url = ConfigurationManager.AppSettings["relayServerUrl"];
remoteGroup = Environment.MachineName; //They have to hardcode the group, but for us it's our machine name
connection = new HubConnection(url);
proxy = connection.CreateProxy("RelayHub");

//Can't do this here because DirectShow has to be on the UI thread!
// This would cause an obscure COM casting error with no clue what's up. So, um, ya.
//proxy.On<int, int>("Move",(x,y) => device.Move(x, y));
//proxy.On<int>("Zoom", (z) => device.Zoom(z));

magic = SynchronizationContext.Current;

proxy.On<int, int>("Move", (x, y) => {
//Toss this over the fence from this background thread to the UI thread
magic.Post((_) => {
Log(String.Format("Move({0},{1})", x,y));
device.Move(x, y);
}, null);
});

proxy.On<int>("Zoom", (z) => {
magic.Post((_) =>
{
Log(String.Format("Zoom({0})", z));
device.Zoom(z);
}, null);
});

try {
await connection.Start();
Log("After connection.Start()");
await proxy.Invoke("JoinRelay", remoteGroup);
Log("After JoinRelay");
}
catch (Exception pants) {
var foo = (WebException)pants.GetBaseException();
StreamReader r = new StreamReader(foo.Response.GetResponseStream());
string yousuck = r.ReadToEnd();
Log(yousuck);
throw;
}
}

It All Works Together

Now I've got all the parts. Buttons that call a Relay that then call back - through NAT and networks - to the Remote Camera Listener which uses the Camera library to move it.

It's ALIVE and it's awesome

It works like a champ. And, because the buttons are transparent, I can put them over the Lync window and pretend it's all integrated.

TODO: I'm hoping that someone who knows more about Windows Internals will volunteer to create some code that will automatically move the buttons as the Lync Window moves and position them over the video window in the corner. Ahem.

The buttons look integrated. But they aren't.The buttons look integrated. But they aren't.

You can set this up yourself, but I haven't gotten around to making an install or anything. If you have a Logitech BCC950 you are welcome to use my Relay until it costs me something. There's a preliminary download up here so you'd only need the Listener on one side and the Buttons on the other. No drivers are needed since we're using DirectShow itself.

This was great fun, and more importantly, I use this PanTiltZoom System ever day and it makes my life better. The best was that I was able to do the whole thing in C#. From client UI to cloud-based relay to device control to COM wrapper, it was all C#. It makes me feel very empowered as a .NET developer to be able to make systems like this with a minimal amount of code.

Lync Developer Resources

Related Links


Sponsor: Big thanks to this week's sponsor. Check them out, it's a great program, I've done it and spoken to actual live humans who help you get started writing an app! Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today. Your Idea. Your App. 30 Days.

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

Instapaper delivered to your Kindle changes how you consume web content - Plus IFTTT, blogs and more

October 18, '12 Comments [29] Posted in Reviews
Sponsored By

I've talked about Instapaper before when I tease folks of having 42 tabs open.

Instapaper - Google Chrome

Remember that "open in new tab" rarely means "read it later." It usually means "use up memory and let this page run in the background until eventually declare tab-bankruptcy and close them all."

Kindle Instapaper Photo by Joshua Kaufman via Flickr under CC BY-SA 2.0 http://www.flickr.com/photos/joshuakaufman/5020686891/So if Open In New Tab doesn't mean Read Later, what does? Why, READ LATER does! This gets even better when you combine a Read Later tool like Instapaper with an Amazon Kindle like my new Kindle Paperwhite (I reviewed the Paperwhite last week.)

Inserting a Kindle into your Life's Workflow

Here's the idea. You get a bunch of links that flow through your life all week long. These are often in the form of what I call "long-form reading." Hackernews links, NYTimes studys, academic papers, etc. Some folks make bookmarks, have folders called "Links" on their desktops, or email themselves links.

I have these websites, papers and interesting links rolled up and delivered automatically to my Kindle every week. Think about how amazing that is and how it can change your relationship with content on the web. The stress and urgency (and open tabs) are gone. I am naturally and organically creating a personalized book for weekend reading.

I have a bookmarklet from Instapaper that says "Read Later" on my browser toolbar. I've put it in every browser I use, even Mobile Safari. I've also logged into Instapaper from all my social apps so that I can Read Later from my iPhone Twitter Client for example. You'd be surprised how many apps support Instapaper once you start looking for this.

Workflow Flow Chart - sorry if you are blind. There's text about this soon.What this means it is that Instapaper is ready and waiting for me in every location where an interesting piece of long-form reading could present itself. I don't stress, I click Read Later and the document is shipped off to Instapaper.

I even made a flowchart a few years back. You can get more details on that in my blog post Two Must-Have Tools for a More Readable Web.

Instapaper delivered to your Kindle

So you're building a queue of links that is sent to Instapaper. Perhaps you've tried this  before but then never visited the Instapaper App or Website. This is a common complaint and why I like document delivery to the Kindle. I use my Kindle all the time so I appreciate a "no clicks required" workflow. If books show up on my Kindle I'll read them.

Just visit http://www.instapaper.com/user/kindle once you've got an Instapaper account and put in your Kindle's email address. Did you know every Kindle has one? It's either something@free.kindle.com for free WiFi delivery or just something@kindle.com for 3G delivery with a small fee. I use the free one. You can find out your Kindle's Email Address here under Personal Document Settings.

The key is to allow your Kindle to receive email from the unique Instapaper email address. It's a whitelist.

image

Then, back over in the Instapaper Settings, I set a delivery time if at least 5 things are in the "book":

image

Pulling Links and Content from other Locations with IFTTT

Perhaps you pull your content from elsewhere, or you Like things on Facebook, put them in Dropbox, email them to a special address or something else. You can use If This Then That as the social workflow glue to route those links to Instapaper - and ultimately to your Kindle!

For example, I also use the Delicious social bookmarking service to hold things I want to save. But, I also want to read them and I don't want to stop using Delicious just because I use Instapaper. Instead, I use an IFTTT Recipe to  take newly bookmarked things and send them to Instapaper (and my Kindle!) as well.

Here's my Delicious to Kindle Recipe. You can make any recipe you want to pull links from wherever you find them and send them into your long-form reading queue.

image

You can even have blogs - like this one! - sent automatically to your Kindle via Instapaper with an IFTTT recipe like this:

image

The possibilities are endless.

Conclusion

It can't be overstated how useful this is if you have a Kindle. Rather than opening "guilt-tabs" that you'll never read, have them delivered to yourself in a way that will encourage you TO READ THEM!

If your system isn't working for you, change it. If you already have a system that works, well, great job making it all the way to the end of this blog post!

For more personal productivity ideas watch my video on Scaling Yourself and visit the Productivity section of this blog.


This Week's Sponsor: Your Idea. Your App. 30 Days. Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today.

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

How to call WinRT APIs in Windows 8 from C# Desktop Applications - WinRT Diagram

October 12, '12 Comments [28] Posted in Win8 | Windows Client
Sponsored By

I was trying to access some of the sensors that are built into this Intel Ultrabook that runs Windows 8. However, while there's support for Location Sensors built into the .NET 4 libraries on Windows 7 and up, I want to access the complete Sensor and Location Platform that is built into Windows 8 itself. Those APIs are available via COM and I could call them via COM, but calling them via the WinRT layer is so much nicer. Plus, this is kind of why WinRT exists.

This got me thinking about WinRT and what it means. I did a podcast a few months ago that really cleared things up but I've always found all the various diagrams that attempted to explain how things fit together to be WAY TOO COMPLEX.

DISCLAIMER: All diagrams are, by their nature, oversimplifications. I work on Web Stuff, not Windows Stuff, so this is all my opinion and conjecture, done on my own time. I'm not in the Windows org, I'm just a dude trying to write an app for babies.

I figure it can't be as complicated as all these diagrams. I drew this to help myself understand.

WinRT Diagram

Just like the C Language has the C Runtime that provides a bunch of supporting functions and defines a calling convention for them, so the Windows Runtime (WinRT) does for Windows and its languages. These APIs and runtime includes metadata about calling conventions that make WinRT APIs easier to call than COM.

See how in the diagram I can call any API from the .NET CLR? In the case of the Sensors APIs I want to call, while they are ultimately Win32 APIs or COM APIs, I would like to call them using the highest level calling convention available and that's the very friendly Windows RT ones.

Calling WinRT APIs from C# Desktop Applications

I like to test things using small Console Apps, but those aren't "Windows Store Applications," so am I allowed to call WinRT APIs from my Desktop or Console application?

Sure. There's actually a section of the MSDN Documentation that lists out all the WinRT APIs for Windows 8 that are able to be called from the Desktop. I can specifically check the LightSensor class itself within the documentation and make sure it's allowed to be called from Desktop applications.

LightSensor is allowed to be called from Desktop Apps

There isn't super-clear but there IS documentation on how to add WinRT references to non-Windows Store applications.

Adding a Reference to WinRT from a Desktop App

The docs say, somewhat obscurely:

In the desktop projects, the Core tab doesn’t appear by default. The user can choose to code against the Windows Runtime by opening the shortcut menu for the project node, choosing Unload Project, adding the following snippet, opening the shortcut menu for the project node again, and then choosing Reload Project. Now, when the user invokes the Reference Manager dialog box from the project, the Core tab will appear.

   <propertygroup>
    <targetplatformversion>8.0</targetplatformversion>
  </propertygroup>

I'll make a .NET 4.5 C# Console Application. I'll edit the .csproj and add the TargetPlatformVersion line. I'll select Add Reference from the context menu on the References node of Solution Explorer.

Windows Core References

I'll add a little code to check the status of the Light Sensor on my laptop:

LightSensor light = LightSensor.GetDefault();
if (light != null)
{
uint minReportInterval = light.MinimumReportInterval;
uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
light.ReportInterval = reportInterval;

light.ReadingChanged += light_ReadingChanged; //event hander
}

However, when I compile the app, I get an error on the line where I'm trying to hook up an event handler. The "+=" language sugar for adding a multicast delegate isn't working.

Error    1    Property, indexer, or event 
'Windows.Devices.Sensors.LightSensor.ReadingChanged'
is not supported by the language; try directly calling accessor
methods 'Windows.Devices.Sensors.LightSensor.add_ReadingChanged
(Windows.Foundation.TypedEventHandler
Windows.Devices.Sensors.LightSensorReadingChangedEventArgs>)'
or 'Windows.Devices.Sensors.LightSensor.remove_ReadingChanged
(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)'

To fix this and get the appropriate assemblies loaded within my application support calling WinRT from my Desktop Application I need to add a reference to System.Runtime and System.Runtime.InteropServices.WindowsRuntime.dll. It's in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5 on my system.

System.Runtime.InteropServices.WindowsRuntime.dll in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5

Now my app compiles. I'll even change out the delegate and make it a Anders lambda because that's fancy.

light.ReadingChanged += (s, a) =>
{
Console.WriteLine(String.Format("There was light! {0}", a.Reading.IlluminanceInLux));
};

Now I can run my little console app, sense some light and check it out in action. Here's a screenshot showing the results of me shining a light at my laptop. You can see the Ambient LightSensor picks it up and outputs to the Console.

The ambient light sensor reacting

While the tooling to make non-Windows Store applications call Windows RT applications is a little manual within Visual Studio right now, the underlying ability and runtime have work very nicely for me. Hopefully these few manual setups will turn into a checkbox at some point.

It's also nice to see the MSDN documentation includes the details about which APIs actually can be called from the Desktop and which can be called from Windows Store apps.


This week's sponsor: Your Idea. Your App. 30 Days. Begin your 30-day journey to creating a Windows Store app or game for Windows 8 or Windows Phone today.

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.