Introduction
In the previous article we talked about COM automation support introduced in
Silverlight 4 and we said that COM automation is available only for Silverlight
OOB (Out-of-Browser) applications that have Elevated Trust, and that's one of
the security restrictions imposed by Silverlight.
Today, we're going to talk about COM automation in more details and give few
Silverlight examples that make use of this great feature.
Concepts
Finding COM Components
COM components expose their interfaces and classes via Windows Registry. COM
classes exposed to public available in this machine are registered in the
Registry at HKCR\CLSID (which is a repository for all COM classes registered in
this machine.) Because the machine may have thousands of COM components
installed, every COM class is identified with a GUID (Globally Unique Identifier.)
This GUID is very long and difficult to remember (it's something like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})
so COM classes are using another way to identify themselves; that is the ProgID
(Programmatic ID.)
ProgID for a COM class is a simple and clear string that identifies that
class and represents it. For example, Microsoft Word exposes its functionalities
through a COM class that you can reach it using the ProgID Word.Application.
So, instead of the GUID of a class, you simply refer to it using its simple and
easy-to-remember ProgID.
Then, how to find the right COM component? Or how to know if a COM component
exposes a certain functionality that I need? Google it, that's the only way! If
you are looking for a COM component that does something you need just google it.
And always have the COM component in your right hand, and have its documentation
in the other. And don't miss a chance to ask MSDN for help.
Accessing the COM Component
Now you have the COM component and know what to do with it. The next step is to
create a new instance from the COM class using its ProgID. This is can be done
using the AutomationFactory class found in the namespace
System.Runtime.InteropServices.Automation (exist in System.Windows.dll.) This
class exposes a few functions and only one property. The only property is
IsAvailable that returns whether or not COM is supported by the operating system
(COM is supported only in Windows.) Of the few functions AutomationFactory
supports, we care about only CreateObject() that takes the ProgID as an input
and returns the created object.
COM and Late Binding
When you assign an object to a variable that assignment can be made as
early-binding or late-binding.
Early-binding is that what you make every day and all the time. By default,
object assignment is made as early-binding, means that you create a variable of
specific type and bind that object to that variable. Then, the compiler always
knows the type of object assigned and the members (methods, properties, etc.) it
supports and that allows him to do some checks, optimizations, and perform some
memory allocations before application start.
In addition, early-bound variables can be thought as strongly-typed objects,
means that you can check for their exposed members, use some IDE features like
Intellisense and Object Explorer, and also receive compiler errors when you try
to make calls to members that don't exist (for instance.)
Late-binding on the other hand is made at runtime, means that the compiler
doesn't have enough information about the type at compile time. That means that
no type checks, no method lookups or Intellisense, no verifications, no
optimizations, and also no compilation errors from the late-bound object.
Is there any benefit from late-binding? Does it have anything to do with COM?
Actually, it's not as ugly as you think, it has lots of benefits and it also the
core of COM automation in Silverlight (and .NET 4.0 too.)
Late-binding allows you not to embed COM types and interfaces in your .NET
assembly, and that would help reduce your application size dramatically, and
also protects you from versioning fails and falling in the DLL Hell.
Worth mentioning that late-binding was introduced in .NET 4.0 via the dynamic keyword
and DLR (Dynamic Language Runtime)
libraries. Before .NET 4.0, late-binding was supported only via reflection.
Regarding Silverlight, late-binding was introduced in version 4 supporting
easier COM automation and HTML
DOM.
After all, to create a COM object in Silverlight you first ensure that
Microsoft.CSharp.dll and Microsoft.Core.dll are referenced to your project.
After that, you can call AutomationFactory.CreateObject() and assign the
returned object to a dynamic variable and start coding with it.
Preparing Your Project
Now, let's get to work. We'll now prepare a Silverlight application for
communication with COM components. Remember that this process requires a
Silverlight 4 application running as OOB and having the elevated trust.
Start with a Silverlight project and ensure that you have selected version 4
from the New Application dialog. (The application will run as OOB, so you can
safely uncheck the web application hosting option.)
Figure 1 - Creating New Silverlight Application
After creating the project, open project properties and from the bottom of the
Silverlight tab check the option "Enabling running application out of browser"
(check figure 2.)
Figure 2 - Configuring Silverlight to run as OOB
Then click Out-of-Browser Settings button and from the bottom of this dialog too
check the "Require elevated trust when running" option (check figure 3.)
Figure 3 - Enabling Elevated Trust
Now click OK and close project properties and save the project.
Next, add support for dynamic variables and late-binding feature to the project
by referencing Microsoft.CSharp.dll (and System.Core.dll too if it's not
currently referenced) in the project.
Figure 4 - Adding Reference to Microsoft.CSharp.dll
OOB Characteristics
First of all, you can launch your OOB application by clicking Run or pressing F5
(figure 5.)
Figure 5 - Running OOB Application
OOB applications can also run in a web page (by default, you'll redirect the
user to a web page where he can install the application to his PC.) Try browsing
to TestPage.html (in Bin\<debug|release>, check figure 6) or referencing the
project in web application Keep in mind that COM support is not available for
OOB applications running in the web.
Figure 6 - OOB Applications from the Web
When running OOB application from a web page the user can right click the
application and chooses to install it on his machine (figure 7.) This behavior
is the default, but you can disable it from the Out-of-Browser Settings dialog
(check figure 3.)
Figure 7 - Installing Silverlight OOB App
When trying to install an OOB application that requires elevated trust the user
may accept a security warning before the installation goes on (figure 8.)
Figure 8 - Installing Elevated Trust App
You can also order the application to launch the installation process via
Application.Install(), but this requires to be called in response to a
user-initiated action (e.g. clicking a button.)
-
Another great feature of ApplicationClass is
IsRunnignOutOfBrowser that returns whether the application is
running OOB.
Sample 1: Talking Apps
Our first example is an application that makes use of the speech API and speech
COM library, sapi.dll, to read a textual input from the user. The code
uses the SAPI.SpVoice class that has the Speak() function that we'll
make use of.
First, design a window that has an input text box and a button to read the text.
You might get help from the following XAML: