Adventures in writing managed VSIP packages
It has been a little too long since I last made a post. A lot has been going on since the last time I wrote, mostly I have been working on getting bugs fixed for the “Whidbey” build of VS, and work has been proceeding on a new wizards tool for VS (while my last post said I would have some information about this wizard, we decided to wait for any announcements about it). Another task that has consumed my time is my IL editor/project sample. As you may know, I have been working on an IL editor and project system sample. If we get a Whidbey version of our book, then any chapters about VSIP will discuss these samples, and I am looking into getting them into a future version of the VSIP SDK. All major work on these samples were completed over the weekend, and only some minor bugs remain. As I mentioned before, the samples that I have been working on were written using ATL, but after some careful thought I decided that they should be converted to C#. So last night I got the latest build of the Everett Extras (interop assemblies for programming the Everett VSIP model – for now I am doing my development against the Everett version of VS) and sat down to convert my existing code from C++ to C#.
Converting the text editor took me a total of about 4 hours. 4 hours! I was expecting it to be much more complicated than it turned out to be, and most of those 4 hours were spent trying to track down an exception that was being thrown within my colorizer because of a bounds checking bug in my C++ code. I did not have any prior experience using the VSIP Extras SDK before last night, so I cannot say that it was easy because I knew how to use the Extras IAs, it was easy because there were only minor differences between the C++ and C# code.
The process was not flawless, however. I was bitten a few times because of some of the odd data types that the IAs seems to use and the conversion of those types to managed types. For example, there are a number of System.IntPtr objects that are passed back and forth, usually when a WCHAR* type is used on the unmanaged side. In this case you want to call System.Runtime.InteropServices.Marshal.PtrToStringUni to convert to a managed string (not PtrToStringBSTR like I was using at first, which would cause an immediate crash). I also had some problems setting up a service provider, I had to try overriding a number of different methods to get it working correctly – and there may be code in the Extras helpers to handle doing that in a cleaner way (don’t forget the Marshal.QueryInterface method, this will help you a lot when trying to implement your service provider). There also has been a noticeable slowdown when switching to a managed language, but most of that is, I believe, a problem with my code and not so much related to managed code. I am doing a lot of string manipulations in the colorizer, and a quick look over the code reveals many places where I can use StringBuilders rather than strings to speed up my code. I was also using a lot of pointers to keep track of positions into strings for optimizations, and when I converted to C# I had to undo those changes.
The next few days will be spent doing some optimizations on the code, and then I will start working on converting the project code to C#. When this experiment is done the packages will be written in both C# and VC for side by side comparisons, and maybe I will try converting to the other languages also. I don’t know of any packages written using VB and J#, and maybe as a proof of concept of using the IL editor/project I can convert them to IL.
Just as I was getting ready to post this, mail was circulated describing how to proffer a service from managed code using code such as this
container.AddService(service.GetType(), service, false);
inside the Initialize method of a package. I noticed that method last night and tried to use it, but I could not get it to work correctly. I will try it again with my code and see where I went wrong.