How to: Use Automation in Trusted Applications
Trusted applications can integrate with some native functionality of the host operating system. Starting in Silverlight 4, this native integration includes the ability to access Automation APIs on Windows operating systems.
Automation is a technology that applications use to expose functionality to scripting tools and other applications. For example, you can use Automation to add Office features to your Silverlight-based applications.
An application or component that exposes Automation APIs is called an Automation server, while an application that accesses these APIs is called an Automation client. The following topic describes how to enable your Silverlight-based applications to work as Automation clients.
Only trusted applications running on Windows can access Automation APIs, and only those exposed by components or applications that are already installed. In Silverlight 4 and earlier, trusted applications must also run outside the browser. Starting in Silverlight 5, system administrators can enable trusted applications to run inside the browser. For more information, see Trusted Applications and AutomationFactory.
Silverlight for Windows Phone and Silverlight 3 do not support trusted applications.
To determine whether Automation is available
Use the AutomationFactory.IsAvailable property as demonstrated in the following code example. The IsAvailable property indicates whether the application is trusted and is running outside the browser on a Windows operating system.
Public Sub New() InitializeComponent() If AutomationFactory.IsAvailable Then ' Use Outlook on a background thread to keep the UI responsive. Dim worker As New BackgroundWorker() AddHandler worker.DoWork, Sub(sender, e) If InitializeOutlook() Then SearchEmail() Else : Dispatcher.BeginInvoke( Sub() MessageBox.Show("Outlook is not available.") End Sub) End If End Sub worker.RunWorkerAsync() Else : MessageBox.Show("Automation is not available.") End If End Sub
To create or retrieve an Automation object
Call the AutomationFactory.CreateObject or AutomationFactory.GetObject method with a programmatic identifier (progID) that indicates the Automation server to use. These methods throw a NotSupportedException if Automation is not available, and throw an Exception if the specified Automation server is not available.
In general, CreateObject will start a new instance of the Automation server and GetObject will retrieve the most recently started instance. However, the exact behavior of CreateObject and GetObject differs for different components, so be sure to check the component documentation and test your usage thoroughly.
The example for this topic searches the user's Outlook inbox. This requires Outlook to be open, so the following code first attempts to retrieve a running instance by calling GetObject. If an exception is thrown, the code attempts to open Outlook by calling CreateObject and displaying the user's inbox. If a second exception is thrown, then Outlook is probably not installed.
The reference to the Automation server is stored in a variable of type Object in Visual Basic and type dynamic in C#. This is necessary because the type information is not available until run time. However, the lack of type information also prevents the use of IntelliSense and compile-time debugging, making the component documentation even more important.
Private outlook As Object Private Function InitializeOutlook() As Boolean Try ' If GetObject throws an exception, then Outlook is ' either not running or is not available. outlook = AutomationFactory.GetObject("Outlook.Application") Return True Catch Try ' Start Outlook and display the Inbox, but minimize ' it to avoid hiding the Silverlight application. outlook = AutomationFactory.CreateObject("Outlook.Application") outlook.Session.GetDefaultFolder(6).Display() ' 6 = Inbox outlook.ActiveWindow.WindowState = 1 ' minimized Return True Catch ' Outlook is unavailable. Return False End Try End Try End Function
To handle Automation events
Use one of the techniques demonstrated in the following code example. For more information, see the AutomationEvent class.
Events with return values are not supported.
Private Sub SearchEmail() UpdateStatusMessage("Searching Inbox for 'Silverlight'...") ' The following code demonstrates three ways to handle Automation ' events. In Visual Basic, all three ways use the AutomationEvent class. searchEvent = AutomationFactory.GetEvent(outlook, "AdvancedSearchComplete") ' The first way is demonstrated by the Handles clause of the ' SearchEvent_EventRaised method, which requires the WithEvents modifier ' on the searchEvent variable declaration. ' The second way uses the AddHandler syntax with the EventRaised event, ' and does not require the WithEvents modifier. ' AddHandler searchEvent.EventRaised, AddressOf SearchEvent_EventRaised ' The third way uses the AutomationEvent.AddEventHandler method, and ' requires the use of a delegate with an API signature that matches the ' Automation event. ' searchEvent.AddEventHandler( ' New AdvancedSearchCompleteDelegate(AddressOf SearchComplete)) ' Begin the search. outlook.AdvancedSearch("Inbox", "urn:schemas:mailheader:subject ci_phrasematch 'Silverlight'", True, "SubjectSearch") End Sub Private WithEvents searchEvent As AutomationEvent Sub SearchEvent_EventRaised(ByVal sender As Object, ByVal e As AutomationEventArgs) Handles searchEvent.EventRaised SearchComplete(e.Arguments(0)) End Sub ' Required only with the second two ways of handling Automation events. ' Private Delegate Sub AdvancedSearchCompleteDelegate(ByRef search As Object) ' Note: Visual Basic does not support the use of custom delegates for ' events with optional parameters. Private Sub SearchComplete(ByRef search As Object) Dim searchResults As New List(Of String) For Each result As Object In search.Results searchResults.Add(result.Subject) Next SetResultsList(searchResults) End Sub
The following code provides the helper methods and user-interface XAML used by the preceding code. To run the code in this topic, create a new Silverlight application project and then add all the code to the MainPage class.
Private Sub UpdateStatusMessage(ByVal text As String) UpdateUserInterface(Sub() message.Text = text) End Sub Private Sub SetResultsList(ByVal results As IEnumerable(Of String)) UpdateUserInterface( Sub() message.Visibility = System.Windows.Visibility.Collapsed items.Visibility = System.Windows.Visibility.Visible items.ItemsSource = results End Sub) End Sub Private Sub UpdateUserInterface(ByVal performUpdate As Action) ' Marshal to the UI thread, if necessary. If Dispatcher.CheckAccess Then performUpdate() Else Dispatcher.BeginInvoke(performUpdate) End If End Sub