Export (0) Print
Expand All

How to: Use Automation in Trusted Applications

Silverlight

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.

Note Note:

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 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 MainPage()
    {
        InitializeComponent();
        if (AutomationFactory.IsAvailable)
        {
            // Use Outlook on a background thread to keep the UI responsive.
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += (sender, e) =>
            {
                if (InitializeOutlook()) SearchEmail();
                else Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show("Outlook is not available.");
                });
            };
            worker.RunWorkerAsync();
        }
        else
        {
            MessageBox.Show("Automation is not available.");
        }
    }
    
    
    

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 dynamic outlook;
    
    private bool InitializeOutlook()
    {
        try
        {
            // If GetObject throws an exception, then Outlook is 
            // either not running or is not available.
            outlook = AutomationFactory.GetObject("Outlook.Application"); 
            return true;
        }
        catch (Exception)
        {
            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 /* Inbox */).Display();
                outlook.ActiveWindow.WindowState = 1; // minimized
                return true;
            }
            catch (Exception)
            {
                // Outlook is unavailable.
                return false;
            }
        }
    }
    
    
    

To handle Automation events

  • Use one of the techniques demonstrated in the following code example. For more information, see the AutomationEvent class.

    Note Note:

    Events with return values are not supported.

    
    private void SearchEmail()
    {
        UpdateStatusMessage("Searching Inbox for 'Silverlight'...");
    
        // The following code demonstrates three ways to handle Automation 
        // events. The first two ways use the AutomationEvent class. 
        // The last two ways require the use of a delegate with 
        // an API signature that matches the Automation event. 
    
        AutomationEvent searchEvent = AutomationFactory
            .GetEvent(outlook, "AdvancedSearchComplete");
    
        // The first way: 
        searchEvent.EventRaised += (sender, e) =>
        {
            SearchComplete(e.Arguments[0]);
        };
    
        // The second way:
        // searchEvent.AddEventHandler(
        //    new AdvancedSearchCompleteDelegate(SearchComplete));
    
        // The third way:
        // outlook.AdvancedSearchComplete +=
        //    new AdvancedSearchCompleteDelegate(SearchComplete);
    
        // Begin the search. 
        outlook.AdvancedSearch("Inbox",
            "urn:schemas:mailheader:subject ci_phrasematch 'Silverlight'",
            true, "SubjectSearch");
    }
    
    // Required only with the second two ways of handling Automation events. 
    private delegate void AdvancedSearchCompleteDelegate(dynamic search);
    
    // To use custom delegates for events with optional parameters, you
    // must specify default values in the delegate signature as shown here:
    // private delegate void MyEventHandlerDelegate(int i, float f=77);
    
    private void SearchComplete(dynamic search)
    {
        List<String> searchResults = new List<String>();
        foreach (dynamic result in search.Results) 
        { 
            searchResults.Add(result.Subject);
        }
        SetResultsList(searchResults);
    }
    
    
    

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.


<Grid x:Name="LayoutRoot" Background="White">
    <TextBlock x:Name="message"/>
    <ListBox x:Name="items" Visibility="Collapsed"/>
</Grid>



private void UpdateStatusMessage(string text)
{
    // Update the message on the UI thread.
    UpdateUserInterface(() => { message.Text = text; });
}

private void SetResultsList(IEnumerable<String> results)
{
    // Hide the message and populate the results list on the UI thread.
    UpdateUserInterface(() =>
    {
        message.Visibility = System.Windows.Visibility.Collapsed;
        items.Visibility = System.Windows.Visibility.Visible;
        items.ItemsSource = results;
    });
}

private void UpdateUserInterface(Action performUpdate)
{
    // Marshall to the UI thread, if necessary.
    if (Dispatcher.CheckAccess()) performUpdate();
    else Dispatcher.BeginInvoke(performUpdate);
}


To use the C# dynamic keyword, your project must include a reference to Microsoft.CSharp.dll.

For security considerations in trusted applications, see Trusted Applications.

Community Additions

ADD
Show:
© 2014 Microsoft