Windows Phone 7 supports VB.Net and F#
Hi Folks,
In this article we’ll review Windows Phone 7 support for the Visual Basic .Net and F# programming languages.
Our goal is to demonstrate that Windows Phone 7 can indeed support F# and VisualBasic.Net code libraries and user controls.
You can get the sample project we’ve build in this article @ http://JustinAngel.net/storage/WP7.Languages.zip
Why?! Why has Microsoft forsaken us?!
Reading about VB.Net & F# Windows Phone 7 support online can be quite misleading.
On the official MSDN WP7 forums we can find the following quote:
“Windows Phone 7 currently is supported only for C#” - Mark Chamberlain
During Windows Phone 7 jumpstart webcasts an audience member asked about VB.Net support and was answered:
“I'm afraid Visual Basic is not supported for WP7 dev” - Andy Wigley
On the official Silverlight WP7 forums we can find many questions asking about WP7 VB.net support with answers like:
Q: “Can I develop applications with VB.NET for Windows Phone 7?”
A: “No, You can't.”
TechRepublic tech blog is quoted in saying:
“The only language that will work up front is C#; VB.NET developers need not apply.” TechRepublic
And Canadian Heritage and official Languages Minister, the Honourable MP James Moore said:
“My dog wears a conservative party raincoat”
All of the aforementioned statements, with the exception of that last one, are all patently false. And that last statement is just plain embarrassing.
Windows Phone 7 does indeed support Visual Basic .Net and F# and has done so since day #1.
Windows Phone 7 Applications are C#
The one statement that can made and is factually true is that during the WP7 Beta the only language supported for the WP7 application project itself is C#.
Which means absolutely nothing, since a WP7 application can just refer to a F# Silverlight 3 library or VB.Net Silverlight 3 library.
Using F# in Windows Phone 7
Let’s go over how to setup a simple “hello world” WP7 app with F#.
1) Create a new C# Windows Phone 7 application.
2) Add a F# Silverlight 3 project to the solution.
3) Open up the module1.fs file and write some F# code.
For this basic sample we’ll make do with a simple non-UI sample of returning “Hello world”.
module WP7FSharpLibrary
type myClass = class
new () as this = {}
member s.myMethod() =
"OMG! Windows Phone 7 is running F# code!"
end
3) Add a reference from your WP7 app to the new F# library and build the solution.
4) in the C# WP7 application, initialize your F# class and invoke the proper members.
// Constructor
public MainPage()
{
InitializeComponent();
var FSharpClass = new WP7FSharpLibrary.myClass();
ContentGrid.Children.Add(new TextBlock() { Text = FSharpClass.myMethod()});
}
When we run our app we can clearly see that F# executes in Windows Phone 7 without a hitch.
It’s also possible to have F# initialize various UI elements and create the UI for us.
But that really isn’t where functional programming normally excels in, so I’ll avoid demoing that worst practice.
Using a Visual Basic .Net UserControl in a Windows Phone 7
1) Create a new C# Windows Phone 7 application.
2) Add a VisualBasic.net Silverlight 3 project to the solution.
3) Add a new UserControl to your Silverlight 3 VB.Net project.
In our case we’ll add a simple user control with a <ListBox /> that has a few items.
Partial Public Class SL3VbNetUserControl
Inherits UserControl
Public Sub New
InitializeComponent()
Me.DataContext = {"Hello from VB.Net on WP7!", "World", "Foo", "Bar", "Baz"}
End Sub
End Class
<UserControl x:Class="WP7.VisualBasicNet.SL3VbNetUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot">
<ListBox ItemsSource="{Binding}" />
</Grid>
</UserControl>
4) Add a reference from the WP7 app to the new VB.Net library and build.
5) Add the new SL3 VB.Net UserControl to your MainPage in the WP7 project.
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentGrid" Grid.Row="1">
<VisualBasicNet:SL3VbNetUserControl xmlns:VisualBasicNet="clr-namespace:WP7.VisualBasicNet;assembly=WP7.VisualBasicNet" />
</Grid>
6) If we try and run the project at this state, we’ll see the following build warning:
Warning 1 The primary reference "d:\visual studio 2010\Projects\WP7.Languages\WP7.VisualBasicNet\Bin\Debug\WP7.VisualBasicNet.dll" could not be resolved because it has an indirect dependency on the framework assembly "Microsoft.VisualBasic, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" which could not be resolved in the currently targeted framework. "Silverlight,Version=v4.0,Profile=WindowsPhone". To resolve this problem, either remove the reference "d:\visual studio 2010\Projects\WP7.Languages\WP7.VisualBasicNet\Bin\Debug\WP7.VisualBasicNet.dll" or retarget your application to a framework version which contains "Microsoft.VisualBasic, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35". WP7.Languages
Make sure to add a reference from the WP7 app to Microsoft.VisualBasic.dll, and that it is marked as “Copy Local = False”.
On my dev box the DLL is found @ c:\Program Files (x86)\Microsoft Silverlight\4.0.50524.0\Microsoft.VisualBasic.dll
Right click on the “Microsoft.VisualBasic” reference, choose “properties” and set “Copy Local” to false”.
After that change we can run our project and the Visual Basic .Net Silverlight 3 UserControl just shows up in our Windows Phone 7 project.
Obviously, after adding the Windows Phone 7 dlls to our VB.Net project we would be able to do anything a C# project can: GPS Location, Push Notifications, Accelerometer, Navigation, etc.
Fin
Windows Phone 7 supports all 3 main .Net 4.0 programming languages: C#, VisualBasic.Net and F#.
While C# alone is supported during the WP7 beta as the root WP7 application, it’s a small hindrance which we can easily be overcome.
In the aftermath of this blog post I expect both F# developers and VB.Net developers to produce some kick-ass WP7 apps. Yeah, I’m looking at you there.
Feedback
Feel free to sound off in the comments. What are your thoughts on this topic?
Is this an unbearable burden to follow this 5 simple steps? Is it exactly what you were looking for?
Are there any caveats you know off and would like to share with everyone?
Sincerely,
-- Justin Angel
TFS2010 WP7 Continuous Integration
Hi Folks,
In this blog post we’ll cover how to set up automated (nightly?) builds on a Team Foundation 2010 Build Server for Windows Phone 7 projects.
The core challenge we’ll face is not having Visual Studio, Windows Phone 7 Tools or Windows Phone 7 SDK installed on the Build Server.
You can get a sample project with all the modifications discussed in this blog post at: http://JustinAngel.net/Storage/Justin.WindowsPhone.BuildFromLocalFiles.zip
Prerequisite Reading
There’s a blog post that I highly recommend you’ll read before embarking on this quest.
Building Silverlight 3 and Silverlight 4 applications on a .NET 3.5 build machine by Jeff Wilcox
In the linked article Jeff explains how to setup a TFS Build Server for Silverlight.
The blog post you are currently reading is heavily influenced by Mr. Wilcox approach to setting up a build server. Mainly because the writer of this blog post was schooled in the “Wilcox School of Application Packaging and offensive driving”.
If you’d like to setup a Continuous Integration in TFS for a Silverlight project, please read Mr. Wilcox’s article. This blog post only deals with WP7 projects.
The Problem – We don’t have WP7 Installed on a Build Server
Imagine this situation, you’re in a company that has multiple Windows Phone 7 projects on the same build server. Or maybe you’re hosting your TFS2010 Build server and multiple companies are using the same server.
Some project could be prototypes, and some projects could be completely different projects.
All of these projects are using different versions of the WP7 Tools.
If we were talking about Silverlight projects we would be talking about Silverlight 2, Silverlight 3 and Silverlight 4 projects.
In WP7’s case it would be different beta shipped at different months for the Windows Phone 7 developer tools.
However, since a server can only have 1 version installed at any given point in time – one project upgrading the server build version breaks all other projects.
For instance, in Vertigo we’ve got multiple Windows Phone 7 projects we’re working on for different customers.
We can’t guarantee that these multiple projects which are on different schedules with different deliverables will all upgrade together.
The Solution – Don’t install WP7 Tools at all, use local resources
Since the problem here is that our WP7 projects have a dependency on installed software, let’s make sure we sever all of these ties.
The ties between our projects and installed WP7 Tools are built into our MSBuild scripts. We’ll be focusing our efforts in this blog post on those MSBuild scripts.
1. Setup an “ExternalDependencies”/”ExternalTools” directory in source control.
As my own best practice, I establish a “Build” directory nested underneath that folder, and underneath it a “WP7_<Version>” folder. But these two last folders are just my own personal convention.
2. Drag & drop the contents of the WP7 MSBuild central directory into the “ExternalDependencies/Build/WP7_<Version>” folder.
On a x64 dev machine the folder is located on: C:\Program Files (x86)\MSBuild\Microsoft\Silverlight for Phone\v4.0
3. Create another nested folder named “Reference Assemblies” and copy the entire WP7 SDK into it.
On a x64 dev machine the WP7 SDK folder is located at: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\Profile\WindowsPhone
4. In the folder holding the default *.targets files (“ExternalDependencies/Build/MSBuild_WP7_Apri10”), add a new <companyName.WP7.Version>.Targets file.
In this example the file is named “Vertigo.WP7.April10.targets”.
Paste in the following MSBuild script:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SilverlightBuildResources>$(CompileTimeSolutionDir)ExternalDependencies\Build\MSBuild_WP7_Apr10\</SilverlightBuildResources>
<TargetFrameworkDirectory>$(SilverlightBuildResources)Reference Assemblies\</TargetFrameworkDirectory>
<TargetFrameworkSDKDirectory>$(SilverlightBuildResources)Reference Assemblies\</TargetFrameworkSDKDirectory>
<_TargetFrameworkSDKDirectoryItem>$(SilverlightBuildResources)Reference Assemblies\</_TargetFrameworkSDKDirectoryItem>
<_FullFrameworkReferenceAssemblyPaths>$(SilverlightBuildResources)Reference Assemblies\;</_FullFrameworkReferenceAssemblyPaths>
<_TargetFrameworkDirectories>$(SilverlightBuildResources)Reference Assemblies\;</_TargetFrameworkDirectories>
<SilverlightRuntimeVersion>3.0.40624.0</SilverlightRuntimeVersion>
</PropertyGroup>
<Import Project="Microsoft.Silverlight.WindowsPhone.Overrides.targets" />
<Import Project="Microsoft.Silverlight.CSharp.targets" />
</Project>
5. Open up the “Microsoft.Silverlight.Common.targets” file (from “ExternalDependencies/Build/MSBuild_WP7_Apri10”) and comment out Lines 78-92.
The reason we have to do this edit, is because the default WP7 MSBuild script from Microsoft accidently uses registry settings instead of relaying on local values.
<!--<GetSilverlightFrameworkPath
RegistryBase="$(FrameworkRegistryBaseWithVersion)"
RuntimePathRegistryKey="$(RuntimePathRegistryKey)"
RuntimeVersionRegistryKey="$(RuntimeVersionRegistryKey)"
>
<Output TaskParameter="SilverlightPath" PropertyName="TargetFrameworkDirectory" Condition="'$(TargetFrameworkDirectory)' == ''"/>
<Output TaskParameter="SilverlightSDKPaths" ItemName="_TargetFrameworkSDKDirectoryItem" Condition="'$(TargetFrameworkSDKDirectory)' == ''"/>
<Output TaskParameter="SilverlightRuntimeVersion" PropertyName="SilverlightRuntimeVersion" Condition="'$(SilverlightRuntimeVersion)' == ''"/>
</GetSilverlightFrameworkPath>-->
<!-- Reset some items from the above task. Will remove when we merge with SL build system -->
<PropertyGroup>
<!--<_FullFrameworkReferenceAssemblyPaths>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToStandardLibraries($(TargetFrameworkIdentifier), $(TargetFrameworkVersion), ''))</_FullFrameworkReferenceAssemblyPaths>-->
<!--<TargetFrameworkDirectory>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToStandardLibraries($(TargetFrameworkIdentifier), $(TargetFrameworkVersion), $(TargetFrameworkProfile)))</TargetFrameworkDirectory>-->
</PropertyGroup>
6. For every WP7 Project that needs to use local resources, we’ll have to edit the *.csproj file and replace the 2 default <Import> XML elements.
Right Click on your project and choose “Edit Project File”:
BTW, The “Edit Project file” context menu item comes from Visual Studio 2010 PowerCommands.
If you don’t have those installed, you’ll have to manually choose “Unload Project –> Edit File” on each project.
Thanks to Allen Newton who told me about PowerCommands!
In the *.csproj we’ll see the 2 default <Imports>:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.$(TargetFrameworkProfile).Overrides.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
We’ll comment out these <Import> elements and include our new <Import> with some flavouring to make Blend 4 RC to work with it well.
<!-- This MSBuild script compensates for Blend Design time having the wrong SolutionDir -->
<PropertyGroup>
<MissingExternalDependenciesBlendDesignTimehack>false</MissingExternalDependenciesBlendDesignTimehack>
<MissingExternalDependenciesBlendDesignTimehack Condition="!Exists('$(SolutionDir)ExternalDependencies')">true</MissingExternalDependenciesBlendDesignTimehack>
<CompileTimeSolutionDir Condition="'$(MissingExternalDependenciesBlendDesignTimehack)'!='true'">$(SolutionDir)</CompileTimeSolutionDir>
<CompileTimeSolutionDir Condition="'$(MissingExternalDependenciesBlendDesignTimehack)'=='true'">$(SolutionDir)..\</CompileTimeSolutionDir>
</PropertyGroup>
<Import Project="$(CompileTimeSolutionDir)ExternalDependencies\Build\MSBuild_WP7_Apr10\Vertigo.WP7.Apr10.targets" />
<!--<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.$(TargetFrameworkProfile).Overrides.targets" />-->
<!--<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />-->
7. We’re done.
Checkin to the server and as long as all files are in source control and all paths are correct the project will build on a server with no Windows Phone 7 Tools.
Setting up a new TFS Automated Build
In terms of setting up a new TFS2010 Build Definition for WP7, it’ll all plain old setup and pretty easy & straightforward.
There’s one major caveat we should call out: Make sure to set the build agent to X86.
If this step if not followed we’ll see a myriad of cryptic errors, like these ones:
If you’re interested in more information about this issue please read TFS2010 Build failed -- “Microsoft.Silverlight.Common.targets (104): The Silverlight 4 SDK is not installed” by Benjamin Day.
Summary
You can get a sample project with all the modifications discussed in this blog post @ http://JustinAngel.net/Storage/Justin.WindowsPhone.BuildFromLocalFiles.zip
Here’s a summary of the changes we needed to make in order for our project to run build successfully on a WP7-less TFS2010 Build server:
Fin
We’ve talked about why we it’s a smart move to avoid installing SDKs on our Build Server.
Additionally we’ve shown how to setup a WP7 project to run on a Build Server that doesn’t have WP7 Tools installed at all.
Hopefully this blog post will help you on your way to Continuous Integration for Windows Phone 7.
Leave a comment
What are your thoughts on this topic? Was this blog post useful?
Sincerely,
-- Justin Angel
Windows Phone 7 – Emulator Automation
Hi Folks,
In this next blog post we’ll review how to automate the Windows Phone 7 Emulator and what are some real-world usages this technique.
This blog post is the second blog post in a series of unrelated advanced Windows Phone 7 blog posts.
The previous blog post in this series is “Windows Phone 7 – Unlocked ROMs”.
Why is Windows Phone 7 Automation Important?
Currently, the Windows Phone 7 Emulator can only launch developer packages (XAPs) from inside Visual Studio 2010.
Meaning, if we’ve got a XAP we can’t get the emulator to load it without Visual Studio.
As we’ve seen in a previous blog post the emulator can be launched and even installed on machines that do not have Visual Studio. More on that here.
Let’s consider that in order to load XAPs into the Emulator we currently have to use Visual Studio.
The problem is – How do we load XAPs into WP7 Emulators and Devices without using Visual Studio?
So how does our Build Server run nightly tests? Or how do our customers see our applications?
Customers and Build servers don't have Visual Studio 2010 installed.
So, how can we deploy XAPs to an emulator running on these machines?
Quit your Jibber-Jabber, show me how to automate the WP7 emulator!
Let’s create a new solution with a Console Application and a Windows Phone 7 Project.
We’ll use the ConsoleApplication as our automation harness that can run on any computer with the .Net framework.
The WindowsPhone Application is the application whose deployment we’ll automate.
The CoreCon 10 WP7 API
The secret sauce for WP7 Automation is the CoreCon API.
These CoreCon DLLs have been in deep hibernation since 2007 when they last got a major upgrade.
For WP7 Tools the CoreCon API has been updated and are used by Visual Studio 2010 when deploying applications to WP7 devices and emulators.
Let’s add a reference to Microsoft.SmartDevice.Connectivity.dll from the CoreCon API.
On a x64 developer box, the DLL can be found at: C:\Program Files (x86)\Common Files\microsoft shared\Phone Tools\CoreCon\10.0\Bin\Microsoft.Smartdevice.Connectivity.dll
Now that we have the CoreCon DLL reference in place, we can start automating WP7.
Here’s the User Experience we’re aiming for in this demo:
We’ll have to build the following workflow:
We’ll start off by getting an instance of the WP7 CoreCon SDK instance to work with:
// Get CoreCon WP7 SDK
DatastoreManager dsmgrObj = new DatastoreManager(1033);
Platform WP7SDK = dsmgrObj.GetPlatforms().Single(p => p.Name == "New Windows Mobile 7 SDK");
Next up we’ll have to get a reference to either a WP7 physical device or a WP7 Emulator.
This demo will use the emulator, but if we set “useEmulator = false” this demo will try and connect to a physical WP7 device.
// Get Emulator / Device
bool useEmulator = true;
Device WP7Device = null;
if (useEmulator)
WP7Device = WP7SDK.GetDevices().Single(d => d.Name == "Windows Phone 7 Emulator");
else
WP7Device = WP7SDK.GetDevices().Single(d => d.Name == "Windows Phone 7 Device");
Now we’ll launch the WP7 Emulator/Device.
Note that the default WP7 Emulator Image is the one we’ll launch into, and in a previous blog post I’ve explained how to use the Unlocked ROM as the default ROM.
// Connect to WP7 Emulator / Device
Console.WriteLine("Connecting to Windows Phone 7 Emulator/Device...");
WP7Device.Connect();
Console.WriteLine("Windows Phone 7 Emulator/Device Connected...");
Next, we’ll have to check if our application is already installed, and if it is – we’ll uninstall it.
Since the the UpdateApplication Method in the current CoreCon API doesn’t work, this is our best bet on easily updating installed apps.
In order to Install or Uninstall our application, we’ll need it’s Application Product Identifier (GUID).
We can get the application GUID from the Properties/WMAppManifest.xml file.
We’ll write the code to check if an application is installed, and if it is – we’ll uninstall it.
Guid appID = new Guid("{5e75bba1-fbf6-463c-94ac-fa4a78f8fd12}");
RemoteApplication app;
if (WP7Device.IsApplicationInstalled(appID))
{
Console.WriteLine("Uninstalling sample XAP to Windows Phone 7 Emulator/Device...");
app = WP7Device.GetApplication(appID);
app.Uninstall();
Console.WriteLine("Sample XAP Uninstalled from Windows Phone 7 Emulator/Device...");
}
At this point, we’ll install our XAP.
In order to do that, we’ll need 3 pieces of information:
1. The location of our XAP.
2. The Application GUID.
3. The location of the application icon.
// Install XAP
Console.WriteLine("Installing sample XAP to Windows Phone 7 Emulator/Device...");
app = WP7Device.InstallApplication(
appID,
appID,
"NormalApp",
@"D:\visual studio 2010\Projects\ConsoleApplication1\WindowsPhoneApplication1\ApplicationIcon.png",
@"D:\visual studio 2010\Projects\ConsoleApplication1\WindowsPhoneApplication1\Bin\Debug\WindowsPhoneApplication1.xap");
Console.WriteLine("Sample XAP installed to Windows Phone 7 Emulator...");
The last step is to actually launch our application.
// Launch Application
Console.WriteLine("Launching sample app on Windows Phone 7 Emulator...");
app.Launch();
Console.WriteLine("Launched sample app on Windows Phone 7 Emulator...");
We’re done. And indeed when we run our sample application the app runs as expected:
So What is WP7 Automation good for?
There’s a lot of good use cases: Automating Unit tests, Loading Nightly builds into the emulator and even letting customers use the WP7 Emulator.
There’s really a plethora of reasons and situations WP7 Automation can prove useful in and it’s up to you to figure it out for your projects.
For instance in Vertigo, we’re using the WP7 Automation harness to run the WP7 Emulator on multi-touch laptops that our customers have.
So Vertigo’s customers, as part of an iterative process, get access to our current build without having to install or use Visual Studio 2010.
Access to Isolated Storage
One use-case in particular interests me, which is automating running all unit tests in the project after a Continuous Integration nightly build.
We can pretty much do all of the work to automate WP7 tests using WP7 Automation we’ve seen so far, but how do we get results into application? Or get instructions in?
The easiest method I can think off is communicate through cold storage – read & write files into Isolated Storage.
We’ll start off by writing a file into our WP7 Application IsoStore.
Remember that this code executes in the WP7 Emulator/Device.
public MainPage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
using (var sw = new StreamWriter(isoStore.OpenFile("Foo.txt", FileMode.OpenOrCreate, FileAccess.Write)))
{
sw.Write("Hello WP7! (Written from WP7 IsoStore, read by Console Harness!)");
}
}
Basically, We’ve written a Foo.txt file into our IsoStore and added some text into it.
Next, we would have used the RemoteIsolatedStorage class and get access to the emulator IsoStore, but that has not been enabled yet in CoreCon10.
We would have used RemoteApplication.GetIsolatedStorage() but that has not been implemented yet.
We’ll use a FileDeployer class instead.
There’s some reflection magic associated with getting a copy of a FileDeployer class that can be used for our application.
Thread.Sleep(10000);
//app.GetIsolatedStore(); <-- Throws NotImplementedException
object ConManServer = WP7Device.GetType().GetField("mConmanServer", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(WP7Device);
FileDeployer f = (FileDeployer)typeof(FileDeployer).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0].Invoke(new object[] { ConManServer });
Next, we’ll copy the Foo.txt file from the application isolated storage into our local binary folder and read it into the console:
f.ReceiveFile(@"\Applications\Data\" + appID + @"\data\isolatedstore\Foo.txt", @"\Foo.txt");
Console.WriteLine("\t" + File.ReadAllText(@"foo.txt"));
When we run this sample we can see the text written from IsoStore showing up on our console.
And we’re done, we’ve esteblished a two-way communication channel between WP7 Emulator/Device and Managed .net code.
Console WP7 Automation Harness Source Code
Here’s the source code we’ve built in this project:
// Get CoreCon WP7 SDK
DatastoreManager dsmgrObj = new DatastoreManager(1033);
Platform WP7SDK = dsmgrObj.GetPlatforms().Single(p => p.Name == "New Windows Mobile 7 SDK");
// Get Emulator / Device
bool useEmulator = true;
Device WP7Device = null;
if (useEmulator)
WP7Device = WP7SDK.GetDevices().Single(d => d.Name == "Windows Phone 7 Emulator");
else
WP7Device = WP7SDK.GetDevices().Single(d => d.Name == "Windows Phone 7 Device");
// Connect to WP7 Emulator / Device
Console.WriteLine("Connecting to Windows Phone 7 Emulator/Device...");
WP7Device.Connect();
Console.WriteLine("Windows Phone 7 Emulator/Device Connected...");
Guid appID = new Guid("{5e75bba1-fbf6-463c-94ac-fa4a78f8fd12}");
RemoteApplication app;
if (WP7Device.IsApplicationInstalled(appID))
{
Console.WriteLine("Uninstalling sample XAP to Windows Phone 7 Emulator/Device...");
app = WP7Device.GetApplication(appID);
app.Uninstall();
Console.WriteLine("Sample XAP Uninstalled from Windows Phone 7 Emulator/Device...");
}
// Install XAP
Console.WriteLine("Installing sample XAP to Windows Phone 7 Emulator/Device...");
app = WP7Device.InstallApplication(
appID,
appID,
"NormalApp",
@"D:\visual studio 2010\Projects\ConsoleApplication1\WindowsPhoneApplication1\ApplicationIcon.png",
@"D:\visual studio 2010\Projects\ConsoleApplication1\WindowsPhoneApplication1\Bin\Debug\WindowsPhoneApplication1.xap");
Console.WriteLine("Sample XAP installed to Windows Phone 7 Emulator...");
// Launch Application
Console.WriteLine("Launching sample app on Windows Phone 7 Emulator...");
app.Launch();
Console.WriteLine("Launched sample app on Windows Phone 7 Emulator...");
Console.WriteLine("Reading Foo.txt Isolated Storage file:");
Thread.Sleep(10000);
//app.GetIsolatedStore(); <-- Throws NotImplementedException
object ConManServer = WP7Device.GetType().GetField("mConmanServer", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(WP7Device);
FileDeployer f = (FileDeployer)typeof(FileDeployer).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0].Invoke(new object[] { ConManServer });
f.ReceiveFile(@"\Applications\Data\" + appID + @"\data\isolatedstore\Foo.txt", @"\Foo.txt");
Console.WriteLine("\t" + File.ReadAllText(@"foo.txt"));
Console.ReadLine();
Fin
In this blog post we’ve talked about why Automating the WP7 Emulator and Device deployment process is important and how to go about doing that.
Hopefully now you know how to automate WP7 XAP Deployment.
In the next blog post in this series we’ll talk about setting up a Continuous Integration build for WP7.
Leave a Comment
Are there any other use cases for WP7 Automation?
Are you planning on using this technique somewhere?
Was this a good blog post? Sound off in the comments.
Sincerely,
-- Justin Angel
Windows Phone 7 – Unlocked ROMs
Hi Folks,
In the following blog post we’ll review a topic which has been widely discussed in mainstream tech journalism but languishes in obscurity within the WP7 developer community.
I am of course talking about the Windows Phone 7 Unlocked ROMs.
Prior to starting this blog post, I’d like to call out this is the 1st blog post in a series of multiple advanced Windows Phone 7 blog posts.
Additional subsequent blog posts will include Windows Phone 7 Emulator Automation, Windows Phone 7 and TFS2010 Continuous Build integration and other topics.
I’ve been told on many occasions that blog posts should be shorter than 50 pages (nonsense if you ask me), so I’ve split up this massive Advanced Windows Phone 7 blog post into several short blog posts.
What’s in a ROM?
From Wikipedia:
“A […] ROM, is a computer file which contains a copy of the data from a read-only memory chip, often […] a computer's firmware.”
It’s vitally important that Windows Phone 7 developers realize that the Windows Phone Emulator is in fact not powered by magical Microsoft pixies. I’ve checked.
The WP7 Emulator is in fact a mix between a virtualization software known as “XDE” (“Emulator Virtual TransportDevice“) and an Image.
Both XDE and the Image change with each public build Microsoft ships for WP7.
Since Microsoft only shipped the Image for development purposes there is limited functionality enabled in them. Specifically: Custom Application support, and Internet Explorer for HTML support.
Through the ingenious work of Dan Ciprian Ardelean and numerous other XDA developers the various Images have been fully unlocked:
Compare and contrast these Print screens of the WP7 home screen from the locked ROM and the Unlocked ROM.
In this blog post I intend to show the benefits of the Unlocked ROMs for developers.
If this is the first time you’ve heard about the unlocked ROMs and want to see what they offer, there’re great resources online.
How do I get these unlocked ROMs?
It’s important to mention there are currently 2 Unlocked ROMs:
1. The 6077 build – Also known as the Mix10 WP7 ROM. Has unlocked Zune Marketplace functionality, lots of apps which has been dropped since and terrible performance.
2. The 6177 build – Also known as the April10 WP7 ROM. Has unlocked Office, lots of new functionality that has lighten up since Mix10 and considerably improved performance.
And there will probably be many more of these Unlocked ROMs as Microsoft ships more and more public bits for WP7.
Both of these work Side-by-side on the latest XDE emulator:
The Mix10 WP7 ROM is available at http://www.multiupload.com/H6IIOZKEMX. (Copied from XDA developers thread)
The April10 WP7 ROM is available at http://www.multiupload.com/POF771XDFD. (Copied from XDA Developers thread)
To fire up the images copy the 2 BIN files into the XDE folder and execute them using the XDE emulator.
The XDE folder on a x64 machine is located at: C:\Program Files (x86)\Microsoft XDE\1.0
If your development machine does not have the latest Windows Phone 7 SDK installed, fear not, you can still install XDE as a stand-alone product.
Instructions can be found at this excellent post by MacHackPC.
How to replace the default Visual Studio ROM with the Unlocked ROM?
When debugging in Visual Studio the default ROM used will be the Locked ROM.
In this blog post we’ll explore why the unlocked ROM is so darn useful for developers when debugging applications.
In order to use the unlocked ROM as the default for VS2010 debugging:
1. Simply open up the default WP7 SDK Directory
2. Drop in the April10 Unlocked ROM BIN file
3. And rename it to “WM70C1.bin”
On a x64 machine the WP7 SDK Directory is located at: C:\Program Files (x86)\Microsoft SDKs\WindowsPhone\v7.0\Emulation\Images

By replacing the original WM70C1.bin file with our unlocked ROM, Visual Studio 2010 will now open up the unlocked ROM for debugging.
Why should developers care about the Unlocked ROM?
There’s a plethora of reasons why the unlocked ROM is important for application develoeprs. Let’s go over them .
Advantage #1: Developers can see the native Look & Feel of WP7
The WP7 UI is not just a fancy version of “desktop” Silverlight 3 UI.
There are different patterns of user experience, different controls used and wildly divergent visual conventions.
Developers who build entire WP7 applications without even trying to use the platform will end up building atrocious user experiences.
Panorama Control Switching between screens (Office)

Line-Of-Business Form for creating new appointments:
Pivot Control: (Contacts page)
There’s a lot of subtle details in how WP7 UI and UX work, and as developers on this brand new platform we should endeavour to fully understand it so we can recreate it in our applications.
For more information on WP7 UX feel free to read the weighty Windows Phone 7 Interaction and UI Guidelines.
Reason #2: All Tasks have been enabled
WP7 has quite a few tasks and choosers that allow developers to interact with various built-in phone functionality.
The majority of these tasks are enabled in the Unlocked WP7 ROM.
Let’s review each of these tasks and choosers, how to invoke it and what’s the UX in the April 2010 Unlocked ROM.
Invoking CameraCaptureTask
new CameraCaptureTask().Show();
Invoking EmailAddressChooserTask
new EmailAddressChooserTask().Show();
(I’ve staged “Foo” and “Bar” contacts to give this dialog some substance).
Invoking EmailComposeTask
new EmailComposeTask()
{
To = "J@JustinAngel.net",
Subject = "Seriously?",
Body = "They actually pay you to develop for Windows Phone 7? Cool!",
Cc = "fake@Vertigo.com"
}.Show();
Invoking MarketplaceLauncher
MarketplaceLauncher.Show(MarketplaceContent.Music,
MarketplaceOperation.Search,
"Foo Fighters");
It is likely to assume that the MarketplaceLauncher task will be enabled in subsequent releases.
Invoking MediaPlayerLauncher
new MediaPlayerLauncher()
{
Media = new Uri(@"http://ecn.channel9.msdn.com/o9/ch9/4/1/9/7/4/5/WPMetroDesignOverivew_ch9.wmv"),
Controls = MediaPlaybackControls.All
}.Show();
Invoking PhoneCallTask
new PhoneCallTask()
{
DisplayName = "Hello World",
PhoneNumber = "123 456 789"
}.Show();
Invoking PhoneNumberChooserTask
new PhoneNumberChooserTask().Show();
It’s likely to assume this error would be fixed in subsequent versions.
Invoking PhotoChooserTask
new PhotoChooserTask()
{
ShowCamera = true,
PixelHeight = 640,
PixelWidth = 480
}.Show();
Invoking SaveEmailAddressTask
new SaveEmailAddressTask() { Email = "J@JustinAngel.net" }.Show;
Invoking SavePhoneNumberTask
new SavePhoneNumberTask() { PhoneNumber = "123 456 7890" }.Show();
Invoking SearchTask
new SearchTask() { SearchQuery = "Windows Phone 7 prototypes, one for Shazam and one for Netflix" }.Show();
Invoking WebBrowserTask
new WebBrowserTask() { URL = "http://www.vertigo.com/Mobile.aspx" }.Show();
Reason #3: Windows Phone 7 Task Manager
The Windows Phone 7 System Info provides useful insight for developers on how their applications are behaving.
Opening SystemInfo and the Task Manager View
Details Summary view + Terminate Button
Threads and Heaps (Gen0, Gen1, Gen2, Gen 64k+) screens
Allocations and modules screens
Reason #4: Local Files and IsoStore View
Using the Shortcuts application developers can view their installed XAP files and IsoStore files.
Let’s start this demo off by writing a “Foo.txt” & “Foo.html” files into our main Isolated Storage directory.
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
using (var sw = new StreamWriter(isoStore.OpenFile("Foo.txt", FileMode.OpenOrCreate, FileAccess.Write)))
{
sw.Write("Hello WP7!");
}
Open up Shortcuts application and set “Show All Files”
Navigate to the “\Applications” Local Device Path
Viewing the contents of an Installed XAP
Opening files installed in the XAP and inspecting them on the device
Opening the Isolated Storage for our application

Fin
In this short blog post we’ve introduced the concept of Unlocked WP7 ROMs, how to best use them and what functionality they have to offer developers.
Specifically, they allow experimenting with native look & feel, using the built-in WP7 tasks, using0 the platform’s Task Manager and exploring local storage.
In subsequent blog posts we’ll talk about how to automate the Windows Phone 7 Emulator, Setup TFS2010 Windows Phone 7 Continuous Integration and other secrets the unlocked ROMs has to share with us.
Leave a Comment
Feel free to leave a comment with your take on the Windows Phone 7 Unlocked ROMs.
Sincerely,
-- Justin Angel
Silverlight 5 Future Features
Hi Folks,
I’d like to share with you some of the top issues that could be included in Silverlight 5 and get your perspective on them.
The full list of possible features can be found on UserVoice.
This is not meant to be a compressive list of possibilities or an official Microsoft document. These are just interesting highlights from the above mentioned list.
Possible Silverlight 5 Feature #1: More Platform Reach
When talking about “reach” there are a few interesting dimensions:
1) Silverlight Browser Support: Silverlight currently only officially supports Internet Explorer, FireFox, Chrome and Safari. Support could be extended to Opera or other less prominent browsers.
2) Operating System: Silverlight is currently limited in the Mobile space (No Symbian support yet) and in the Gaming Console space.
3) CPU Architecture: Silverlight doesn’t support x64 CPUs, Mac G4 PowerBook CPUs, and a few other CPU architectures.
If you think extending Silverlight’s Platform Reach is important vote on this issue @ Implement Silverlight on more platforms
For Silverlight on the iPhone vote @ Get Silverlight on the iPhone
Possible Silverlight 5 Feature #2: 3D support
In the future Silverlight could more effectively support 3D user scenarios.
There are a plethora of 3D use cases starting at 3D Modeling, 3D gaming and 3D Virtual World design.
Personally, I do not believe Microsoft should build another 3D framework.
What I’d like to see the Silverlight Team do is enable success in the multitude of Open Source Silverlight 3D projects.
Such projects include Balder by Einar Ingebrigtsen for advanced 3D modeling, Matrix3DEx by Rene Schulte for 3D space design and Kits3D by Mark Dawson for WPF-Compat 3D API.
However, the existing projects are struggling with rendering performance issues, offloading computation to the GPU and UI virtualization. All missing from Silverlight 4.
If you’d like to see Silverlight have better support for these 3D projects or just to have a better native story for 3D please vote @ 3D Support.
Possible Silverlight 5 Feature #3: Bundle Silverlight with Windows
At Mix10 Microsoft VP Scott Guthrie announced Silverlight Adoption rate is at 60% of all internet connected machines.
In the future, we could hope to see Microsoft bundle Silverlight with Windows or add it as a super-duper-should-have update to Windows Machines.
If you’d like to see this feature implemented vote @ Bundle Silverlight with Windows so that it will always be available
Possible Silverlight 5 Feature #4: Improved WriteableBitmap API
The in-memory drawing API in Silverlight is somewhat limited for advanced tasks, like:
1) No API for Drawing Shapes.
2) No API for Resizing & Rescaling.
3) No API for Clear, Copy & Crop methods.
4) No API for Conversion to various formats.
5) Performance issues that plague any “1 pixel, 1 read/write” approach.
In future versions of Silverlight we might see these features or other in-memory drawing features implemented.
If you’d like to vote on that please do so @ Enhance the rendering bitmap API
In the meanwhile Rene Schulte has a Silverlight open source project named “WriteableBitmapEx” that enables some of these scenarios.
Possible Silverlight 5 Feature #6: Store File Permissions Granted by the User
Using the OpenFileDialog and SaveFileDialog end-users can respectively grant read and write permissions for any file to a Silverlight Application.
Developers would like to see these permissions persist after the application has been restarted.
We can see in Silverlight 4 RTM that Full Screen, Webcam and Clipboard access already get persisted after application restart.
So it’s not unreasonable to hope this feature will be included in future Silverlight versions.
If you’d like to see this feature implemented please vote @ Make FileInfo class serializable
Possible Silverlight 5 Feature #7: Add PLINQ and TPL support
In .Net 4.0 Parallel LINQ (PLINQ) and Task Parallel Library (TPL) have been introduced.
With PLINQ & TPL creating, debugging and maintaining multi core applications has been massively simplified on the .Net framework.
Read more about PLINQ and TPL at @ Visual Studio 2010 + .NET 4.0 = Parallelism for the Masses.
With Silverlight supporting C# 4 and a majority on new .Net 4.0 features, it is possible we’ll see PLINQ and TPL in future Silverlight versions.
That would allow Silverlight to have the best in-browser threading solution for any major programming platform.
If you would like to see this feature implemented vote for it @ PLINQ and TPL
Possible Silverlight 5 Feature #8: Reporting Controls and SQL Reporting Services Integration

Microsoft has a great suite of Reporting and Analysis tools that are part of the SQL Server 2008 product group.
As part of ASP.Net and winforms there are ReportViewer controls that allow to view, zoom, page and export from predefined RDLS reports.
If this feature is implemented it would probably include a new Silverlight & WPF <ReportViewer /> control as well as deep SQL Server Reporting Services integration.
In the meanwhile Perpetuumsoft has a commercial 3rd party component that might help you out.
If you’d like to vote for this feature please do so @ Add Report Controls
Possible Silverlight 5 Feature #9: Media Playback Speed
As part of the a user workflow some users watch or listen to media at high speeds.
The Silverlight MediaElement however does not support variable play speed. The WPF property MediaElement.SpeedRatio is missing.
It’s reasonable to assume Microsoft has heard this feature request many times and might be considering it for future Silverlight versions.
If you’d like to see this feature implemented please vote @ Media Playback variable speed/rate
Possible Silverlight 5 Feature #10: Better Full Screen Support
Quotes from Full-Screen Support article on MSDN.
Silverlight Full Screen mode disables support for some key features in the Silverlight platform.
It is possible that in future Silverlight releases we’ll see some of these issues fixed.
We could see a Silverlight application in full screen mode with a security prompt to enable full keyboard input. Vote for this feature @ Full Screen with Full Keyboard Support
We could see a Silverlight application in full screen mode providing Multi-touch events.
We could see a Silverlight application in full screen mode enable the <WebBrowser> control so applications could integrate HTML content in Full Screen.
Other Silverlight Platform Feature Requests
A lot of other people would like to see a lot of other features implemented in future Silver light versions, here’s a shout-out to a few of them:
Fin
There are a myriad of other possible Silverlight features up on UserVoice for you to choose from.
See the full list @ Silverlight Feature Suggestions
If you’d like to make your voice heard leave a comment or better yet open up a new UserVoice issue.
The important thing is that you keep pushing for the features you’re interested in and let Microsoft know what’s important for you.
So go vote! Vote on Silverlight vNext Features
Sincerely,
-- Justin Angel
Joining the Vertigo Team!
Hi Folks,
I’ve got big news!
If you don’t already know I’ve left my position as Microsoft Silverlight Program Manager.
Working for Microsoft is a once in a lifetime experience and I’ve gained friends for life while helping ship Silverlight, the Silverlight SDK, the Silverlight Toolkit, Expression Blend and Visual Studio.
This week I’ve joined the notorious Silverlight company – Vertigo [twitter feed].
The rest of this blog post is basically a very long winded way of saying “Wow, Vertigo rocks.”
Vertigo? What’s that?
Vertigo is a San Francisco Software company code ninja collective bent on world domination aiming to produce top notch interactive experiences in modern application development platforms.
Well, technically that is. And “Technically” carries a lot of weight around here.
Who works at this “Vertigo” of yours?
A few big ticket names actually, and lots of amazingly smart and competent developers, visual designers, BizDev folks and managers.
Bill “I just pioneered Silverlight gaming, no biggie” Reiss
Bill’s fame proceeds him. He’s the Silverlight MVP and Book Author that’s been doing Silverlight Game Development since before Silverlight existed.
Check out Bill’s blog here or catch up with him up on twitter. Bill’s actually responsible for me joining up with Vertigo, so give him a big round of applause.
Alan “Will It Blend?” Le
Alan has been a pillar of the WPF community for years, an avid twitter personality and a top notch devigner for as long as I can remember.
Check out Alan’s blog and his twitter feed.
Scott “You’ve seen me at conferences” Stanfield
Scott’s the Microsoft Regional Director for San Francisco, is a frequent PDC/Mix conference speaker and a pillar of the local .Net community.
Follow Scott up on twitter or watch one of his many MIX / PDC presentations.
Kevin “I Smurf, You Smurf, We all Smurf together” Rohling
Kevin’s the guy behind Microsoft Silverlight Media Framework V2 which is the most comprehensive Silverlight Media Player out there.
Follow Kevin up on twitter.
Justin “I have a Silverlight and I’m not afraid to use it” Angel
Ok, Granted, that’s me. And you probably know who I am. But hey, I’m with Vertigo now.
There are lots more awesome Veirtgoers who I haven’t had space to mention – check them out at our people's page.
All of whom are amazingly talented, fiendishly smart and a few are even extremely well dressed.
What do you build at Vertigo?
Oh, nothing much.
The Silverlight Olympics Player [read more]
2009 Presidential Inauguration - Silverlight HD Broadcast [read more]
Hard Rock Memorabilia [read more]
Guided Rocket Missile Systems powered by Silverlight, WPF and Surface Ninjas.
OK, those – we don’t build these.
But If we put our minds to it, we might.
PDC / Mix Event Web Sites
Windows Marketplace [read more]
Vertigo’s has had a hand in lots of high profile innovative applications, and you can read all about them on our projects page.
And what about you Justin?
Well, I’m starting on a new Windows Phone 7 project here at Vertigo.
One of my cohorts will be Bill Reiss, which is a dream come through for me.
I get to work on a WP7 project with a pillar of the Silverlight Community – Woo Hoo!
Fin
I’ve left Microsoft and joined Vertigo. Wish me luck.
Seriously, wish me luck.
Sincerely,
-- Justin Angel
Former Microsoft Silverlight Program Manager, now with Vertigo.
Silverlight Isn’t Fully Cross-Platform
Hi Folks,
In this article I’d like to go over some well-known Silverlight divergent behaviours between Windows and Mac.
Cross Platform? What’s that?
Previous .Net UI frameworks like WPF & WinForms were mostly limited to running exclusively on Windows machines.
Silverlight differs from WinForms & WPF in that it runs primarily in the browser and works on multiple operating systems.
From the history of web development (especially from Javascript) we all recognize the importance of writing code that runs on multiple browsers and operating systems.
The Misconception – Silverlight is 100% Cross Platform
Confused? Perplexed? Bewildered? Get a hold of yourself and be a man.
It is often said in Silverlight books, articles and presentations world-wide that “Silverlight is Cross Platform”.
It’s quite easy to see why when first introducing Silverlight speakers don’t immediately go “Well, sort of Cross Platform” or reserve themselves by saying “mostly cross-platform that is.”
Let’s look at some definitions for “Cross Platform”:
- “[…] capability of software to run identically on different platforms […]” – Source
- “Of software, etc., designed to work on various operating systems” - Source
Silverlight is in fact not fully cross platform.
In that strict sense of the definition, Silverlight does have some places where it behaves differently for different operating systems.
There’s a small, yet important, list of differences in how code executes on a Mac and on a Windows machine.
This article is only sourced from MSDN
Every factual statement about a Windows-to-Mac difference that is listed in this article will be quoted directly from MSDN.
I’ve compiled this list based on the following Bing search: site:msdn.microsoft.com/en-us/library Silverlight AND ("Mac" OR "Macintosh" OR "OS X")
I will not be using my personal working experience with Silverlight, or my experience having worked at Microsoft, or any knowledge gained at Microsoft, or any external 3rd party evidence. This article is strictly sourced from official Microsoft Silverlight documentation.
Difference #1: WindowLess is always True
Category: Plugin Browser Integration
“For Windows, you can display a browser-hosted Silverlight content area in either a windowed mode or a windowless mode. For Windows, the default is a windowed mode.
For Macintosh, there is no windowed mode. The mode is always windowless regardless of the Windowless setting.” - MSDN
While on a Windows Machine, you can choose to have WindowLess=False, that state just isn’t available on a Mac.
Which sounds pretty harmless, until we run into issues like this one:
“if Silverlight is running on a Macintosh computer (where windowless mode is always active, regardless of theWindowless setting), the Background property value can specify an alpha value for the color.” – MSDN
If we were to specify an <object> background property with opacity and WindowLess=False, it would still be transparent on a mac.
While on a Windows machine, the background would look perfectly solid.
That would cause a performance hit on a Mac, while leaving Windows machines completely unaffected.
This issue might be especially important since visual properties like background might be set by designers, and not developers.
Difference #2: Different System.Net.Sockets Stack
Category: Coding difference
“On Windows, the System.Net.Sockets namespace provides a managed implementation of the Windows Sockets (Winsock) interface.
On Apple Mac OS X, the System.Net.Sockets namespace provides a managed implementation of the sockets interface based on Berkeley Software Distribution (BSD) UNIX.” - MSDN
The Silverlight Sockets implementation uses different O/S features to implement it’s sockets support.
Perfectly sensible approach, but that might cause some divergent coding differences between Mac and Windows. Like this one:
“On Mac OS X, this property controls how many bytes can be in the network stack's waiting-to-be-sent buffer before additional calls to the BeginSendToGroup or BeginSendTo methods start failing. Applications on Mac OS X may need to be concerned with this property if they are sending a large number of UDP packets in a short timeframe.
On Windows, calls to the BeginSendToGroup or BeginSendTo methods will take longer to call the callback depending on the value of the SendBufferSize property if the send buffer is full. The SendBufferSize property only controls whether the user's buffer stays locked in physical memory until the send completes.” - MSDN on UdpAnySourceMulticastClient.SendBufferSize Property
With the UdpAnySourceMulticastClient.SendBufferSize Property we can see some wildly divergent networking behaviour between Windows and Mac.
This should cause developers to revaluate how you use the SendBufferSize property, and BeginSendTo & BeginSendToGroup methods.
Difference #3: Different source for HighContrast mode
Category: Different O/S UX
“On computers that run Windows, the HighContrast property is true when the user has enabled High Contrast in Control Panel. On Macintosh computers, HighContrast is true when the user has selected the White on Black option in Universal Access.” - MSDN
It’s important to note that Macs do not have a “High Contrast” mode but rather they have a “Black on white” mode.
When providing instructions to end-users on how to enable HighContrast mode for an application, it’s important to remember these differences.
Difference #4: Different Exception details
Category: Debugging
“There are known issues with reported line offsets when a XamlParseException occurs on a Macintosh client. Line numbers/positions on other clients are more accurate.” – MSDN
When debugging on a Mac or when users are sending application error reports, developers might see the XamlParseException.
However, if the exception arises from a Macintosh the Line number and Column positions might be all wrong.
Difference #5: HtmlPage.Window doesn’t equal itself
Category: Coding difference
- MSDN
When comparing HtmlPage.Window to itself, there are different results on a Windows machine and on a Mac machine.
Difference #6: MessageBox will always have an Icon
Category: UX Difference
“The message box may have a slightly different appearance on different platforms. For example, the message box includes an icon when it is displayed on a Macintosh.” – MSDN
Based on this MSDN excerpt even when invoking MessageBox.Show even without an Icon, Mac will always display an Icon.
While Windows machines will not show any icon.
This may be an important difference for applications when visual consistency is an important factor.

Difference #7: Cross-Zone networking security restrictions
Category: Security Restriction Differences.
“Cross-zone URL: Internet Explorer defines the concept of security zones with a security level assigned to each zone. Four zones are defined: Internet, Local intranet, Trusted sites, and Restricted sites. In addition, the local machine is also considered to be another zone. A Silverlight application downloaded from a web server in one security zone tries to access resources on a target server in a different security zone. Cross-zone access restrictions are designed to prevent a Silverlight application downloaded from a server in the Internet zone from accessing resources in the more trusted Local Intranet, Trusted Sites, and local machine zones. This prevents a Silverlight application run from a remote internet server from getting access to resources on the local intranet and other resources (an elevation of privilege). Cross-zone access is blocked even if a security policy file on the target server would allow the resource to be accessed. Note that cross-zone access is not restricted for applications downloaded from the server in the Local intranet zone to resources on an internet server. However, any access cross-domain requires a security policy file. Cross-zone access restrictions are implemented only for Silverlight 2 and later applications running on Windows.
The concept of security zones and cross-zone access is not currently supported for Silverlight applications running on the Apple OS X.” – MSDN
There are 2 types of Cross-X networking restrictions:
1) Cross-Domain: The famous restrictions developers know and love from clientaccesspolicy.xml. Based on a comparison of site-of-origin and the location of the remote networking resource.
2) Cross-Zone: A restriction based on the zone-of-origin (internet, intranet, trust or local) an application was downloaded from and which zone a network resource is located in.
While Cross-Zone is less familiar to most of us, it is by no means less important.
However, on a Mac the cross-zone restrictions don’t take place, either by being fully blocked or by being fully allowed.
- MSDN
The above chart illustrates rather effectively which cross-zone interactions are allowed on Windows Machine. But as MSDN says, that is not the case for Mac.
If an application uses Cross-Zone networking it is important to make sure those work in a Macintosh environment.
Difference #8: Silverlight 4 Drag & Drop
Category: Coding Difference, Missing Feature on Mac
“To handle drag-and-drop events for applications hosted by Safari browser on the Macintosh, you must forward the relevant HTML DOM events to the specific handler in Silverlight” – MSDN
When implementing code that handles the new Silverlight 4 Drop/DragX event sit is important to know that the events will not fire on Mac by default.
There is special HTML & Javascript code that needs to be included to assure that Silverlight 4 Drop support in enabled on a mac.
“The forwarding technique described for Safari might not work for Firefox.” - MSDN
However, even with this change Silverlight 4 Drop support might not work on Macintosh FireFox.
Difference #9: Uris
Category: Coding Difference
- MSDN
It is vitally important to know that when doing any parsing work with the Uri Class, it’s properties will behave differently on different operating systems.
Difference #10: BCL classes
Category: Coding differences
The following table lists out some common Base Class Library differences between Windows and Macintosh:
- MSDN
Difference #11: Exiting Full Screen Keystrokes
Category: UX difference
“A Silverlight plug-in that is in full-screen mode can return to embedded mode in several ways. The simplest way to leave full-screen mode is for the user to enter a keystroke or keystroke combination:
Windows users should press ESC or ALT+F4.
Macintosh users should press ESC.” – MSDN
When exiting full-screen mode back to normal browsing mode, the “Alt + F4” keystroke combination will only work in Windows.
If an application provides guidance for users on how to exit full-screen mode, it might be best to limit it to “Press ‘Esc’ to exit full screen mode” or some such similar message.
Users who have previously used the ALT+F4 combination on the application when running on Windows, could be somewhat confused to see it’s disabled on a Mac.
Difference #12: Silverlight 4 COM Automation
Category: Missing Feature on Mac
“Trusted applications can integrate with native functionality that differs depending on the host operating system. For example, on Windows, trusted applications can interoperate with Automation APIs through the AutomationFactory class.” - MSDN
The new Silverlight 4 Operating System Automation features are currently only enabled on Windows.
While going from Silverlight 4 Beta and Silverlight 4 RC the class has been renamed from “ComAutomationFactory” to “AutomationFactory”. Signalling that Macintosh might be supported for this feature in the future.
Either way, as of Silverlight 4 RC there appears to be no way to use the multitude of features offered by Silverlight 4 Automation on a Mac.
“A ha! A Microsoft Conspiracy!”
At this point some of you might be thinking to yourself “ah ha! A microsoft conspiracy! I have proof!” or some such nonsense. That’s wrong, cut it out.
These same differences would realistically have to exist in one form or another in other RIA platforms such as Flash and JavaFX.
A common trend amongst all the differences we’ve surveyed in this article is that they’re all to do with deep Operating System Integration or Browser Integration. These are either issues with the operating system or the browser itself.
Remember that .Net at it’s core is just a framework abstraction on top of the O/S.
And as anyone who’s ever written a framework knows, some differences cannot be abstracted away.
In my opinion, a lot of these differences are issues that at the end of the day just requires developers to be alert.
Most of these differences aren’t in the Silverlight UI rendering itself, but more towards O/S integration or Browser integration.
Be aware of these issues and work to avoid them.
What can Microsoft do? Option #1 - Developer Education
I have yet to see a Silverlight presentation that mentions that there are differences between Silverlight on Windows and Silverlight on a Mac.
It always saddens me to see YetAnotherConference(TM) that doesn’t mention this topic at all.
Maybe there could be a PDC/Mix/DevDays/WhateverConference session called “Silverlight differences between Windows and Mac”?
While it’s definitely not in anyone’s best interest to point out Silverlight isn’t fully cross-platform, it’s better to educate developers then pretend it is.

Another good avenue for developer education is through MSDN articles.
While there is a MSDN article titled Silverlight Differences on Windows and the Macintosh it is minimal and does not contain most examples found elsewhere on MSDN and others that must surely exist. It is imperative that Microsoft properly documents these non Cross-Platform issues in a central location.
What can Microsoft do? Option #2 - Visual Studio Warnings
Another more proactive route Microsoft might choose to follow on this issue, is to encapsulate all of the Cross-Platform differences into FxCop / Code Analysis rules.
Those rules would execute whenever a developer builds an application and would provide immediate feedback on code that might behave differently on various platforms.

Creating such Build Warnings appears to be an integral part missing from the Silverlight developer experience.
The mono team might even choose to do the same in order to help developers build truly cross-platform applications.
What should developers do? Option #1 – Educate ourselves
There’s nothing wrong with saying “I’m not familiar with this topic” and reading about it.
If up until you’ve read this article you’ve thought Silverlight is 100% cross-platform, maybe your colleagues do to?
What should developers do? Option #2 – Report bugs to Microsoft
If you come across other issues/bugs that break cross-platform behaviour in Silverlight, make sure to report it to Microsoft.
The “Connect” system allows you to report bugs to microsoft and follow up to make sure they’re fixed.
Report bugs on Connect @ http://tinyurl.com/SilverlightBug
What should developers do? Option #3 – Automated Nightly Tests
Writing tests and running them on nightly on both Windows and Macintosh is a recommended practice.
There’s quite a bit of infrastructure work involved, and if you don’t know how to test there’s a steep learning curve.
But having automated tests that execute nightly is the best thing we can do to help ourselves spot these issues early.

If you’re not familiar with Silverlight Unit Testing I’d suggest the following article @ SILVERLIGHT UNIT TESTING, RHINOMOCKS, UNITY AND RESHARPER.
Statlight is a dedicated Silverlight Unit Testing Automation tool by Jason Jarrett that also comes in very handy when automating Silverlight Tests @ http://statlight.codeplex.com/
As of November 2009 it is possible to execute Silverlight Unit Tests from the command line prompt, see Jeff Wilcox’s post @ Walkthrough: The power of the November 2009 Silverlight Toolkit testing tools
Fin
In this article we’ve talked about the common misconception that Silverlight is fully Cross-Platform.
We’ve seen many examples from MSDN that clearly state Silverlight is not fully Cross-Platform.
And we’ve gone over what we as Developers should do to overcome this issue, and what Microsoft can do to help.
I’d love to hear your thoughts in the Comments on this issue.
I’d also like to thank David Gadd, Chris Walsh and Kelly White for providing feedback on this article before it was published.
Sincerely,
-- Justin Angel
“Advanced MVVM” Book Review
Hi Folks,
I recently bought a copy of Josh Smith’s new self-published book “Advanced MVVM” and I’d like to share with you my impressions.
For those of you in a hurry, I’ll conclude my thoughts here.
If you’re looking into learning MVVM or enriching your understanding of MVVM, Don’t buy the first edition of this book.
This book is god-awful bad.
I Love Josh!
The Silverlight & WPF community is a very tight-knit group of super community ninjas.
Personally, I adore Josh and hold him in the highest possible respect as a professional colleague.
Josh’s blog is amazing and he’s known to share some profound revelations on the WPF Disciples mailing list.
Let me make this abundantly clear: Josh is awesome. This book isn’t.
This review ignores Josh’s radiating awesomeness and focuses solely on this atrocious book.
Mistake #1: The Wrong Problem Domain – Gaming?
Generally speaking, all Silverlight & WPF applications will fall into one of the following categories: Games, Media and LOB (Line of Business).
There are definitely more categories then these basic three, but those three are assuredly the majority of applications out there.
Most applications out there are going to be LOB apps.
Most MVVM developers are going to be LOB developers.
So why is this MVVM book about using a Game as the Sample Application?
Over here you can see a print-screen of the sample application developed in this book:
It’s fundamentally wrong to base an entire MVVM book on a game.
There’s so much game related minutia in this book, that it’s easy to get distracted and forget the book is about MVVM.
Realistically almost 50% of this book is gaming plumbing and not about MVVM.
To highlight this point even further: This entire codebase doesn’t have a single <TextBox />.
How many of you find an application without a TextBox relevant to your day to day coding?
Mistake #2: Not even a good Games Tutorial
Developers reading this book will have to trudge through dozens of code snippets relating to Gaming application architecture.
One would at least expect that code to be useful and relevant as a gaming tutorial. But it’s not.
This isn’t how you architect games.
All throughout this book I was looking for a “Sprite” class which is mandatory in all Gaming Architectures but couldn’t find it.
This book rebuilds the whole concept of a Screen, Sprite and Movement without calling them by their proper names and mixing responsibility.
To put it bluntly: This is not a properly written gaming tutorial.
This book should have consumed one of the many Gaming frameworks out there and not roll out it’s own. (With my favoruite Gaming framework being Bill Reiss’s SilverSprite)
That might fly in a gaming tutorial book, but not in an MVVM book.
Readers of this book shouldn’t spend precious pages on reinventing a square wheel.
If you’re interested in how real gaming applications look like, I suggest reading Bill Reiss’s blog, Andy Beaulieu’s blog and many other Silverlight Gaming oriented blogs.
Just like this picture, when looking at the Gaming Architecture samples in this book, I’m left thinking “This isn’t right”…
Mistake #3: Not a Good MVVM Book
MVVM is essentially about these 3 things:
1) Data Binding
2) Commands
3) VisualStateManager.
Once you’ve got those three basic aspects down, everything else flows naturally.
Maybe this would have been a more appropriate book cover?
The book has 1 Command Sample in it, 1 Binding Sample in it and not a single VisualStateManager sample in it.
There are some sections of the book that scream out “This needs to be MVVMed” but aren’t.
The above code snippet screams out to me “Refactor into 1 Visual State Group with 4 Visual States!”.
But even such a basic example is left standing in this book.
In a MVVM book, I’d expect the book to be filled with these 3 basic concepts, and yet there are hardly any mentions of them anywhere.
This book isn’t about teaching MVVM fundamentals, but you just can’t have a conversation about MVVM without these 3 core concepts.
The book is stuck in a quagmire of trivialities instead of focusing on substantial MVVM issues.
Mistake #4: Not a good Code oriented book
There are lots of places in the book where I felt “Wow, If this was going through code review I wouldn’t let anyone check this in.”
There’s clearly quite a few Anti-Patterns, Code Smells and Worst practices throughout the sample codebase.
Even if you weren’t programming in Silverlight & WPF, these apply to any platform or coding language.
There’s some pretty fundamental anti-patterns in this book.
One thing that was like nails on a chalkboard to me was the prolific use of Enums and multiple Switch Statements.
Enum switch statements are widely regarded as an anti-pattern when there’s more then 1 switch statement per enum.
Most of the enums in this book should have been refactored to independent classes.
From Code Smells on Jeff Atwood’s “Coding Horror” blog:
Any change to the BubbleTaskType enum would cause many cascading changes all throughout this application.
Which will cause a high overhead when maintaining this application.
Some of the code in this book just seems like there’s some pretty fundamental coding principles missing from it.
The author is entitled to his own unique style of coding (like we all are), but public book authoring needs to be held to a higher standard.
Mistake #5: Doesn’t even mention Blend
One of the main benefits from MVVM is the ability to design views separately from their behaviour.
MVVM Developers should use designers like Expression Blend and the Visual Studio designer to built their screens.
But this book doesn’t even mention that or touches on that point.
Most of the code in this book is pretty non-designer friendly and would cause MVVM developers to get the wrong idea about MVVM development.
In an advanced MVVM book I’d expect to see some talk about designers, yet there isn’t any.
Is there anything good about this book?
Sure, it’s a huge article written by an extremely smart and talented author.
There are bound to be many great tips & tricks spread throughout this book.
However this book is a failure as an MVVM book, It’s a failure as a gaming tutorial book, and it’s a failure as a code sample book.
Follow-up Discussion on the WPF Disciples
We’re having a discussion on the WPF Disciples newsgroup reading this book review.
There seems to be a consensus that I’m wrong and this is an incredible book.
Feel free to read the whole discussion or my summary of the points made.
But Justin, I want to learn MVVM!
“Well Justin, you just crashed my hopes of ever learning MVVM! I’m going to drown myself somewhere to teach you a lesson!”
Well, Please don’t.
You can still easily learn MVVM like we all did. There are some great blog posts out there.
Literally every Silverlight & WPF expert has written about MVVM at some point or another. Here’re a few blog post to get you started:
1) Laurent Bugnion
2) Shawn Wildermuth
3) John Papa
4) Jesse Liberty
5) And lots more
Sincerely,
-- Justin Angel
Cutting Edge Silverlight4 COM+ Features
Hi Folks,
The new Silverlight 4 COM+ Automation feature can be used to perform a myriad of previously unavailable tasks in Silverlight.
In this blog post I’ll review some of these tasks, what COM+ Automation is, some related issues and helpful introduce developer tools.
The code we’ve created in this blog post is available @ http://Justinangel.net/Storage/SL4Com/SL4Com.zip
And a Live demo is available @ http://Justinangel.net/Storage/SL4Com/testpage.html
What is Silverlight 4 COM+ Automation support?
Silverlight 4 Beta 1 offers the ability to initialize and use COM+ classes from Silverlight.
It should be noted that these features are only available in elevated privileges Out-Of-Browser mode and are not available in-browser.
In Silverlight 4 Beta1 Com+ Automation only works on Windows machines (but more on that later).
The majority of work around Silverlight 4 COM+ support is centered around the ComAutomationFactory and ComAutomationEvent classes.
Nooo! COM+ killed my inner child back in the 90s!
Get over it.
Silverlight 4 COM+ Automation is not about authoring, deploying or versioning COM+ components, that is a worst practice for this feature.
The best practice for Silverlight 4 COM+ is to only use common operating system COM+ classes, and not ship your own.
Given that best practice, you are just the consumer of some time tested Windows APIs.
Using COM+ Windows APIs is no different then consuming the .Net framework, 3rd party frameworks or p/Invoke features.
Stop yapping and show me how to setup a Silverlight 4 OOB project!
We’ll start by creating a new Silverlight 4 OOB (Out Of Browser) project with Elevated Privileges in Visual Studio 2010.
For our test project we don’t need a Server-Side project, and we need to make sure we’re using Silverlight 4.
Right-Click on the SL4Com project and choose “Properties”.
Check the “Enable Running Application out of browser”.
Click “Out of Browser Settings” and set “Require Elevated Trust when running outside the browser”.
Next add a Button to MainPage that’ll install our Out-Of-Browser application.
<Button x:Name="btnInstall" Click="btnInstall_Click" Content="Install Out-Of-Browser App" />
private void btnInstall_Click(object sender, RoutedEventArgs e)
{
if (Application.Current.InstallState == InstallState.NotInstalled)
Application.Current.Install();
}
Note: This article is about COM+, not best practices for wiring up events.
If this was a real application, we should have used Prism Commands or Blend Behaviours to hook up these events.
We’ll run our app and install it.
Next, we’ll need to tell Visual Studio 2010 to run the Out-Of-Browser app when debugging.
Go to Project properties –> Debug –> Installed out of browser application –> SL4Com.
One last step we have to do is add a reference to Microsoft.CSharp.dll so we could use the new Silverlight 4 dynamic keyword.
(on my machine the DLL is at c:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\Microsoft.CSharp.dll)
Feature #1: Write files anywhere on the local machine
Using the FileSystemObject we have virtually unlimited access to the user’s file storage.
<Button x:Name="btnWriteFile" Content="Write file to C:\test.txt" Click="btnWriteFile_Click" />
private void btnWriteFile_Click(object sender, RoutedEventArgs e)
{
using(dynamic fsoCom = ComAutomationFactory.CreateObject("Scripting.FileSystemObject"))
{
dynamic file = fsoCom.CreateTextFile(@"c:\test.txt", true);
file.WriteLine("Bloody Hell!");
file.WriteLine("Silverlight is writing to C:\\");
file.Close();
}
}
When we run our app and click the button we can see that a new file has been created on C:\test.txt.
Feature #2: Reading any file from the user’s machine
Using FileSystemObject.ReadAll method we can read any file off the user’s machine.
<Button x:Name="btnReadFile" Content="Read file C:\test.txt" Click="btnReadFile_Click" />
private void btnReadFile_Click(object sender, RoutedEventArgs e)
{
using (dynamic fsoCom = ComAutomationFactory.CreateObject("Scripting.FileSystemObject"))
{
dynamic file = fsoCom.OpenTextFile(@"c:\test.txt", 1, true);
MessageBox.Show(file.ReadAll());
file.Close();
}
}
Running the app and clicking the button shows us the file contents:
What else can FileSystemObject do for us?
The FSO object let’s us essentially own the user machine.
It provides a way to read, write, delete or modify any file or directory on the user’s file system.
Here’s a list of Methods you can explore independently:
Feature #3: Execute/Run any command or file
Using the WShell Run Method we can execute any command.
<Button x:Name="btnExecuteCmdPing" Content="Cmd Ping 127.0.0.1" Click="btnExecuteCmdPing_Click" />
private void btnExecuteCmdPing_Click(object sender, RoutedEventArgs e)
{
using(dynamic shell = ComAutomationFactory.CreateObject("WScript.Shell"))
{
shell.Run(@"cmd /k ping 127.0.0.1");
}
}
Clicking the button opens up the CMD and runs the specified command:
Feature #4: Emulate user input
Using the WShell SendKeys method we can send input to the currently focused application.
This feature is extremely useful for integration testing.
<Button x:Name="btnExecuteNotepadAndSendKeys" Content="Run Notepad and write something" Click="btnExecuteNotepadAndSendKeys_Click" />
private void btnExecuteNotepadAndSendKeys_Click(object sender, RoutedEventArgs e)
{
using (dynamic shell = ComAutomationFactory.CreateObject("WScript.Shell"))
{
shell.Run(@"c:\windows\notepad.exe");
shell.SendKeys("Justin Angel{Enter}Rocks!");
}
}
Looking at the SendKeys syntax it’s easy to see there are special keys (like Enter, Tab, escape, ctrl, etc) that can be specified using a special notation.
Feature #5: Pin files to the Windows 7 Taskbar
Using The Shell.Application class we can iterate over all applications, check their Verbs and execute those verbs accordingly.
Here are the Verbs for the Calculator application:
However, this method allows us to Pin Calculator to the Win7 taskbar even when the Calculator is closed.
It does that by checking the Windows verbs on the LNK (Link) file to Calculator.
<Button x:Name="btnPinCalculator" Content="Pin Calcuator to the Win7 Taskbar" Click="btnPinCalculator_Click" />
private void btnPinCalculator_Click(object sender, RoutedEventArgs e)
{
using (dynamic ShellApplication = ComAutomationFactory.CreateObject("Shell.Application"))
{
dynamic commonPrograms = ShellApplication.NameSpace(23);
string allUsersPath = commonPrograms.Self.Path;
dynamic directory = ShellApplication.NameSpace(allUsersPath + @"\Accessories");
dynamic link = directory.ParseName("Calculator.lnk");
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
if (verb.Name.Replace(@"&", string.Empty).ToLower() == "pin to taskbar")
{
verb.DoIt();
}
}
}
}
Essentially, what this method does is:
1. Gets the path for all the users start menu links.
2. Gets the specific link for Calculator.
3. Checks what Verbs are available for that link.
4. Execute the “Pin to Taskbar” verb.
And when running this application we can see Calculator is now pinned to the user’s taskbar:
Feature #6: Read any Registry values
Using the Shell.Application RegRed method you can read values from the machine’s registry.
At the "HKLM\Software\Microsoft\Windows\CurrentVersion\CommonFilesDir" registry key we can see the location of the machine’s Common Files:
We can easily access that value using RegRead.
<Button x:Name="btnReadRegistry" Content="Read HKLM registry" Click="btnReadRegistry_Click" />
private void btnReadRegistry_Click(object sender, RoutedEventArgs e)
{
using (dynamic WShell = ComAutomationFactory.CreateObject("WScript.Shell"))
{
string reg = WShell.RegRead(@"HKLM\Software\Microsoft\Windows\CurrentVersion\CommonFilesDir");
MessageBox.Show("The Program files on this machine are at: " + reg);
}
}
Clicking the button shows the value of the registry key.
Feature #7: Add OOB App to Windows’ Startup
Using a combination of the LNK technique we’ve seen earlier and Shell.Application RegWrite method we can add our OOB app to the Windows’ startup applications.
Every program listed under “HKLM\Software\Microsoft\Windows\CurrentVersion\Run\” will be executed when the machine first starts up.
So if we can get our OOB link and add it to that Registry location, we can add our OOB application to Windows’ Startup.
<Button x:Name="btnAddOOBAppToStartup" Content="Add out-of-browser application to Startup" Click="btnAddOOBAppToStartup_Click" />
private void btnAddOOBAppToStartup_Click(object sender, RoutedEventArgs e)
{
using (dynamic ShellApplication = ComAutomationFactory.CreateObject("Shell.Application"))
{
dynamic commonPrograms = ShellApplication.NameSpace(11);
string allUsersPath = commonPrograms.Self.Path;
dynamic directory = ShellApplication.NameSpace(allUsersPath + @"\Programs");
dynamic link = directory.ParseName(Deployment.Current.OutOfBrowserSettings.ShortName + ".lnk");
string OOBLink = link.Path;
using (dynamic WShell = ComAutomationFactory.CreateObject("WScript.Shell"))
{
WShell.RegWrite(@"HKLM\Software\Microsoft\Windows\CurrentVersion\Run\"
+ Deployment.Current.OutOfBrowserSettings.ShortName,
OOBLink);
MessageBox.Show("Please restart your machine and this application will load on startup.");
}
}
}
This code snippet isn’t all that complicated.
First, we get the LNK to the current out-of-browser application by checking the start menu links directory.
Next, we add that LNK file Uri to the registry node we mentioned earlier on.
And after running clicking the button we can see the registry value was added:
Task #8: Pinning the OOB Application to Windows’ 7 Taskbar
We’ve previously seen how to get the LNK for the OOB application and we’ve seen how to pin those LNKs to the Taskbar.
It’s fairly easy to combine those two techniques to pin the current OOB app to the taskbar.
<Button x:Name="btnPinOOBApp" Content="Pin Out-of-Browser application to Taskbar" Click="btnPinOOBApp_Click" />
private void btnPinOOBApp_Click(object sender, RoutedEventArgs e)
{
using (dynamic ShellApplication = ComAutomationFactory.CreateObject("Shell.Application"))
{
dynamic commonPrograms = ShellApplication.NameSpace(11);
string allUsersPath = commonPrograms.Self.Path;
dynamic directory = ShellApplication.NameSpace(allUsersPath + @"\Programs");
dynamic link = directory.ParseName(Deployment.Current.OutOfBrowserSettings.ShortName + ".lnk");
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
if (verb.Name.Replace(@"&", string.Empty).ToLower() == "pin to taskbar")
{
verb.DoIt();
MessageBox.Show("Close this application and start it up again from Win7 Taskbar");
}
}
}
}
And we can see that even when our OOB application is closed, it’s still showing up on the Win7 taskbar.
Feature #9: Text to Speech
Using Windows’ built-in SAPI engine we can easily do Text to Speech and even Speech to Text.
We’ll demo using the SAPI.SpVoice class for Text2Speech.
Feel free to explore the SAPI namespace since it’s full of other useful speech related features.
<Button x:Name="btnText2Speech" Content="Use Text to Speech" Click="btnText2Speech_Click" />
private void btnText2Speech_Click(object sender, RoutedEventArgs e)
{
using (dynamic ISpeechVoice = ComAutomationFactory.CreateObject("SAPI.SpVoice"))
{
ISpeechVoice.Volume = 100;
ISpeechVoice.Speak("<rate speed=\"0\"><pitch middle=\"0\">Hello World! My HoverCraft is full of eels.");
}
}
Clicking the button does indeed cause Windows to start speaking.
For a relatively acceptable use of this feature, have a look at my Molecular Biology DNA Visualizer.
It is also possible to do limited speech recognition using SAPI using the SAPI.SpInprocRecognizer class.
Feature #10: Execute SQL with Local Databases
Using ODBC features available in Windows, we can easily connect to local databases and execute SQL.
Here’s a sample of executing a simple SQL Insert with the local Northwind database:
<Button x:Name="btnExecuteSQL" Content="Execute SQL Insert statement" Click="btnExecuteSQL_Click" />
using (dynamic IDbConnection = ComAutomationFactory.CreateObject("ADODB.Connection"))
using (dynamic IDbCommand = ComAutomationFactory.CreateObject("ADODB.Command"))
{
IDbConnection.ConnectionString = "driver={SQL Server};" +
"server=.\\;uid=sa;pwd=password;database=Northwind";
IDbConnection.Open();
IDbCommand.ActiveConnection = IDbConnection;
IDbCommand.CommandText =
@"INSERT INTO [Northwind].[dbo].[Region]
([RegionID], [RegionDescription]) VALUES (10, 'JustinLand')";
IDbCommand.Execute();
}
Note: this code snippet does not show best practices for using ODBC for Silverlight. For one thing, Commands should use parameters and not strings.
If you were to execute this code sample you’d probably get the following error:
Since you don’t have the Northwind Database installed or the username & password are wrong you’d see some exception or another.
Allow me to assure you “It works on my machine”!
It is important to discuss best practices at this point.
It is not my intent to advocate executing local SQL statements in conjunction with a local database.
However, It is possible to convert any 3rd party OR/M or Persistence layer to run on ODBC.
Which would make for a very comfortable EF/Linq2SQl/NH like syntax. In that case, it would be much more acceptable to use ODBC.
Another issue with this method is the end-user might not have any local database available.
And you’ll end up resorting using Access or the likes.
Personally I believe that for local Silverlight storage we should use local OODBs, and not use ODBC.
Feature #11: Automate Scanners and Cameras
Using the WIA (Windows Image Acquisition) infrastructure we can automate external Scanners, Cameras and Video cameras.
Many very unique samples (converting file formats, getting scanners to scan, taking pictures, etc) are available at the WIA Samples page.
One possible task is to iterate over all Cameras and Scanners currently connected to the local machine and their commands:
<Button x:Name="btnIterateWIA" Content="Iterate over external Cameras and Scanners" Click="btnIterateWIA_Click" />
private void btnIterateWIA_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("List of available external devices and commands:");
using (dynamic DeviceManager = ComAutomationFactory.CreateObject("WIA.DeviceManager"))
{
var deviceInfos = DeviceManager.DeviceInfos;
for (int i = 1; i <= deviceInfos.Count; i++)
{
var IDevice = deviceInfos.Item(i).Connect();
var DeviceID = IDevice.DeviceID;
var DeviceName = IDevice.Properties("Name").Value;
var Commands = IDevice.Commands;
for (int j = 1; j <= Commands.Count; j++)
{
var IDeviceCommand = Commands.Item(j);
var CommandName = IDeviceCommand.Name;
var CommandDescription = IDeviceCommand.Description;
sb.AppendLine(" " + DeviceName + " (" + DeviceID + "), " + CommandName + ": " + CommandDescription);
// Execute with: IDevice.ExecuteCommand(IDeviceCommand.CommandID);
}
}
}
MessageBox.Show(sb.ToString());
}
The above code is actually pretty simple.
1. We initialize a DeviceManager.
2. We ask for all the DeviceInfos.
3. We then iterate over all devices, getting their commands.
4. We display the command name and device name.
On my dev machine with an External Scanner and External Camera, this is what we see:
Another thing we can do is select Images from external Image devices.
<Button x:Name="btnGetExternalImage" Content="Acquire External Image from Scanner/Camera" Click="btnGetExternalImage_Click" />
private void btnGetExternalImage_Click(object sender, RoutedEventArgs e)
{
using (dynamic CommonDialog = ComAutomationFactory.CreateObject("WIA.CommonDialog"))
{
dynamic imageFile = CommonDialog.ShowAcquireImage();
if (imageFile != null)
{
imageFile.SaveFile(@"c:\myImage.jpg");
MessageBox.Show("Saved c:\\myImage.jpg");
}
}
}
When clicking the button on my local machine we’ll see the following dialogs:
And we can see c:\myImage.jpg is indeed that same photo:
Feature #13: Use the Windows 7 Location API
As part of Windows 7 the Location API was added to provide developers with the current machine GPS location.
If the proper hardware is connect, Using the Location API we can get the current Latitude and Longitude of the current Machine.
<Button x:Name="btnWin7LocationAPI" Content="Activate Windows 7 Location API" Click="btnWin7LocationAPI_Click" />
private void btnWin7LocationAPI_Click(object sender, RoutedEventArgs e)
{
using (dynamic LatLongReportFactory = ComAutomationFactory.CreateObject("LocationDisp.LatLongReportFactory"))
{
uint curStatus = LatLongReportFactory.Status;
if (curStatus == (uint)4)
{
using (dynamic LatLongReport = LatLongReportFactory.LatLongReport)
{
MessageBox.Show("Latitude: " + LatLongReportFactory.Latitude + "\r\n Longitude: " + LatLongReportFactory.Longitude);
}
}
LatLongReportFactory.ListenForReports(5000);
ComAutomationEvent NewLatLongReportEvent = ComAutomationFactory.GetEvent(LatLongReportFactory, "NewLatLongReport");
NewLatLongReportEvent.EventRaised += (s, args) =>
{
using (dynamic LatLongReport = LatLongReportFactory.LatLongReport)
{
MessageBox.Show("Latitude: " + LatLongReportFactory.Latitude + "\r\n Longitude: " + LatLongReportFactory.Longitude);
}
LatLongReportFactory.StopListeningForReports();
};
}
}
The above code will display the current Latitude and longitude and then listen in for new reports every 5 seconds.
Feature #14: Use Classes from the Full .Net framework
While it is not recommended, you can consume some classes from the full .Net framework.
The reason it is not recommended, is because all of your users would need to have the full .Net framework installed.
Here’s an example of initializing the ReaderWriterLock class used for multithreading multiple readers or a single writer.
<Button x:Name="btnUseFullDotNet" Content="Use a class from the full .Net frameowrk" Click="btnUseFullDotNet_Click"/>
private static int foo = 0;
private void btnUseFullDotNet_Click(object sender, RoutedEventArgs e)
{
using (dynamic ReaderWriterLock = ComAutomationFactory.CreateObject("System.Threading.ReaderWriterLock"))
{
ReaderWriterLock.AcquireWriterLock(1);
MessageBox.Show("System.Threading.ReaderWriterLock.AcquireWriterLock() - acquired lock");
foo++;
ReaderWriterLock.ReleaseWriterLock();
MessageBox.Show("System.Threading.ReaderWriterLock.ReleaseWriterLock() - released lock");
ReaderWriterLock.AcquireReaderLock(1);
MessageBox.Show("While in reader lock - Foo value is " + foo);
ReaderWriterLock.ReleaseReaderLock();
}
}
Executing this code we’ll see the expected messages.
The interesting part here is that we’re using classes from the Full desktop .Net framework which are not available in Silverlight.
Feature #15: Use WMI to build FileSystemWatcher
Using the WbemScripting.SWbemLocator class we can execute WMI queries in Silverlight.
WMI allows querying for many operating system related information, like: Performance (CPU & Memory), Security, Networking, Storage, Kernel, Active Directory, etc.
In this sample we’ll rebuild the .Net FileSystemWatcher using WMI Events
<Button x:Name="btnActivateFileSystemWatcher" Content="Active FileSystemWatcher on C:\" Click="btnActivateFileSystemWatcher_Click" />
private void btnActivateFileSystemWatcher_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
using (dynamic SWbemLocator = ComAutomationFactory.CreateObject("WbemScripting.SWbemLocator"))
{
SWbemLocator.Security_.ImpersonationLevel = 3;
SWbemLocator.Security_.AuthenticationLevel = 4;
dynamic IService = SWbemLocator.ConnectServer(".", @"root\cimv2");
string fileSystemWatcherQuery =
@"SELECT * FROM __InstanceOperationEvent WITHIN 3 WHERE Targetinstance ISA 'CIM_DirectoryContainsFile' and TargetInstance.GroupComponent= 'Win32_Directory.Name=""c:\\\\""'";
dynamic monitor = IService.ExecNotificationQuery(fileSystemWatcherQuery);
Dispatcher.BeginInvoke(() => MessageBox.Show(@"Now listening to file changes on c:\"));
while (true)
{
dynamic EventObject = monitor.NextEvent();
string eventType = EventObject.Path_.Class;
string path = EventObject.TargetInstance.PartComponent;
Dispatcher.BeginInvoke(() => MessageBox.Show(eventType + ": " + path));
}
}
}).Start();
}
This code might look complex, but it really isn’t.
1. We’ve initialized a
WbemScripting.SWbemLocator and connected to the local Machine with proper security.
2. We’ve executed a WMI Query for all storage changes on C:\.
3. When that event fired we’ve shown a messagebox.
Since Wbem doesn’t directly support events, we have to constantly query it. So we’re executing the whole thing in a background thread.
Executing this code and adding c:\foo.txt file will cause the following messagebox to occur:
Feature #16: Iterate over valid ProgIDs
This one is just a shout-out to the COM infrastructure.
If you’ve been paying attention you’ve noticed some magic strings when calling ComAutomationFactory.CreateObject.
Those magic strings are the ProgIDs of registered COM+ components.
We can get a list of all valid ProgIDs using WMI.
<Button x:Name="btnIterateOverProgIDs" Content="Iterate over valid COM+ ProgIDs" Click="btnIterateOverProgIDs_Click" />
private void btnIterateOverProgIDs_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("The first 25 valid ProgIDs: ");
using (dynamic SWbemLocator = ComAutomationFactory.CreateObject("WbemScripting.SWbemLocator"))
{
SWbemLocator.Security_.ImpersonationLevel = 3;
SWbemLocator.Security_.AuthenticationLevel = 4;
dynamic IService = SWbemLocator.ConnectServer(".", @"root\cimv2");
dynamic QueryResults = IService.ExecQuery(
@"SELECT Caption, Description, InprocServer32, ProgID FROM Win32_ClassicCOMClassSetting where progid is not null");
for (int i = 1; i < 25 /*QueryResults.Count*/; i++)
{
string progID = QueryResults.ItemIndex(i).ProgID;
sb.AppendLine(" " + progID);
}
}
MessageBox.Show(sb.ToString());
}
After clicking the button we can see this list of the first 25 valid Classes for Com+ Automation:
Feature #17: Automate Microsoft Office
Office exposes a set of COM+ automation classes allowing to automate PowerPoint, word, excel, outlook, etc.
There’s been quite a lot written on this one so It’ll suffice to provide links to what’s already been said by folks more knowledgeable than myself:
Silverlight 4's New COM Automation Support by Jeff Prosise (Outlook)
Silverlight 4 Rough Notes: Trusted Applications by Mike Taulty (Excel)
Silverlight 4: New features overview (Part 3) – Elevated Out-of-browser applications by Alex Golesh (Word)
Silverlight TV Episode 1: The Joys of Trusted Out-of-Browser Applications by Keith Smith & John Papa (PowerPoint)
Tools for Silverlight 4 COM+ Development
When developing Silverlight COM+ applications these 4 tools will prove to be invaluable source of information.
Tool #1: WMI Explorer
WMI Explorer is a general purpose tool used to visualize WMI queries. (Which we’ve seen earlier)
Using WMI Explorer and the following query we can see a list of all available COM+ Components on the relevant machine:
SELECT Caption, Description, InprocServer32, ProgID FROM Win32_ClassicCOMClassSetting where progid is not null
This list is extremely helpful when examining which ProgIDs are available for COM Automation.
Tool #2: DLL Export Viewer
When working with dynamic types there’s no intellisense available.
But fear not, using DLL Export Viewer we essentially get the same information reflector would have provided us on an assembly.
First, find the COM+ DLL file address from WMI Explorer and load it into DLL Export Viewer:
Make sure “Scan COM Type Libraries” is checked.
And now we can see an exported list of members from the ODBC DLL:
Tool #3: Resharper
Though development with dynamic types doesn’t offer intellisense, Resharper 5 makes this a little better by offering intellisense on members that have been previously used.
Notice the intellisense for the “Run” and “SendKeys” methods.
Tool #4: MSDN and Search Engines
Most core Windows’ COM+ components have adequate documentation up on MSDN when searching for the type name on google:
In case the documentation on MSDN is missing or just irrelevant (and that’s quite common) search “CreateObject <ProgID>” and the VBScript results are easily portable to C#.
But What about Macs?
COM+ Automation isn’t supported for Macs in Silverlight 4 Beta 1.
For a good reason, Mac doesn’t have COM+.
However, Microsoft have stated they are looking into getting COM+ support working in Silverlight 4 RTM on a Mac.
Macs have similar programmatic access to COM known as AppleScript.
It’s not that hard to read once you remove the added spaces and add some indents.
Once you get past the syntax, it’s easy to see those are the same classes and members on a Mac as are available for Windows.
The point here is that if Microsoft wants to enable Com Automation-like features on a Mac there are 2 options:
1) Enable executing AppleScripts.
This option will let us have the same amount of control on a mac machine as we do on a windows machine.
2) Add an overload to ComAutomationFactory.CreateObject() that calls the “Tell Application” command under the scenes and gets a AppleScript object.
This option would work extremely well for Office automation. For any other operating system feature, you’ll have to code OS access twice.
If Microsoft chooses to not go ahead with Mac support in Silverlight 4 RTM, well, it’s not because they couldn’t.
What about Linux?
Moonlight has had the superior security model since it first shipped.
Mono supports hosting Moonlight in a GtkWidget that has full-trust capabilities.
So while Silverlight has an elevated privileges model, Mono has a full trust model.
Read more about this model over at Miguel de Icaza’s blog @ Standalone Silverlight Applications.
Can I author my own COM+ Components?
It is possible yet unadvisable.
Authoring COM+ Components has a huge cost of learning COM+, and deploying and versioning COM+ Components.
COM+ was such a successful technology most of us left as soon as we could.
Can I author .Net components and then deploy them as COM+ components?
Jeremiah Morril has a blog post on how to go about doing that.
It is possible yet tremendously cumbersome.
Consider that you’ve just added a requirement for the full desktop CLR when running in Silverlight.
Some of your users might not have .Net (or the right .Net version) installed.
Additionally, you’ll still back into COM+ DLL versioning hell.
If you’re going to take that level of dependency it might be best if you moved over to WPF.
Or, if you insist on taking a .Net dependency you shouldn’t use COM+ for communication.
It’d be best to use WCF for that.
Michael Wolf has a good blog post demoing how to create that connection.
Fin
In this blog post we’ve reviewed many new features enabled by Silverlight 4 COM+ support.
We’ve also covered how to best use this new feature including tools, best practices and the possible future of this feature.
Leave A comment
I’d love to hear what you think of Silverlight 4 COM+ automation?
Better yet, if there’s some novel use of Silverlight 4 COM+ I haven’t shown here, feel free to link to it.
Sincerely,
-- Justin Angel
Mix10 And Molecular Biology DNA Visualizer
Hi Folks,
If you haven’t already done so, I strongly encourage you to sign up for Mix 2010.
Windows Mobile and Silverlight, you say?
I really can’t discuss what’s on the agenda, but I can say it’s cool.
You will define your life as “Before Mix10” and “After Mix10”.
Especially if you join us at the bar afterhours :)
It looks like there’s some interesting Windows Mobile and Silverlight news at Mix10.
I wonder what that could possibly be.
Registering for Mix 2010
If you register before January 15th 2010, there’s a fairly substantial price reduction (600$) and a free night at the hotel.
I’d jump on it if I were you.
http://live.visitmix.com/Registration
Vote for my Mix10 Sessions!
Is Justin talking at Mix 2010? Well, that’s really up to you!
I’ve submitted 2 sessions for Mix 2010.
1) 6 Reasons why Silverlight & WPF are better than ASP.Net & Winforms - Where I talk about the guiding principles behind Silverlight & WPF design.
2) Silverlight Community Q&A w/ Justin Angel – This is an open forum to ask a Silverlight Community Expert and a former Microsoft Silverlight Program Manager any Silverlight question.
This will be the 8th time I’ve done that session and it’s always wildly successful.
So if you’d like to see me talk go to the mix site and vote for my sessions:
http://visitmix.com/opencallvote/?query=Justin%20Angel
Also checkout some other Silverlight sessions up for voting.
There’s some pretty amazing content offered by the world’s best Silverlight Community experts.
If you don’t vote for me I’ll club a baby seal. And it’ll be because of you.
Or if you’re into clubbing baby seals, vote for and I’ll club a baby seal. It’s really up to you.
Mix10K Smart Coding Challenge
As part of Mix10 there’s an online contest for the best Silverlight application in 10KB of C# and XAML.
I’ve submitted my entry: Molecular Biology DNA Visualizer
I was really going for a non-trivial use of the technology. Something that isn’t a game or a neat graphic trick.
But something that would showcase Silverlight as a force that could revolutionize LOB applications. In this case, bioinformatics apps.
If you liked my Mix10K app, feel free to vote for it.
There are also some other amazing 10k entries in Mix10k so you might want to spend 30 minutes going over the gallery.
I’d like to thank my inspiration while writing my Mix10K app:
[SimpleVideo:source=http://justinangel.net/Storage/They Might Be Giants - Science is Real.mp4|width=480 |height=390]
Sincerely,
-- Justin Angel
AutoMagically Implementing INotifyPropertyChanged
There have been lots of discussions in the Silverlight Developer Community recently about how to best implement the INotifyPropertyChanged interface.
In this blog post I’ll submit before the reader, what I perceive to be the simplest and the superior solution.
As you all know I’m a huge supporter of Silverlight open source projects, and in this blog post we'll use Mono.Cecil and PostSharp.
Download the projects from this blog post @ http://Justinangel.net/Storage/PostBuildMSILWeaving.zip
But first, INotifyWhatchaMaCallit?
Right, let’s start explaining this issue from scratch. For that, we need Cows!
Let’s setup a simple Silverlight form used for inputting the names of Cows.
Yes, Cows.
So first, we’ll start out by creating a simple POCO (Plain Old CLR Object) class to hold our Cow data.
public class Cow
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
}
Next, We’ll create super simple form to represent our new Cow class.
Normally, in real-world applications it would be best to use the DataForm control to create this form.
But for demo’s sake we’ll keep it simple with StackPanels and TextBoxs.
<StackPanel HorizontalAlignment="Left">
<StackPanel Orientation="Horizontal">
<TextBlock Text="First Name" Width="150" />
<TextBox Text="{Binding FirstName}" Width="300" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Middle Name" Width="150" />
<TextBox Text="{Binding MiddleName}" Width="300" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Last Name" Width="150" />
<TextBox Text="{Binding LastName}" Width="300" />
</StackPanel>
<Button x:Name="changeName" Content="Change Person Properties" />
</StackPanel>
Note the bolded and underlined {Binding} expressions that specify the connection between our POCO property and UI Elements.
After we’ve setup our bindings we’ll need to initialize the DataContext with some initial data. Like so:
this.DataContext = new Cow() { FirstName = "Bassy", MiddleName = "Won't Change", LastName = "LeCow" };
It’s an odd name for a Cow “Bassy ‘Won’t Change’ LeCow”, but it’s good enough for us.
Let’s fire up the form:
But here’s the core issue that starts off this whole INotifyPropertyChanghed discussion. How do we let the form know when the data changes?
Let’s see this problem in action.
We’ll implement the Button.Click event and change the First, Middle and last name of Bassy LeCow.
private void changeName_Click(object sender, RoutedEventArgs e)
{
Cow p = (Cow)this.DataContext;
p.FirstName = "Changed by manual implementation";
p.LastName = "Changed by Post-IL Weaving";
p.MiddleName = "Changed";
}
But what happens when we click our button?
Nothing. Updating the underlying datasource hasn’t done a single thing to update our form.
Silverlight as a UI Framework has no way of knowing when our POCO property has been updated.
What’s the solution?
There are two solutions that could easily fit into this scenario:
1. Inheriting from DependencyObject and replacing all of our POCO properties with DependencyProperties.
Read more about that option at this SilverlightShow article.
2. Implementing the INotifyPropertyChanged interface and invoking PropertyChanged event in our property setters.
Up until recently, I was squarely in the DependencyObject camp.
But after a tempestuous round of discussions on the WPF Disciples mailing list and this aptly written blog post by Kent Boogaart I’ve moved to the INotifyPropertyChanged camp.
The core reason I decided on INotifyPropertyChanged was that you can’t use DependencyObjects in non-UI Disptacher threads. Which is a deal breaker.
Enough with your jibber jabber, show me the code!
So here’s the basic implementation of INotifyPropertyChanged for the FirstName property:
public class Cow : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
public string LastName { get; set; }
public string MiddleName { get; set; }
#region Implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
We won’t go over the specifics, but it’s a fairly easy interface to implement, just fire the PropertyChanged event.
When comparing LastName implementation to FirstName implementation we can clearly see that it was much simpler to declare the LastName property.
It’s more readable, more maintainable, and has less chance of duplicating code throughout our system.
Solving the problem caused by the solution
There are a lot of options that were recently discussed for solving the syntax issue caused by declaring INPC (INotifyPropertyChanged) properties.
1) Ray Huston and Jonas Follesoe talk about Runtime substitution of INPC properties through Castle.DynamicProxy.
public class MyViewModel : IAutoNotifyPropertyChanged
{
public virtual string Name { get; set; }
public virtual int Age { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
However, this method requires you stop using our beloved “New” keyword and start using runtime proxies. I’m not a fan of either of those.
A solid solution should have zero-impact on the way we write code today.
2) Michael Sync, Einar Ingebrigsten and Oren Eini talk about improving the syntax needed to declare an INPC property.
public class Employee : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _firstName;
public string FirstName
{
get { return this._firstName; }
set
{
this._firstName = value;
this.PropertyChanged.Notify(() => this.FirstName);
}
}
}
There are various sugar-coated syntaxes that have been suggested for INPC. but all of them require us to change the way we code.
3) Brad Abrams demos Silverlight WCF RIA Services generating the INotifyPropertyChanged and INotifyPropertyChanging interfaces for you.
But that only works if these types are declared on the server and are sent down to Silverlight. Additionally, if the property name changes it’s all still string based.
[DataMember()]
[Key()]
[ReadOnly(true)]
public int EmployeeID
{
get
{
return this._employeeID;
}
set
{
if ((this._employeeID != value))
{
ValidationContext context = new ValidationContext(this, null, null);
context.MemberName = "EmployeeID";
Validator.ValidateProperty(value, context);
this._employeeID = value;
this.OnPropertyChanged("EmployeeID");
}
}
}
Solving the problem caused by the Solution to the Solution of the Problem
Confused? Tired? About to start crying? Be a man for gods sakes!
Each of the existing solutions we’ve seen up until now has it’s own set of unique challenges.
All of which either creates weird, unnatural and repeatable C# Syntaxes, or relays heavily on string based solutions.
Post Build MSIL Weaving
C# becomes MSIL, which later becomes Byte Code.
Remember those good old .Net 1.1 days when this chart looked important?
Well, I believe we’ve exhausted all the possible C# hacks to create sustainable and readable INPC properties in straight C# code.
The Silverlight & WPF developer community has been working on this for 2 years. Let’s think outside the C# box.
Specifically, let’s think in the MSIL box.
Post Build MSIL Weaving is the practice of taking compiled MSIL assemblies and manipulating them after compilation.
So, we can write C# code that manipulates our assemblies after they’ve been compiled.
In this article we’ll look at 2 approaches to doing Post-IL weaving: Mono.Cecil and PostSharp.
Low Level MSIL Weaving with Mono.Cecil
This method is super low-level and takes us down to writing code in MSIL with a custom MSBuild Task.
It’s not for everyone, but try and follow.
This is the C# Syntax I want us to end up with:
public class Cow : INotifyPropertyChanged
{
[Property]
public string LastName { get; set; }
1) We’ll start off by creating the PropertyAttribute in our Silverlight project:
[AttributeUsage(AttributeTargets.Property)]
public class PropertyAttribute : Attribute
{
}
2) Next, we’d like to create a Custom “AfterBuild” MSBuild task we can integrate into our project to read this attribute.
Let’s create a new Desktop project to hold that MSBuild Task:
3) Add a reference to the MSBuild V3.5 DLLs:
4) Now that we’ve got our MSBuild references we’ll create a custom MSBuild task:
public class WeavingInpcTask : Task
{
public override bool Execute()
{
SearchForPropertiesAndAddMSIL();
return true;
}
private void SearchForPropertiesAndAddMSIL()
{
}
[Required]
public string SolutionDir { get; set; }
}
5) We’ll need to tell our Silverlight project to execute this task after building our project.
To do that we’ll unload our Silverlight project and add a reference to this task after build.
<UsingTask
TaskName="WeavingINPC.MSBuildTask.WeavingINPCTask"
AssemblyFile="$(SolutionDir)WeavingINPC.MSBuildTask\bin\$(Configuration)\WeavingINPC.MSBuildTask.dll" />
<Target Name="AfterBuild">
<WeavingINPCTask SolutionDir="$(SolutionDir)" />
</Target>
6) Download the latest Mono.Cecil binaries from http://mono.ximian.com/daily/ MonoCharge.
7) Add a reference from our MSBuild project to the unzipped Mono.Cecil.DLL.
Now that we’re done with all the grunt work of setting up an MSBuild Mono.Cecil project we can get down to business.
Here’s how our class looks like:
public class Cow : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
[Property]
public string LastName { get; set; }
public string MiddleName { get; set; }
#region Implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
FirstName manually implements INotifyPropertyChanged.
LastName should be auto implemented by Mono.Cecil.
And Middle Name won’t have any INPC support at all.
Let’s open up reflector and see the differences between FirstName and LastName:
But wait, we don’t really care about the C# differences, do we? We care about MSIL!
So let’s change reflector to show us the IL code.
Here’s the set_LastName method MSIL and you can see it doesn’t call RaisePropertyChanged:
And here’s the set_firstName method MSIL that does invoke RaisePropertyChanged:
We can see that if we’re going to add MSIL directly to set_lastName we’re going to need to add these 5 lines of MSIL:
Let’s write the code to load up all the assemblies in our solution and find all properties that have the PropertyAttribute:
foreach (string assemblyPath in Directory.GetFiles(SolutionDir, "*.dll", SearchOption.AllDirectories))
{
AssemblyDefinition sourceAssembly = AssemblyFactory.GetAssembly(assemblyPath);
foreach (TypeDefinition type in sourceAssembly.MainModule.Types)
foreach (PropertyDefinition prop in type.Properties)
foreach (CustomAttribute attribute in prop.CustomAttributes)
if (attribute.Constructor.DeclaringType.FullName == typeof(PropertyAttribute).FullName)
{
Here’s the object model we have to go through to find usages of PropertyAttriubte:
Next, we’ll add those 5 lines of MSIL:
CilWorker MSILWorker = prop.SetMethod.Body.CilWorker;
Instruction ldarg0 = MSILWorker.Create(OpCodes.Ldarg_0);
Instruction propertyName = MSILWorker.Create(OpCodes.Ldstr, prop.Name);
Instruction callRaisePropertyChanged =
MSILWorker.Create(OpCodes.Call, raisePropertyChanged);
MSILWorker.InsertBefore(prop.SetMethod.Body.Instructions[0], MSILWorker.Create(OpCodes.Nop));
MSILWorker.InsertBefore(prop.SetMethod.Body.Instructions[prop.SetMethod.Body.Instructions.Count - 1],
ldarg0);
MSILWorker.InsertAfter(ldarg0, propertyName);
MSILWorker.InsertAfter(propertyName, callRaisePropertyChanged);
MSILWorker.InsertAfter(callRaisePropertyChanged, MSILWorker.Create(OpCodes.Nop));
This isn’t the simplest code you’d ever seen for sure.
But It’s not that hard to see how these 5 InsertBefore/InsertAfter become our 5 MSIL lines.
Look for the words “nop", “ldarg_0”, “ldstr” and “call”. And then it becomes pretty clear we’ve just implemented the missing MSIL.

Next we’ll build our project.
And reflect into set_LastName:
Isn’t that cool? We’ve added 5 lines of MSIL directly into our property.
Let’s run our solution:
So FirstName was changed by our manual INPC implementation, and LastName was changed by our Post-Build MSIL Weaving.
We can now take this solution all the way home and end up with this syntax:
public class Cow : INotifyPropertyChanged
{
[Property] public string LastName { get; set; }
[Property] public string MiddleName { get; set; }
[Property] public string LastName { get; set; }
}
High Level MSIL Weaving with PostSharp
Some people would find MSIL intimidating, writing your own build tasks frightening and reinventing AOP a daunting task.
Those developers are essentially pansy little girls, but let’s see a more straightforward way of doing Post-Build MSIL Weaving.
Step #1: Go to the PostSharp website, register to the website, and install PostSharp. Make sure you close down Visual Studio during installation. Seriously.
Step #2: Add a reference to PostSharp.Loas.SL.dll and PostSharp.Public.SL.dll from your Silverlight project.
(On my dev box PostSharp installed to: C:\Program Files (x86)\PostSharp 1.5\Reference Assemblies\Silverlight 2.0\)
Step #3: What? We’re done?
That was pretty much all the setup you had to do.
Next, we’ll add a the PropertyAttribute so it inherits from OnMethodInvocationAgent and override OnInvocation:
public class PropertyAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
eventArgs.Proceed();
}
}
We’ll make sure that the attribute was applied on a Setter.
public class PropertyAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
eventArgs.Proceed();
if (eventArgs.Method.Name.StartsWith("~set_"))
{
}
}
}
And lastly we’ll call the RaisePropertyChange method with the property Name.
public class PropertyAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
eventArgs.Proceed();
if (eventArgs.Method.Name.StartsWith("~set_"))
{
MethodInfo method = eventArgs.Instance.GetType().GetMethod("RaisePropertyChanged");
method.Invoke(eventArgs.Instance, new object[] {(eventArgs.Method.Name.Replace("~set_", string.Empty))});
}
}
}
This is how our class looks like:
public class Cow: INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
public string LastName { get; [Property] set; }
public string MiddleName { get; set; }
#region Implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Let’s run our sample:
And Indeed, Post Build MSIL Weaving worked great here as well.
In reflector we can see the Post-IL weaved code in Last Name:
It isn’t really clear when you first look at it.
But basically, this code just invokes our PropertyAttribute method at runtime.
So PostSharp weaved some MSIL to invoke our code, but not the code itself.
We can take this solution all the way home and end up with this syntax:
public class Cow : INotifyPropertyChanged
{
public string LastName { get; [Property] set; }
public string MiddleName { get; [Property] set; }
public string LastName { get; [Property] set; }
}
What’s next?
In this article I’ve shown 2 Post-Build MSIL weaving techniques:
1) Mono.Cecil – that changes MSIL directly at compile time.
2) PostSharp – that changes MSIL to invoke our code at runtime.
If you’re going to use any of these options, you’ll have to consider where it’s best for you to apply your attribute – on the class? on each property? on the entire assembly?
Are you going to implement INPC with default values, raising notifications only on changes, cross-property change notifications, and a myriad of other features? Or just stick to the basics?
If you’re going to go with Mono.Cecil you’ll have to work a bit more on the infrastructure of the MSBuild tasks and Visual Studio integration.
If you’re going to go with PostSharp you’ll have to spend some time looking at the various classes and overloads offered in the framework.
Plus, you’ll have to consider the performance and payload ramifications.
Fin
In my opinion, Post-Build MSIL Weaving provided us with the best and simplest solution.
We can support the property INPC syntax:
public class Cow : INotifyPropertyChanged
{
public string LastName { get; [Property] set; }
public string MiddleName { get; [Property] set; }
public string LastName { get; [Property] set; }
}
or the class INPC syntax:
[INPC]
public class Cow : INotifyPropertyChanged
{
public string LastName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
or even go with the assembly Wide syntax:
Each of these syntaxes affords us total control of our INotifyPropertyChanged scenario without having to change the look, feel and flow of our code.
Sincerely,
-- Justin Angel
Silverlight Weblog Features Overview
Hi folks,
Welcome to my new Silverlight Weblog!
Join me on a tour of the numerous features this blogging engine offers.
But first: Why Silverlight?
Simply put: my time is worth money.
I blog as a labour of love, devotion and personal passion.
As such, I’d like to spend the minimum amount of time required to setup a blog.
Upon deciding to move out of my previous blog, I faced two prospects:
- Move to another HTML based weblog – which normally takes me a week (60 hours~) of fiddling around with HTML, CSS, Javascript and deployment.
- Recreate my blog in Silverlight – which I estimated would take about the same and I’d finally be rid of this horrible nuisance – HTML, Javascript and CSS.
For me, it was an easy choice.
Now I get to experiment with which UI patterns work best for blogging.
Not just use the same handy down comprise-driven-UI I’ve always had.
Using accordions for the front page, expanding panels for comments, responsive user interface, and many others are just some of the benefits Silverlight afforded this blog.
What Technologies were used?
Silverlight - User Interface front end.
WCF RIA Services - Server<->Client Communication.
PRISM – Commanding and Messaging support.
Managed Extensibility Framework (MEF) – Dynamically loading blog widgets.
ASP.Net Webforms & ASP.Net MVC – Processing client requests and returning shell HTML.
ASP.Net Dynamic Data (AJAX, Webforms) – The back office management portal.
WCF Syndication Services – RSS 2.0 and Atom 1.0 Feeds.
SQL Server 2008 – Database.
Entity Framework V3.5 – Data Access Layer.
MSTest - Unit testing Server side.
Microsoft Silverlight Unit Testing Framework – Unit testing Client side.
RhinoMocks – Unit testing Mocking.
Unity – IoC Unit Testing framework.
3rd Party commercial component – rendering out HTML in Silverlight.
Everything else – home grown.
Is Silverlight Weblog open source?
Yes. Get it @ http://SilverlightWeblog.codeplex.com under Ms-PL license.
Posting from Windows Live Writer
A major part of my workflow when authoring blog posts is using Windows Live Writer.
Support for Windows Live Writer is enabled through the Metaweblog API.
Here’s a sample blog post in Windows Live Writer:
After publishing this blog post to Silverlight Weblog it’ll render out as expected:
Hierarchical Blog Categories Widget
When posting from Windows Live Writer the blog post author can tag blog posts.
The Silverlight Weblog blogging engine support endlessly nested hierarchical categories.
The Print screen above shows 3 levels of Categories, but in theory the blog supports infinite nesting.
Clicking on a Category Link in the Categories Tree or In a Blog post would navigate the user to a list of all blog posts in that category.
Hierarchical Comments
Silverlight Weblog supports leaving infinitely nested comments on blog posts.
Having properly nested comments elevates the mess of replying to 6 people in one comment.
As you can see from the above print screen each comment is accompanied with a Gravatar and can be infinitely nested to a parent.
RSS 2.0 and Atom 1.0 Feeds
Silverlight Weblog supports RSS and Atom feed formats through the Links Widget.
Here’s a print screen of the main blog RSS feed:
Moreover, Silverlight Weblog supports RSS/Atom feeds for each individual category:
Clicking the RSS Icon next to each category would provide the user with a link to it’s RSS link.
Twitter Integration
Silverlight Weblog displays the latest non-reply tweets from the blog author on the Sidebar.
When mouseovering the Twitter widget it smoothly expands it’s vertical height to accoemdate easier reading.
At the end of each blog post, it is suggested to the user to retweet this blog post:
Clicking the “Twitter this blog post” link would open up a new tweet on twitter.com.
User Friendly URLs
Silverlight Weblog generates easy to remember user-friendly URLs.
This enables people to easily link to your Rich Internet Application and have it load up the relevant blog post.
Single and Multi-user Support
When hosting blogs, some blogs are meant for only one user while others are used by multiple users.
Silverlight Weblog supports both schemes with it’s easy to customize UI and user-relevant URLs.
In the print screens above it’s easy to see how the blog supports multiple users through a convenient URL schema.
Authoring Rich Content with Macros
When authoring blog posts It’s always helpful to introduce richer content.
Macros translate text into visual elements.
For instance, the following macro (presented here as an image) would translate into a video player:
![[SimpleVideo:source=http://mschannel9.vo.msecnd.net/o9/mix/09/wmv/key01.wmv | width=650 |height=400] [SimpleVideo:source=http://mschannel9.vo.msecnd.net/o9/mix/09/wmv/key01.wmv | width=650 |height=400]](http://justinangel.net/BlogFiles/WindowsLiveWriter/SilverlightWeblogFeaturesOverview_7BB2/image_67.png)
[SimpleVideo:source=http://mschannel9.vo.msecnd.net/o9/mix/09/wmv/key01.wmv|width=650|height=400]
This next macro will translate a literal string into a Visual XAML element:
[Xaml:string=<Rectangle Width="250" Height="250" Stroke="Black" StrokeThickness="1" Fill="Red" />]
And this last built-in macro would load up an external XAP file and present it’s main visual element:
[Xap:source=SilverlightTestApp.xap|type=SilverlightTestApp.MainPage]
SEO (Search Engine Optimization)
Silverlight weblog is fully indexable by Google, Bing and Yahoo.
Each Silverlight weblog has a Robots.txt and a Site Map which lets the search engine know of the available blog posts.
Each blog post page emits the proper HTML as to be indexed by google and accessible to disabled users.
In the following print screen you can see the Text-Only Webrowser Lynx fully reading the content of a Silverlight Weblog blog post:
If you’re interested in this SEO technique you can read more about it at Brad Abrams’ blog post.
Deep Linking and Back/Forward Support
When navigating in Silverlight Weblog the URL Anchor fragment changes accordingly.
Which enables Silverlight Weblog to support Refresh, Back and Forward uses.
Search Deep Linking
Category Deep Linking
Blog Post Deep Linking
Home Page Deep Linking
Google Analytics Support
Every user action performed in Silverlight Weblog can be logged into Google Analytics.
In the above print screen there’s a list of all User initiated actions (which did not cause a server postback) and have been logged in Google analytics.
Primarily, Loading Blog Posts, Performing Searches, Leaving Comments, Viewing categories and other user initiated actions.
Silverlight weblog also supports drilling down into specific google analytics data.
Here’s a drill down of which searches were performed and which categories were viewed:
On the left there’s a list of search terms searched, and on the right a list of categories viewed.
Management Back office
Using ASP.Net Dynamic Data an easy to use back office is generated for silverlight weblog.
Extensibility
Silverlight Weblog is fully extensible.
Each piece of the UI is considered a Widget and each response is an independent Service.
Widgets and Services communicate through Messages.
Both of which are loaded dynamically by MEF which ends up composing the UI.
I’ll go into greater detail on this topic in future blog posts, but here’s an easy to understand breakdown of the UI:
Implementing custom Widgets and changing the default layout and behaviour is much easier than it appears to be.
Personalized Widgets
Through the Extensibility mechanism in Silverlight Weblog I easily implemented two of my favourite widgets.
Custom Get Silverlight Screen
When first approaching a Silverlight Weblog, users will get an easy to understand “Get Silverlight” screen.
Customized Splash Screen
Silverlight Weblog supports changing the default loading splash screen into a more relevant user exprience.
In my case I wanted to let people know they were going into my blog.
Fin
There are many other features included in Silverlight Weblog.
Hopefully this first Silverlight weblog blog post was enough to give you a quick overview of this project.
One final note is I’d like to thank all Beta Testers who took part in making sure Silverlight Weblog actually works:
Scott Hanselman, Rob Eisenberg, Velvárt András, Yasser Makram, Rui Marinho, Ian Smith, Juan Puebla, Mark Woodhall and Jim Wightman.
Feel free to leave a comment and let me know your thoughts!
Sincerely,
-- Justin Angel
About Justin Angel
This is a place holder blog post for some interesting “About Me” information for Justin Angel.
In the meanwhile, here are some pictures of Justin.
Talking at Vancouver TechFest 2009 on Silverlight Unit Testing
Striking a pose at “Party With Palermo” MVP Summit 2008
Striking another pose with Joey Devilla at Coffee and Code Vancouver
Snowboarding (as such) in Whistler
Yeah, these poses only work if you photoshop in a fireball.