In this new series, Dermot explains how to integrate
a programming language into Visual Studio 2005. Part
One: The Basics (see also: Part
Two) |
Microsoft isn’t shy about advertising its merits.
Not usually, anyway. But it’s made an exception
for one part of Visual Studio. You’d be hard pressed
to find much of a mention of this in the press, but you
can now customise and extend Visual Studio 2005 to a
far greater extent than before. I don’t mean the
usual ‘automation’ stuff, called from a Visual
Basic for Applications (VBA) script, either. What we’re
talking about are full blown programmatic extensions
to Visual Studio. You can get Visual Studio to host a
Cobol environment, an Oracle PL/SQL development system
or an implementation of your favourite ‘ology’ – complete
with boxes and interconnecting squiggles.
There are three ways to extend Visual Studio:
- First, there’s the simple macro approach. You
record a few keystrokes and attach them to a key. Press
the key and your key sequences are repeated. It’s
simple, easy to do and use but limited in its scope.
- Second, there’s the ‘automation’ model.
Like Office, Visual Studio has a COM model which can
be called from a scripting language such as VBA. You
can access most of the document/code windows in Visual
Studio and do quite a lot of neat stuff with automation.
The problem is that it’s still an add-on.
You can’t fundamentally override the way the
debugger works for example.
- The third way is by far the most interesting. It’s
Visual Studio Extensibility or Visual Studio Industry
Partners (VSIP).
As usual with Microsoft, the names seem a little confused. ‘Extensibility’ can
refer to the whole thing – macros, automation and
the VSIP program - or just the VSIP bit. And VSIP refers
to ‘Industry Partners’ or ‘Integration
Package’. Whatever its name, to get at the most
interesting bits, you have to download the Visual Studio
SDK. And to get this you have to register with Microsoft
as an ‘Affiliate’ (start here: http://msdn.microsoft.com/vstudio/partners).
It’s free, relatively painless and at the end of
the registration, you can down load the VSIP SDK - about
85MB in size.
Just in passing, I’d note that the Industry Partners
thing has been around at least since Visual Studio 2003.
It’s just that in Visual Studio 2005, Microsoft
has opened it up a good bit more and made it a lot more
accessible and usable.
At the time of writing (February 2006), the VSIP SDK
isn’t finalised – it’s being rolled
out on a two month ‘refresh’ cycle, so you
may have to put up with some rough bits (mainly in the
documentation and examples) and one or two bugs. The
latest February SDK is pretty good though. Personally,
I rather approve of the rolling release cycle. I’d
far rather have something that’s pretty usable
but not finished than have to wait about a year for the
final product.
Packages
The key feature with the VSIP SDK is that you can define
a Visual Studio ‘integration package’ – something
that can be loaded when you create a new project. For
example, C# or Visual Basic would be considered packages.
Once
you’ve registered with Microsoft
and downloaded the SDK, you can create your own integration
package, just like Visual Basic or C#.
But before you leap in and start producing your very
own Visual Basic++, there are a couple of things to be
aware of. First, before you can distribute any package
you’ve built, you need to obtain a ‘product
license key’ or PLK. Once you’ve installed
the SDK, you’ll see a message on the splash screen ‘VSIP
License Required’. In effect, when you download
the SDK, you get a ‘development’ PLK (also
known as a DLK) which allows you to load your new
package on a machine with the SDK installed. To get a
production PLK you have to again apply to Microsoft – and
it may (or may not) grant you one. I have to say that
I don’t really understand the reasoning behind
this – a PLK seems a pretty innocuous thing to
me. Possibly a touch of paranoia?
Second, read the licence conditions. The licence isn’t
the usual ‘we can do anything we want even though
you’ve paid us good money’ sort of thing.
You have to agree to produce code of a decent quality,
incorporate your splash logo and not disable PLKs. All
reasonable stuff, really, and I suppose most of it’s
there to protect Microsoft’s Visual Studio reputation.
In particular, it seems that you can produce ‘open
source’ implementations provided you don’t
try and GPL (the GNU licence) Microsoft’s source
code.
Third, you should have at least a working knowledge
of COM. Visual Studio is predicated on COM interfaces:
Visual Studio lives, breathes and is COM. While
you can get some way without knowing what COM stands
for, at some point you’ll need to at least know
what an ‘interface’ is and how to use one.
This last point has made adding things to Visual Studio
difficult in the past. Unless you are a COM/C# expert,
the best way of using a non-trivial COM interface is
via C++. However, if you are using C++ and COM that probably
means that you already are an expert. Somewhat circular,
really – and it can be a little difficult to break
into the circle.
Of course you can indeed use COM interfaces in C#, but
I’ve found that debugging these can be tricky – you
really need to see both sides of the COM interface if
you have a problem. Also, you’ll find that not
all COM types are supported by the CLR. One way round
this is to write a C++ ‘shim’ that allows
you to intercept and possibly modify the COM call before
it goes into C#. Still, the Visual Studio COM interfaces
are not simple – and there is a good number of
them to master. So, in the past, unless you were pretty
knowledgeable about COM, building a VSIP was far from
simple.
With the Visual Studio 2005 SDK, Microsoft
has engineered a decent solution to the skill level problem
needed in using the Visual Studio COM interfaces from
managed code. There is a new ‘managed package’ interface
that allows you to use the Visual Studio COM services
from C#. This is implemented via some C++ plus a good
few C# classes. It really does simplify the way you can
build a VSIP. After some initial scepticism, I was won
over: the managed package framework is excellent.
Starting off
So now you’ve got the Visual Studio SDK installed,
what next? There isn’t anything like an ‘idiots
start here’ page and, while the documentation is
reasonably comprehensive (and growing), it can
be downright confusing. The main problem is that the
managed package stuff is thrown in with the COM interface
part, so at one moment you can be reading how to do something
in C# and at the next moment you’ll find yourself
directed to an obscure and ill-documented COM interface.
There are a number of sample applications to
start from. Just select the most appropriate and use
that as a base.
The good news is that there are plenty of example applications
to chose from and, depending on what you want to do,
it’s best to choose one of these. The first one
I’ll look at here is the ‘Reference Package’ project.
You’ll find this in the \VisualStudioIntegration\Samples\IDE\CSharp subdirectory
of the SDK installation. Load up Package.sln in
Visual Studio 2005. This illustrates a number of important
VSIP points. The first thing you’ll see in the
BasicPackage.cs file are the following lines:
[MsVsShell.DefaultRegistryRoot(@"Software\Microsoft\VisualStudio\8.0Exp")]
[MsVsShell.PackageRegistration(UseManagedResourcesOnly
= true)]
[Guid("01069CDD-95CE-4620-AC21-DDFF6C57F012")]
public
class BasicPackage : MsVsShell.Package {
…
All packages have to start off deriving from the
Package class. This
implements about a half-dozen or more Visual Studio COM
interfaces so you don’t
have the hassle of doing that. So here we’ve got
BasicPackage as
our fundamental class - you’d typically rename
this to MyWonderfulProjectPackage or whatever.
Now look at the three lines above the class declaration.
The first one declares which registry ‘hive’ we’re
going to use:
[MsVsShell.DefaultRegistryRoot(@"Software\Microsoft\VisualStudio\8.0Exp")]
It puzzled me when I first came across
VSIP as to how you can develop an extension for Visual
Studio without screwing up Visual Studio itself. The
answer is that first of all Visual Studio stores all
the information it requires about what products it’s
got installed, what languages it knows about, etc in
the registry. In particular, it stores the whole shebang
under a key Software\Microsoft\VisualStudio\8.0 for
VS 2005. But – and this is really neat - you can
specify which key Visual Studio should look under by
starting Visual Studio from the command line like this:
devenv /rootsuffix exp
This tells Visual Studio to look under the 8.0Exp key
for its information and so you can keep code that you
are developing completely separate from the code that
is doing the developing, so to speak. You’ll almost
certainly screw up the experimental registry in your
first few attempts at working in VSIP, and you’ll
be relieved to know that the experimental registry can
be completely reset via an SDK menu command. This is
nearly foolproof. Except, ahem, for the fool writing
this. A word of caution: don’t try and test your
package deployment into the non-experimental (production)
VS hive on the same machine that you are developing on.
I did – and I ended up having to remove and re-install
the whole of Visual Studio after about a week of bizarre ‘impossible’ events.
Visual
Studio stores the data it needs to develop Visual Studio
Integration Packages under a separate ‘experimental’ Registry
hive. If you screw up, it can be reset without affecting
your main development environment.
Back to the example: the next line sets another attribute – it
tells Visual Studio whether any user interface commands,
etc., are in a satellite DLL:
[MsVsShell.PackageRegistration(UseManagedResourcesOnly
= true)]
This is the way things
used to be done; but, fortunately, all resources can
be merged into a single assembly now. Setting this to true means
that there is no satellite DLL and everything is neat
and tidy.
The last attribute line declares a GUID (Global Unique
IDentifier) for the class:
[Guid("01069CDD-95CE-4620-AC21-DDFF6C57F012")]
Don’t forget Visual
Studio is COM based and COM means GUIDs. Lots and lots
of GUIDs. Visual Studio expects the Registry to contain
information about your package under a registry key Packages and so you must provide a GUID for it. Also, when you
come to request a PLK for you finished product, you’ll
need to provide this particular GUID to get a key, so
don’t use the one in the reference package example.
You can create your own easily enough in Visual Studio
via the Tools/Create GUID menu item.
When you build your package, the MSBuild system will
register these attributes in the experimental Registry
hive automatically (I’ll look at the remarkable
MSBuild – another well-hidden Visual Studio technology
- in a later article). In passing, it’s interesting
to note the use of attributes as a ‘declarative’ style
of programming. Here, you don’t explicitly program
a piece of code, instead, you declare what you want and
something else comes along later and does it for you.
The more the better: it removes a whole raft of rather
boring coding from the program.
With
Visual Studio 2005, Microsoft has completely redone the
old makefile system for building projects, replacing
it with the new MSBuild. It’s pretty
damn good too.
You can build and run this example application from
the SDK, but it doesn’t do a great deal. In fact,
it doesn’t do anything at all. In order to, say,
get the project to display in the list of available projects
under Project/New menu, we have to do a bit more work.
As I’ve commented above, the SDK is still a work
in progress but not having a functioning basic reference
project under the heading ‘Reference.Package’ is
a little odd. However, if you do a bit more ferreting
around, you’ll find an example that does the job.
It’s carefully hidden away under VisualStudioIntegration\Archive\CS_Samples\Project.
I’ll look at using that next
month to get a simple
text editor with some text colouring.
March 2006 |