My primary development machine at home is still (gasp!) running the 32 bit version of Windows 7. I just haven’t gotten around to paving it to upgrade to 64 bit. My other machines, including my presentation laptop, are all running 64 bit.
Prior to PDC, I had made some significant changes to the Silverlight C64 emulator. I added sound, started to add a touch-enabled user interface, fixed up some minor perf issues etc. One of the changes was to enable access to the Windows 7 device API in order to use the accelerometer as a joystick.
Accelerometer as a Joystick – a COM Hack
The idea was to strap the accelerometer to the back of my tablet, and use the touch interface as the button and keyboard. The end result is a pretty expensive 8-bit hand-held game machine :)
// this relies on the .NET accelerometer joystick implementation I wrote
// and the COM component it registers. It also requires that the app have
// the silverlight version of full trust so it can work with COM
public class AccelerometerJoystick : IJoystick
{
private dynamic _joystick;
public void Initialize()
{
_joystick = ComAutomationFactory.CreateObject("PeteBrown.AccelerometerJoystick.Joystick");
_joystick.Initialize();
}
public bool IsJoystickPointedNorth
{
get { return _joystick.IsJoystickPointedNorth; }
}
public bool IsJoystickPointedSouth
{
get { return _joystick.IsJoystickPointedSouth; }
}
public bool IsJoystickPointedEast
{
get { return _joystick.IsJoystickPointedEast; }
}
public bool IsJoystickPointedWest
{
get { return _joystick.IsJoystickPointedWest; }
}
}
Since the canonical Windows 7 demo for the accelerometer is the XNA racing car game, I decided to use Pole Position as my own test case.
I built the accelerometer interface by using a shim DLL I wrote which interfaces with the device API using the Windows API Code Pack and then exposes that info via COM. I did that because the native device API is not exposed via IDispatch (although it appears there may be some COM+ way around that). Silverlight 4 only supports IDispatch-based COM interfaces.
On my main dev machine, I just did a regasm /codebase on the COM dll, and Silverlight was immediately able to use it via the IDispatch support in Silverlight 4. It actually worked really well and had decent performance.
Now I knew this was a colossal hack, and not an approach I would recommend for any real app. After all, you’d have to install and register a separate inproc COM dll with your Silverlight app, something that’s akin to including a custom ActiveX control in your Ajax app. It’s the VB6 days all over again. Naughty developer!
Besides, if you’re going to go through that trouble, just write the app in WPF and get a cleaner end-user install and better developer experience. If you want to light up both on Windows and x-platform, use MEF and/or cross-compilation.
In the course of a different conversation, I mentioned this little hack to Ashish Shetty (one of the Silverlight PMs) and he seemed surprised it worked and worked well. To put it bluntly, this is not a supported scenario.
What the COM API is expected to be used for is out-of-process communication with existing COM Servers installed on the local machine – the “automate Microsoft Excel” scenario. While you could talk to your own custom out-of-process servers, that wasn’t really the intent, as it would require an additional install. Again, if you’re going to go through all that trouble and restrict yourself to the Windows platform anyway, write it in WPF.
64 bit vs. 32 bit
One reason the in-process scenario is not a supported scenario (and I say that without any official statement on the matter – just basing it on reactions from the team) is you’ll get different results on a 64 bit vs. 32 bit system.
So, I was going to demo this cool hack at PDC09, but my demo machine is 64 bit. It simply would not work on the 64 bit machine, and it wasn’t until the day before PDC that I realized the platform bitness was why. It failed when trying to find the inproc server entry in the registry. Now, before you ask, I didn’t check to see if I compiled to 64 bit if that would fix the issue on the 64 bit platform, as I felt that was a completely unsustainable approach.
The Solution: Out-of-Process
If you must create your own shim, you’ll need to do it as an out-of-process COM server (the old ActiveX EXE). But before you go that route, ask yourself if it wouldn’t be better to write this in WPF and just use the full .NET framework rather than involve COM, the registry, the performance hit of an out-of-proc server, and the install issues related to it all.
What’s Next for the C64 Emulator
I have a few things in store for the emulator, but the biggest is opening it up and cross-compiling. When Silverlight 4 is released in 2010, I intend to have a cross-compiled version running on Silverlight 4 and WPF 4, that likely uses MEF to pull in different types of interfaces (like the accelerometer, keyboard-simulated, and on-screen touch joysticks). I don’t intend to push the COM approach on Silverlight any further, as while it was really fun to do, I don’t consider that a best practice. I’ll keep the Silverlight version web-oriented, and add machine access “stuff” to the WPF version.