Programming


One of the guys I am working with at the moment uses the phrase “every day is a school day”. He’s not wrong, rarely does a day go past when I don’t learn something new about some bit of computing technology (typically finding out a new way that some piece of software is broken).

Today’s lesson was on Microsoft SQL Server. I was struggling to debug a problem inside a stored procedure that is buried deep with a nested set of other stored procedures. I was getting frustrated and thought to myself “it would be so nice if I could dump stuff to the Windows Event Log from within this stored procedure”.

I got so fed up in the end that I went off to see whether event logging from Transact-SQL was actually possible. It is, using the xp_logevent stored procedure (which lives in the master database).

This is the code that I am using:

declare @message varchar(255)
set @message = '@primary_contact_type ' + cast(@primary_contact_type as varchar(30))
EXEC master..xp_logevent 60000, @message

Two things to know to make this work:

  • you have to declare the @message variable, you can’t just pass a string constant to the xp_logevent call
  • your database user needs the relevant permissions on the master database to make the call

The xp_logevent stored procedure makes a COM call to log the message, so you probably wouldn’t want to leave the call in any production code (unless you put in a switch to turn it on and off when you needed).

If you have ever got involved with putting .NET assemblies into the GAC (Global Assembly Cache), then you will have come across gacutil.exe

There is a problem with gacutil.exe, it isn’t part of the .NET framework and therefore isn’t installed on machines that have had the framework installed on. It is actually part of .NET SDK and you aren’t supposed to distribute it with your own applications.

If like us you don’t realise until late on in your project that gacutil isn’t redistributable then you are faced with a number of options for registering your assemblies with the GAC:

  • use the features in your installer (not an option for us as we were using a very old version of Install Shield)
  • illegally redistribute gacutil
  • write your own code to call the GAC API

I’m ashamed to say that we took option 2 as we were pushed for time and resources. At the time I couldn’t find C# code to call the GAC API and we didn’t have anyone around that could write a C++ version for us.

I have since found this C# code, which is supposed to achieve the task of registering with the GAC:

using System.EnterpriseServices.Internal;

string path = Directory.GetCurrentDirectory() + "\\";
Publish publish = new Publish();
publish.GacInstall(path + "MyAssembly.dll");

I had a problem today when trying to call a C# component from Classic ASP. When I called a method in the C# component I got the error “class doesn’t support automation”.

This was very puzzling because I had already prototyped this to make sure that I could sucessfully call C# from Classic ASP (using both VBScript and Javascript). The C# assembly and class were marked as COMVisible and I had used regasm to register the DLL with COM.

Through a process of elmination I worked out that the problem was that the method had some boolean parameters that I wasn’t initialising with boolean values in my ASP code. I hadn’t completed my ASP page, so the variables being passed to the booleans were in fact set to empty strings.

So the error message is very misleading, as it has nothing to do with the class you are calling not supporting automation.

Once I initialised my booleans correctly the problem went away, which made me a very happy bunny ;)

I ran into a problem today, with VS.NET and references between projects. In the development project that I am working on at the moment we have two main C# classes that are called by various classic ASP pages and client side code.

Because both of the classes have attendant helper classes and they are logically separate (and also being coded by two different people) we have them in two separate VS.NET projects. Until today it all worked fine.

Today however we broke things. Class A was already calling Class B, but in a change today we decided that Class B then had to call back into Class A.

Until today the project for Class A had a reference to Class B, not the other way around. When we tried to add a reference to Class B’s project back to Class A’s we got an error complaining that it could not be done because it would create a circular reference.

I guess the problem is that the two projects get compiled to two separate assemblies and that one can’t be built before the other because they both embed meta data from the other.

We scratched our heads for a while, it didn’t help that it was at the end of the day, and came up with the following options:

  1. move the two classes into the same project (this would be less than ideal two people need to work on the code at the same time and it would also stop us from shipping one of the components without the other)
  2. abandon the VS.NET build process for these two components and build them together into the same assembly using the commandline tools (still has the problem of not being able to ship them separately and complicates the build/debug process)
  3. create another class that sits above A and B that makes calls into A and B (A still then needs to call B, but at least B doesn’t then have to call A)

At the moment it looks like we are going to go with option 3, which means some more work for me tomorrow. I hope I can do it cleanly without duplicating code from A and B into the third class.

So, something to look out for in my next .NET project (in our defence this project wasn’t really designed with .NET in mind).

Edit:

I have found another and I believe, better solution. I have created a interface in a separate project (that matches Class A’s current public interface). Class A can then implement the interface and pass a reference to itself cast as the interface when it calls Class B. Class B can then call back to into Class A via the interface.

Class A and B then need reference to the project with the interface, but crucially Class B doesn’t need a reference to Class A.

I have decided that when using the .NET framework’s XML classes it is a bad idea to pass XmlDocument objects to methods. It is a much better idea to pass the document’s root XmlNode object instead.

The reason for this is that at some point down the line you might, as I have today, decide that you need to use one of your methods on a sub-set of a document. If your methods are setup to receive XmlDocument objects then you suddenly have a lot of code to refactor to allow you to pass an XmlNode object from an arbitary level in the document instead.

…insert useful example here…

Passing the XmlNode object is just as easy as passing the document and you can still access the document via the XmlNode.OwnerDocument property anyway.

Update:

I discovered a serious problem with this approach today. The XmlNode object that represents the top level of the XmlDocument returns null from its OwnerDocument property! Doh!

How annoying is that? I can see how logically the node that represents the document itself doesn’t really have an owner document. However it seems a very pureist way of looking at it and it isn’t a very useful design decision for someone using the class.

So all the methods on which I carefully replaced the XmlDocument parameters with XmlNode parameters have now had to gain an XmlDocument parameter as well, otherwise there is no way to insert new nodes and elements.