VSIP Package Deployment

There is a rather timely article about VSIP package deployment on the Microsoft extensibility blog (Dr Ex). Due to some recent Clover.NET experiences I think there are a few additional points to be made.

Most of the problems we had revolved around the Microsoft.VisualStudio.VSIP.Helper.dll assembly. This assembly is not as well “controlled” as the VSIP interop assemblies. The beta versions of Clover.NET shipped with this assembly exactly as it comes with the VSIP Extras install – i.e. not modified at all. While it was not installed in Common7\IDE\PublicAssemblies, as Dr Ex. recommends, this dependency was a source of problems. In a few instances there was a conflict with an existing version of the assembly on the user’s machine.

In the end, we repackaged the whole Helper assembly into our own DLL to avoid conflicts with other VSIP packages. I’d be very careful about depending on the Helper DLL as it comes with VSIP Extras and would probably recommend you also repackage it, even if you do not change it.

Such assembly conflicts in a VSIP package are very difficult to diagnose because Visual Studio gives no indication whatsoever when a package fails to initialize. Some logging or an event viewer entry would be good. To diagnose these you need to have your user use debugCLR or the Visual Studio debugger to launch a separate Visual Studio instance. You need to trap any CLR exceptions and then try to initialize the package. VSIP packages are initialized on demand by the IDE, so you usually need to access some feature such as a menu item to activate the package. As the package initializes, the debugger will catch the CLR exception and you can sort out your package load errors.

Luckily for the Clover.NET development we had two cluey users who were able to help us isolate this issue.

Visual Studio and File Encodings

We recently had a bug report in Clover.NET that it was not handling UTF-8 encoded files. We had to smile because we had earlier had a bug report that Clover.NET only handled UTF-8 files and could barf on files that were written in the local encoding. Nevertheless the bug was certainly valid.

It turns out that there is more to this than we thought – there’s a little trickery being performed by Visual Studio and the compiler, csc. The /codepage description in MSDN gives a clue:

If the source code files were created with the same codepage that is in effect on your computer or if the source code files were created with UNICODE or UTF-8, you need not use /codepage.

So you can use either your default encoding or you can use UTF-8. Hmmmm. It turns out that this applies even to UTF-8 files which do not have the initial UTF-8 signature. How does the compiler decide which encoding to use? Certainly with my default encoding, CP-1252, there are byte sequences which are both valid 1252 encoding and UTF-8 encoding.

Well, of course, I don’t know what goes on in csc’s internals but the effect seems to be that it assumes UTF-8 and falls back to the default encoding if there is a problem.

It’s not too critical with csc where you can explicitly designate the codepage for the compielr to use. What about Visual Studio, where you can;t control the codepage. If your default encoding is 1252, try this little example. Create a new file and copy the following code into it. (I’m hoping all this encoding works between your browser, my browser and my server).

using System;

namespace Sample
{
    public class SampleClass
    {
        private const string testData = "§";
        
        public static void Main() 
        {
            Console.WriteLine("Hello - " + testData);
        }
    }
}

Now save the file and close it. Then reopen it. For me the result is

using System;

namespace Sample
{
    public class SampleClass
    {
        private const string testData = "§";
        
        public static void Main() 
        {
            Console.WriteLine("Hello - " + testData);
        }
    }
}

The initializer for testData has changed. What has happened is that the string that initializes testData is valid in both codepage 1252 and UTF-8. Hey, IDE, don’t change my code. I really don’t like that. If we change the code to be what was originally entered, the change will now stick. I guess that Visual Studio realizes the encoding is now UTF-8 and saves the file with UTF-8 encoding. If, however, you open the file assuming encoding 1252 (try wordpad), the string will have become "ç"

Maybe I’ve got it wrong but it seems it’s all too clever by half. Maybe nobody will be using these combinations of odd characters and the convenience of guessing the encoding is worth the risk. Yet, having the IDE assume an encoding which may not be correct and even changing the file encoding is not cool in my book.

If you are using some odd characters in your file and you don’t intend to live wholly within the IDE, be careful about how your files are encoded.

Clover.NET beta

In addition to changing our name to Cenqua (see Matt’s Blog for more details), we have released a beta for Clover.NET. The beta includes command line tools, a Visual Studio 2003 plugin and NAnt tasks for both version 0.84 and the current CVS version (0.85).

We’ve learnt a few lessons along the way with this development. We now know how to perform long running operations in Visual Studio. It may sound easy but operating on a separate thread in Visual Studio can give you strange results. No doubt there is an apartment threading issue at play but I think only God and Don Box understand the concepts at play there (and I think even God isn’t sure about it).

Personally I’ve been interested to see the contrasts between my experience in Ant and how things work in NAnt. The use of .NET metadata is cool but can also be restrictive. More on this in another post.

Another contrast is of course the difference between C# and Java development. There isn’t much there, IMHO. On the plus side, some things in C# are nice such as delegates for function pointers, enums and the general level of syntactic sugar. On the other hand some things are more primitive than Java. The runtime library seems strangely incomplete, such as, for example, not having a Set interface in the Collections namespace. I’m not sure why we don’t have the same level of capability as the original STL in C++ in both Java and C#. Overal much of a muchness for me.

We’ve put up a sample report for NUnit on the new website. Ideally we’d like to add a few more open source C# projects as nice examples but frankly it’s hard to find open source C# projects with good unit test suites. Any recommendations would be welcome. As with Clover, Clover.NET will be free to open source projects.

Nant and Licensing

The alpha for Clover.NET is coming along nicely and we are getting some great feedback. Thanks to our alpha testers. The alpha is currently command line driven and that is not really optimal in the long term. We’re working on Visual Studio integration which should ease the situation but, given my long affiliation with Ant, it’s natural to look at using a build tool such as Nant to manage Clover.NET operations. The java version of Clover provides Ant tasks, after all.

There is, however, a fly in the ointment. Whereas Ant uses the Apache licence, Nant uses a GPL licence. That would seem to prohibit the distribution of non-free tasks for Nant. I’m extrapolating here a little from my experience with Java, where even the LGPL is considered to prevent distribution of non-LGPL code that uses a LGPL library.

Just considering the GPL for the moment, a 1999 post from Richard Stallman spells it out for Java and I assume, by extension, .NET

So I think it is meaningful to release a Java program either under the
GPL or the LGPL, and the consequences are basically the same as for a
C program: if you use the LGPL for your Java program, it can be called
by non-free programs, but if you use the GPL, it cannot be.

I’m not sure how much the position has evolved since 1999 especially with the LGPL, as that now seems to have issues. For those that are interested, Sam Ruby has discussed these issues more recently.

It is interesting that Nant has an exclusion to the GPL for Microsoft’s .NET library. See the Nant licence page. The reason I find that interesting is that the author of Nant has obviously considered the impact of GPL. Unfortunatly without such an exclusion, any Clover.NET tasks for Nant will be limited to driving the command-line tools.

I respect people who choose to license their code using the GPL, it is their choice after all. OTOH, I really wonder if it is an approriate license for a build tool. If I read the licence right, Nant currently makes it difficult to provide rich integration of proprietary tools. It’s a pity as .NET needs a good automated build tool for continuous integration operations. MSBuild? …