Add-In Power
Let Users Customize Your Apps With Visual Studio Tools For Applications
Paul Stubbs
This article is based on a prerelease version of the 2007 Microsoft Office system. All information herein is subject to change.
This article discusses:
|
This article uses the following technologies: Visual Studio 2005, InfoPath 2007, C#, Visual Basic |
Contents
About Add-Ins
Learning with ShapeApp
More Add-Ins: InfoPath 2007
Getting Visual Studio Tools for Applications
M any software developers have increased the usefulness of their applications by making them customizable, usually through the addition of a technology like Microsoft® Visual Basic® for Applications (VBA). But these days VBA doesn't go far enough. You need a way to provide customers with better security, better development tools, 64-bit support, and generally more robust solutions—solutions that can be easily taken over by professional developers after a user's macro turns into an enterprise-critical tool.
Three application-customizing technologies are currently available from Microsoft: Visual Studio® Tools for Applications, Visual Studio Tools for Office, and VBA. Developers often ask how these similar-yet-diverse technologies address their specific needs. VBA is the oldest and most familiar. You can think of Visual Studio Tools for Applications as the .NET Framework alternative to VBA. Visual Studio Tools for Applications and VBA can run side-by-side within the same app. This enables apps that use VBA to add Visual Studio Tools for Applications support, allowing users to begin using Visual Basic or Visual C#® when they are ready.
The same team that created Visual Studio Tools for Applications also developed Visual Studio Tools for Office and the two technologies share a common architecture. However, Visual Studio Tools for Office is designed for developers who want to include Microsoft Office in custom solutions, while Visual Studio Tools for Applications is designed for end users of any application that includes it. For example, an accountant could add a new capability to accounting software by writing a function, without having to involve the company's development department. End users add new functionality by creating add-ins.
Visual Studio 2005 Tools for Applications is designed to meet developers' needs by offering application customization through .NET Framework-based code, which the end user can develop in a simplified Visual Studio 2005 development environment.
The list of requested features for every application is normally greater than the development resources available, so how do you satisfy the customers within your constraints? With Visual Studio Tools for Applications, your app users can create add-ins that meet their unique needs. Integrating Visual Studio Tools for Applications allows you to spend less time developing features for a minority of customers, makes it easier to empower users of your application as developers, and cuts the cost of bringing new developers up to speed on your application.
There are really two aspects to using Visual Studio Tools for Applications. The first involves integrating it into your application. This means deciding what the experience will be for those who will develop solutions for your application. The second aspect is what the end user developer (the person who is using your application and wants to customize it) will see. You design the development experience for the user through the decisions you make during the integration phase. For illustration purposes, I'll show you an example of the choices made by the developers of Microsoft Office InfoPath® 2007 when they integrated Visual Studio Tools for Applications into InfoPath.
About Add-Ins
As mentioned, the vehicle for new functionality is an add-in. The term add-in has different meanings depending on context, but Visual Studio Tools for Applications uses the term "add-in" or "customization" to mean any component that is dynamically loaded by an application. The application that loads the add-in is called the host application. Application-level add-ins are familiar to users of Office in the form of COM add-ins.
Add-ins always have a lifetime. For example, an add-in can have an application-level lifetime, meaning that it loads when the application starts and unloads when the application stops. Add-ins can have a narrower lifetime as is the case with Visual Studio Tools for Office-based Word and Excel® solutions, whose lifetime is tied to a document. Add-ins can also be scoped to apply to only a portion of a host application's object model. In an application like Word, for example, application-level add-ins would be scoped to the Application object and document-level add-ins would be scoped to the Document object. An easy way to think of the scope is that it is the object returned when you reference the "Me" keyword in Visual Basic or the "this" keyword in C#. These are just two examples of lifetime and scope.
The host application is free to include add-ins with any lifetime or scope. For instance, you can implement add-ins scoped to forms or even dialog boxes. Visual Studio Tools for Applications makes no restrictions on the host application and is flexible enough to handle a wide-variety of scenarios.
Visual Studio Tools for Applications provides classes that let the host application load and unload add-ins dynamically. The default behavior loads each add-in into its own application domain, which provides isolation between the host and the add-in and between other add-ins. Application domain isolation prevents the add-in from interfering with the host application and enables the add-in to be unloaded from memory. Other add-in loading models enable various levels of isolation by allowing multiple add-ins to be loaded into the same application domain or even the host's application domain. Add-ins may even be loaded into an application domain in a process outside of the host's application process, which provides the greatest isolation.
As more applications move to 64-bit processors, the ability to load 64-bit add-ins becomes increasingly important. Visual Studio Tools for Application supports creating and loading 32-bit, 64-bit, or bit-neutral add-ins. Bit-neutral is the default behavior and allows the add-in to run in either a 32-bit or a 64-bit process.
The add-in loader is defined in the System.AddIn namespace and is contained in the System.AddIn.dll assembly. This namespace will ship first with Visual Studio Tools for Applications and then as part of WinFX®. The components that will ship as part of WinFX are collectively known as the Managed Add-In Framework (MAF). MAF allows you to create new versions of add-ins independent of the host application's version. MAF also lets add-ins dynamically load and unload in a secure manner. MAF uses contracts as the immutable piece that allows independent versions. The contracts are defined in the System.AddIn.Contract namespace and are contained in the System.AddIn.Contract.dll.
Contracts enable proxies and adapters to communicate across application domains. Proxies and adapters are the pieces that enable add-ins to communicate with the host application (see Figure 1). Visual Studio Tools for Applications includes a command-line tool called Proxygen.exe that takes your app's object model as input and creates the proxies as C# source code files. You can then modify the proxies to suit your needs. Proxygen.exe can also generate an XML-based descriptor file that represents your object model. The proxy descriptor file can be the sole input to Proxygen.exe, letting you get the proxy you need by manipulating the input descriptor file or the generated C# file or both.
Figure 1** Add-Ins Communicate with the Host App **
Adapters implement the System.AddIn.Contract interfaces that the proxies call into. Proxies and adaptors hide the implementation and complexity of using contracts from the host application and the add-ins. The proxy provides a friendly view of the host application's object model as well as a good place to optimize cross-boundary calls by implementing techniques like caching. Each part is packaged in a separate assembly. The proxy is used as the base class for the add-in assembly, which is created using Visual Studio Tools for Applications.
Visual Studio Tools for Applications contains a subset of features normally contained in the Visual Studio 2005 development environment, but otherwise it looks and operates much like the familiar Visual Studio IDE (see Figure 2). You can embed the Visual Studio Tools for Applications environment into your application to give your users a seamless add-in development environment of their own.
Figure 2** Coding a Macro in Visual Studio Tools for Applications **
Like VBA, the Visual Studio Tools for Applications environment can be launched from within your host application using a key combination like Alt+F11. Unlike VBA, Visual Studio Tools for Applications can also be launched from the Start menu, giving users a development model more like Visual Studio. You are free to choose the level of integration appropriate for your application and your end users.
A benefit of having a common architecture with Visual Studio is that you can open Visual Studio Tools for Applications projects in other versions of Visual Studio. This solves a problem often encountered when using VBA in the enterprise: someone creates a VBA-based solution for personal or limited workgroup use. The solution becomes so successful that it begins to see wider distribution, but it isn't able to scale or may not comply with corporate security or other standards. Another possible complication is that the team responsible for corporate-wide solutions may not be familiar with VBA. In such cases, the common response is to rewrite the customization entirely.
These problems disappear if the host application employs Visual Studio Tools for Applications projects. Visual Studio Tools for Application projects are true Visual Studio projects. Developers can open a Visual Studio Tools for Applications project using the full version of Visual Studio to add enterprise features like unit testing and performance testing.
Learning with ShapeApp
ShapeApp is a sample app included in the Visual Studio Tools for Applications SDK. This drawing program allows you to drag shapes onto a drawing surface (see Figure 3).
Figure 3** ShapeApp Sample App **
There are two versions of ShapeApp, one written in C++ and one written in C#, and there are three samples for each version. ShapeAppCSharp.zip and ShapeAppMFC.zip contain the source code projects for the ShapeApp application with no Visual Studio Tools for Applications modifications. Walkthroughs in the documentation use these projects as a starting point to take you through integrating Visual Studio Tools for Applications.
ShapeAppBasicCSharp.zip and ShapeAppBasicMFC.zip contain the source code projects for ShapeApp with a basic implementation of Visual Studio Tools for Applications. This is the end result of the walkthroughs, so if you just want to see a running sample, skip the walkthrough and look at this instead. The basic implementations focus on creating an application level add-in. The walkthrough shows you how to use the add-in manager to load and unload add-ins and how to create MAF-enabled proxies for your object model.
This sample also takes you through the steps to create Visual Studio Tools for Applications project templates for your add-in. These templates are regular Visual Studio project templates. They're the ones you see when you open the New Project dialog box in Visual Studio. Project templates are used to create a project instance.
ShapeAppAdvancedCSharp.zip and ShapeAppAdvancedMFC.zip contain the source code projects for the ShapeApp application, integrating some of the advanced features of Visual Studio Tools for Applications.
More Add-Ins: InfoPath 2007
You can also try out an example of Visual Studio Tools for Applications integration by looking at InfoPath 2007. I'll walk you through the process of creating an add-in so you can see the type of experience that Office designed—but keep in mind that this is not the only way that the user experience can be designed. All you need to follow along is a copy of InfoPath 2007.
InfoPath lets you design and fill out structured data forms. Unlike most Office applications, InfoPath does not support VBA. Instead it supports JScript® and VBScript out of the box and uses Microsoft Script Editor. Starting with InfoPath 2003 Service Pack 1 (SP1), you could download the InfoPath 2003 Toolkit for Visual Studio .NET 2003, which lets you create solutions in Visual Basic or C#. The toolkit was updated for Visual Studio 2005 and was included with Visual Studio 2005 Tools for Office. InfoPath 2007 includes Visual Studio Tools for Applications, so you can create applications in Visual Basic or C# using the embedded Visual Studio Tools for Applications environment. Figure 4 shows what the development environment and code look like when you press Alt+Shift+F12 while in design mode.
Figure 4** Using Visual Studio Tools for Applications with InfoPath 2007 **
Let's create a simple InfoPath form and customize it using Visual Studio Tools for Applications. InfoPath includes a number of sample forms, so we'll start with one of these. On the File menu choose Fill Out a Form, and then choose Customize a Sample. Select SampleForm, then the Meeting Agenda form. Click Design this Form from the tasks on the right. Now you can see the sample form in design mode.
Press Shift+Alt+F12 or click Tools | Programming | Microsoft Visual Studio Tools for Applications to open the development environment. You'll be prompted to save your form first. Click OK and choose a name and location to save your form. The development environment opens with Visual Basic as the default language. You can switch between C# and Visual Basic as the default language in InfoPath by selecting Tools | Options | Design.
At this point you'll see that InfoPath has generated some code, which is shown in Figure 4. It has added a few Import statements to reference the InfoPath object model and the XML classes in the .NET Framework. The namespace matches the name of your form, and a class called FormCode contains an InternalStartup method. InternalStartup is where InfoPath will add the event handlers. Pressing F5, or clicking Debug | Start Debugging, will compile the code and start debugging your InfoPath form in Preview mode. At this point the preview form will open, but nothing else happens because you haven't written any code yet.
So now let's go ahead and add some code to the form. Switch focus back to Visual Studio Tools for Applications and press Ctrl+Alt+Break or Debug | Stop Debugging. When the debugger stops it will close the Preview mode of the form. The first thing we'll do is display a simple message box when the form is loaded (see Figure 5). You can get InfoPath to create the form-loading event by clicking Tools | Programming | Loading Event from the design view of the form. Add the code to show the message box to the FormEvents_Loading method. This method will be called when the form opens.
Figure 5 Simple Message Box
C#
public void InternalStartup()
{
EventManager.FormEvents.Loading +=
new LoadingEventHandler(FormEvents_Loading);
}
public void FormEvents_Loading(object sender, LoadingEventArgs e)
{
MessageBox.Show("The form has loaded");
}
Visual Basic
Private Sub InternalStartup( _
ByVal sender As Object, ByVal e As EventArgs) Handles Me.Startup
AddHandler EventManager.FormEvents.Loading, _
AddressOf FormEvents_Loading
End Sub
Public Sub FormEvents_Loading(ByVal sender As Object, _
ByVal e As LoadingEventArgs)
MessageBox.Show("The form has loaded")
End Sub
Run the form now by pressing F5 and you'll see that the message box is displayed before the preview form loads. Click OK to close the message box and allow the form to finish loading. At this point your code is complete and attached to the form. You could close Visual Studio Tools for Applications and the code would still run whenever you switch to preview mode.
That's how easy it is to get started. Now let's try adding code that's a bit more complicated to this scenario. The sample form has a Prepared By field. On the loading event I want to populate the project name, manager name, and department name. As you can see in Figure 6, I have created a helper function called SetFieldValue to make it easy to set the value to multiple fields. I can call SetFieldValue on the loading event, passing in the new value and the XPath to the field. So how do you know what the XPath value should be? You can find the XPath value by selecting the field in the design view of InfoPath and showing the Data Source task pane. The Data Source task pane displays a tree view of the data fields. Right-click on the field you're interested in and choose Copy XPath from the context menu. Paste this XPath expression into code where you need to reference a field.
Figure 6 Using SetFieldValue to Populate Multiple Fields
C#
public void FormEvents_Loading(object sender, LoadingEventArgs e)
{
MessageBox.Show("The form has loaded");
SetFieldValue("VSTA Overview",
"/my:meetingAgenda/my:meeting/my:meetingTitle");
SetFieldValue("Paul Stubbs",
"/my:meetingAgenda/my:meeting/my:meetingOrganizer");
}
private void SetFieldValue(string value, string xpath)
{
XPathNavigator root = this.MainDataSource.CreateNavigator();
XPathNavigator field = root.SelectSingleNode(xpath,
this.NamespaceManager);
//set the value
field.SetValue(value);
}
Visual Basic
Public Sub FormEvents_Loading( _
ByVal sender As Object, ByVal e As LoadingEventArgs)
MessageBox.Show("The form has loaded")
SetFieldValue("VSTA Overview", _
"/my:meetingAgenda/my:meeting/my:meetingTitle")
SetFieldValue("Paul Stubbs", _
"/my:meetingAgenda/my:meeting/my:meetingOrganizer")
End Sub
Private Sub SetFieldValue(ByVal Value As String, ByVal xpath As String)
Dim root As Xml.XPath.XPathNavigator = _
Me.MainDataSource().CreateNavigator()
Dim field As Xml.XPath.XPathNavigator = _
root.SelectSingleNode(xpath, Me.NamespaceManager())
field.SetValue(Value)
End Sub
This is just one way to design the development experience. You can provide basic functionality or you can add advanced features such as macro recording to help your users. Visual Studio Tools for Applications gives you the tools, but what you create is completely up to you.
Getting Visual Studio Tools for Applications
Visual Studio Tools for Applications is included in the Visual Studio 2005 SDK, which you can download from the MSDN® Extensibility Web site at (msdn.microsoft.com/vstudio/extend) though you'll need to register for free as a VSIP affiliate member). The SDK contains the Visual Studio Tools for Applications setup package. Running the package installs the Visual Studio Tools for Applications development environment and runtime. The SDK also contains the help documentation and sample applications. The help file walks you through the process of integrating Visual Studio Tools for Applications into your application. You'll also find tools to help with the integration process: Proxygen.exe creates the MAF proxies from your object model; Projectgen.exe generates Visual Studio Tools for Applications project templates to create add-ins.
The Visual Studio SDK contains help and samples for customizing Visual Studio and many of these topics relate directly to Visual Studio Tools for Applications as well. You'll find information about creating custom help, project templates, project wizards, and profiles, all of which will be needed to create a seamless development experience for your end users.
Visual Studio Tools for Applications is the way to provide end users with a powerful and flexible customization experience that helps them get what they want from your application. The Visual Studio Tools for Applications development environment and the .NET Framework give your users tools for rapid development in an environment that helps keep applications secure. The result is that your app is tailored for each user in a way that can be expanded to be enterprise ready at any time—and you didn't have to add any new, unplanned features to your app to let them do it.
Paul Stubbs is a program manager with the Visual Studio Tools for Applications team at Microsoft and also works with the Visual Studio Tools for Office team developing Office solutions. He has spoken at Tech·Ed and TechReady and participates in the developer community on the Microsoft forums. Read Paul's blog at blogs.msdn.com/pstubbs.