Visio 2003 Developer's Survival Pack

NETVSL Adapter Introduction: Build VSLs Using .NET
(aka VBVSL Adapter for .NET)
   This page

Contents

Overview

As you may have read in Chapter 22, there are a number of potent reasons why you may want to house your solution's functionality in a Visio Solution Library (VSL). 

The superficially similar alternative is the COM Addin, but a COM Addin solution would rely on QueueMarkerEvent in order to serve the ShapeSheet, and also to serve the UI properly. This requires each such COM Addin to run on every Visio startup in order to register to see those QMEs, and also means that Visio has to send every actual MarkerEvent to each such COM Addin (or the solution has to make finesseful use of Visio event filtering to reduce this burden).

All in all, COM Addins are problematic, and indeed many (if not most) of the addon functionality in Visio 2003 continues to be supplied as VSLs. (They now have plain "dll" extensions, but Dependency Walker shows that they have VisioLibMain entry points, so Visio calls them as VSLs).

However, for all the virtues of the VSL form of solution, as further discussed in Chapter 22, the interface between Visio and VSLs is a DLL interface that can't be built in VB6 directly.

For the Visio 2002 edition of "Survival Pack", this prompted me to introduce an "adapter" component called VBVSL adapter. The basic notion is that this adapter looks to Visio like a VSL, and in turn the adapter is able to call solution functionality in an ActiveX component -- which is something that VB6 can build.

Please see Chapter 22, particularly Fig 22-1 on page 330, for a quick understanding of how this arrangement is structured.

Developers who have moved on to .NET naturally wondered how they might build VSLs using the increased power of that platform and framework.

Like VB6, VB.NET and C# cannot directly create a VSL DLL. However, since .NET can build ActiveX components, it was not long before developers attempted to use the VBVSL adapter to bridge between Visio and VSL functionality housed in a .NET component.

This initially seemed to work satisfactorily, at least on development machines. However, it was later learned that the .NET components built this way run afoul of problems in the .NET component installation process, and hence are not easily deployable.

This current page, and attached downloadable components are a step to solving that problem.

Perspective, Caveats, Disclaimer

The NETVSL approach described here is really the third choice in a list of preferences as to how one would approach this problem:

1. Better Visio VSL Interfaces The prefered approach would be for Visio to implement VSL-like interfaces direct to ActiveX and .NET components. This hasn't happened. It may be that the inclusion of the Office-wide COM Addins interface too the wind out of inproving the VSL interface, but regardless, we don't have this ideal approach.
 
2. NETVSL Adapter direct to .NET If we are going to have an adapter, then why does it talk to ActiveX rather than directly to .NET components? This is primarily due to a limit in my knowledge, time and patience. At this writing, so far as I am aware, the only plausible way to build an adapter with a raw DLL interface on one side, and .NET components on the other, is using Visual Studio .NET C++. It looked like it was going to be a considerable detour to understand how to do that, which I didn't have time to embark upon.  If someone with C++ savvy wants to take a crack at it, please contact me to get a head start.
 
3. NETVSL talks to COM (ActiveX) The approach described here.

Disclaimer:  Please also realize that this is not a commercial component, it is a helper component supplied to support the material presented in by Survival Pack book. The concept has been tested in the VBVSL Adapter component that has enabled a number of solutions, and the NETVSL adapter component is a minor modification to this. However, this new component, and the sample code and base classes supplied here should be considered at a beta-level of preparedness, particularly because having Visio call .NET is relatively unexplored (though promising) territory.

The supplied samples should allow you to determine, with mininal investment of effort, whether these components do something useful for you. Please test cautiously when moving beyond that.

Problem Details; Solution Approach

The basic nature of the problem was this: I had designed the VBVSL interface to be as much like the original VSL interface as possible, including the aspect of having the ActveX solution module able to call back into Visio for several functions. To permit this, the VBVSL Adapter provided the solution module with an object to call when needed. VB6 components can do this just fine.

But for .NET components, it means that managed code in the .NET component would be calling unmanaged code in the adapter (and ultimately in Visio for that matter). The installer would see this and not provide a way to permit this arrangement to be installed.

The basic approach I've take to work around this is to eliminate the need for the VSL solution code component to callback into the adapter.

In some cases this is not a problem, because the information provided via the callback is either not very important, or can be obtained by having the adapter call the solution component instead.

In a couple of other cases, the callback info is actually needed, and is not simply a response to a call from the adapter. Here I've replaced the callback with periodic polling by the adapter. Not so tidy, but seems to do the job.

Solution Details

As with the first version of VBVSL, the main innovation provided by the adapter is to define ActiveX objects by which adapter and your solution functionality can communicate.

In VBVSL, I defined an ActiveX object (actually an "interface" called IVBVSL) that your solution must provide (and register) for the adapter to find and call. (The available sample code provides a generic IVBVSL implementation in VB6... your solution just needs to fill in the blanks).  I also define another interface (IVVA_Callback) which your solution must request from the adapter, in order to communicate some info back to the adapter.  The design was intended to mimic as closely as possible the "real" VSL DLL interface defined by Visio.

NETVSL defines only the .NET interface that your solution  must satisfy, which in turn the .NET framework provides a COM/ActiveX interface for that the Adapter can find. This is a little less like Visio's native VSL API, since it replaces some callbacks with other methods to handle the same communication. (Parallel to VBVSL, a generic NETVSL class is provided in the sample code for this article, your solution just needs to fill in the blanks.)

Below is a summary of how the "native" VSL API features correspond to the NETVSL features, corresponding to Table 22-1 on page 329.

Message from Visio via VSL API Supplies Arguments Description Normal VSL Action or Response NETVSL Implementation, action for the solution code
LOAD VSL API version
Callback function
Visio sends this message when first loading a VSL. This might be at startup, or when Visio wants to survey VSLs (see ENUMADDONS), or when preparing to call RUN for the first time. Earilest opportunity to initialize itself. Can return success or failure INETVSL.Load
UNLOAD none Visio sends this just before unloading a VSL, usually prior to quitting. Last opportunity for VSL to clean up. INETVSL.Unload
ENUMADDONS Callback function Here Visio requests the VSL to callback with information about each VSL's Addons Normally, the VSL is expected to call Visio's callback function once for each Addon, supplying Addon's name, a unique Addon Id number, and various flags specifying when Addon can be called. Adapter acquires this info from solution by calling:
INETVSL.AddonCount
INETVSL.GetAddonInfo
(sample implements this for you, your code just has to initialize the parameters)
ISAOENABLED Addon Id One way for Visio to determine whether the Addon is enabled Responds whether Addon is enabled. (Addon can check state of Visio, such as whether document is open, to determine whether it's OK for Visio to call). INETVSL.IsAddonEnabled
Your code can default to always enabled, or set this more deliberately.
RUN Addon Id
Session Id
Callback function
"Command line" args
This is the most important part of the API. Visio sends this message as a result of the RUNADDON ShapeSheet function, or UI, XxxItem.AddonName, or Event.Target. VSL directs this info to the appropriate Addon functionality, which uses the arguments to decide what to do. If Addon wishes to be non-modal (eg: non-modal form) then it remembers the the Sesion Id and responds with "I'm going modal" return value. INETVSL.Run
This is where the main solution functionality gets invoked.
... later   If previous Run caused Addon to go "non-modal", then that Addon must later tell Visio that's it has finished. This is a callback in the Visio-to-VSL API. When non-modal form closes, Addon calls the callback function with Session Id to say "OK, I'm finished now". Adapter calls INETVSL.
PollNextEndSessionMessage
Sample provides a way for your solution to queue EndSession messages.
KILLSESSION Session Id Visio uses this to explicitly tell non-modal Addon sessions to close. VSL must locate the non-modal form (or other Addon functionality) associated with that Session Id, and close it. Visio ignores the return value. INETVSL.KillSession
Your solution code should tidy up and release resources here.
RUNABOUT; RUNHELP Addon Id Visio uses these only from the buttons on the developer-oriented Tools > Addons > RunAddon dialog. These have been deprecated for a few versions, on the way to being phased out. VSL can show About or Help dialogs for the Addon specified. Not implemented

From Here

Go back up to the Table of Contents, and proceed to download and install the samples, or on to the code discussion.


Article Created: 2004-01-15  Last edit: Last edit: 04-02-24 Graham Wideman
Go to:
  DiagramAntics.com