When writing VSTO projects the developers are asked to write their startup code in an innocuous event handler e.g. ThisDocumet_Startup. VSTO project does a good job of making you believe that this event handler is where the game begins. However, the class you are asked to write is a partial class and the other part of the class is automatically generated for you by Visual Studio. You can take a peek at the generated code if you click on the “Show All Files” icon on the Solution Explorer and look for a file that has a “designer” word in it. At the top of the class definition you would see it is derived from IStartup interface. All VSTO startup objects are required to implement this interface for the simple reason – this is the interface VSTO runtime uses to startup and shutdown customization.
In client-based application typical life cycle of an extensibility component goes through three stages: Startup stage, Interaction stage and Shutdown stage.
Host Application instantiates and initializes the extensibility component. During the initialization stage the component is passed in one or more objects that allow it to talk back to the host application. Such objects are known as entry points to the object model. The component than uses the object model to hook itself up to various events that the host application exposes and/or adds some User Interface elements such e.g. toolbars, menus, or event new top level windows with custom functionality which is populated with some data related to the user task. This stage is usually short. It is worthy to note that usually errors that might occur during this stage are critical and would prevent the component to load and function correctly.
This is where the component spends most of its lifetime. This stage is driven by events. As user interacts with the application various events occur and those trigger code inside the extensibility component. The code then might change the appearance of the user interface, bring in some more data or otherwise invite more actions from the user. Usually the errors are non-critical and while certain tasks may not be fully accomplished the component continues to run.
When host application terminates it shuts down the extensibility components as well. This is the time when the component would need to do the clean up of the resources it is holding to. Interestingly, some host applications may be in a half terminated stage when the extensibility component is being closed and accessing Object Model may not yield expected results.
But I am back to the IStartup. This interface has the 3 following methods that are called during the startup stage:
And 1 method that is called during the Shutdown stage:
VSTO customizations are not exactly like other extensibility components. One major difference is that VSTO customization might have several entry points. A good example is the VSTO Excel project where there is one ThisWorkbook class and number of Sheet classes. This has direct impact on the way IStartup class is designed. The startup happens in four phases:
First phase is when VSTO runtime constructs all the startup objects.
Second phase is when Initialize method is called on all the startup objects. During this phase startup objects should initialize its own controls, but not use any data that resides in other startup objects. Typical VSTO customization would hook up managed controls to their unmanaged counterparts, initialize the properties of Globals class and load cached data items.
Third phase is to call InitializeDatabindings. The name InitializeDatabindings is not particularly successful because the real intention is that controls consuming data from other startup objects can now be hooked up. The reason for the name is that in VSTO those are the data bindings that might consume cached datasets residing in other components.
Fourth stage is when FinishInitialization is called. This is when all the objects have been already fully initialized and all the controls defined in design time are ready to be used. It is time to party and invoke the user code!
Shutdown stage however consists of a single phase where OnShutdown method is called on each of the entry objects in exactly same order as specified by StartupOrderAttribute (TODO: name of the attribute).
It is left as an exercise to the reader to realize what determines the order in which objects are iterated during each phase 🙂
Last thing I wanted to say is related to unhandled exceptions. VSTO is not very tolerant in this regard. If an unhandled exception happens during either Startup or Shutdown stage the execution of the rest of the stage is aborted.