April 2006 - Posts

Hosting controls in IE is easy. Most of the time. Simply create a Windows Control Library, and then put that DLL in the path of your html/aspx page which will host the control. Now, all you need to do is put an object tag in your page which references the control. The classid for the object tag must be of the form: "DllName.dll#Namespace.ControlName". Voila, your control will now appear.

Making debugging a pain in the neck

Well, maybe. There's various security issues with the browser and .NET Framework that may bite you badly here. Suffice it to say that you may spend quite a bit of time playing around with various settings. One piece of advice that may assist in your debugging is to remember that IE caches stuff, so when you make any changes to the control itself, go into Tools->Internet Options and use the Delete Files button in the General Tab.

However, that's not enough on it's own, since .NET also stores a "cache" in the form of the download cache. You'll have to clear this out by using "gacutil /cdl". However, before doing this you'll need to close down the IE session that hosted your control, as it will be locking this cache. Note that I said IE session, not IE instance. If you opened any new IE windows from that instance of IE, or opened it from any others, they all need to be closed down, even if they opened before you navigated to the hosting page.

If you're struggling to get your control to even appear, you might want to go into Internet Options, Settings, View Files, and then look for a file called "?FusionBindError...". Copy this file out somewhere onto your hard disk since you won't be able to view it from here. It'll have a weird name (different from it's one in the Temporary Intenet Files folder I mean). This may contain information that will help you find out why your control can't be loaded.

Alternatively, it may be a problem with IIS not being able to find DLLs or their dependencies. The IIS logs come in handy for this, just go look for 404's with .dll in the same line.

I wanna access the control from JavaScript!

Of course. I mean you're hosting it in your page, and obviously you may want to respond to events fired by the control, and you may also want to set properties on the control. The important thing to remember here is that IE is a COM-based system, and doesn't understand .NET events, properties and methods.

IDispatch, how we've missed you

So the first thing you're going to have to do is create a COM IDispatch interface for your control. Before you sign off in hopelessness, this is actually quite easy to do inside .NET. Create a stock-standard .NET interface, and put your members in. Now all the members are going to be methods, even the properties and events, which may seem a bit weird. So you'd define events as:

void EventOne(object sender, System.EventArgs e);

and properties as:

string Property();

This might seem a bit strange, but COM doesn't really have the concept of properties and events, they're all just methods (much as it might seem otherwise). In a sense .NET is the same, it's just better at hiding it.

Right, now we've got our interface, what next? Well, we're going to have to make it COM-compatible. We do this by applying a GuidAttribute to the interface, with a unique GUID. We also need to mark the interface as being of type IDispatch. Don't worry about this too much, it's basically saying it supports something similar to Reflection (yes, in COM you need to tell it this explicitly). Javascript uses IDispatch exclusively to access methods. To mark the interface as such, just apply the InterfaceTypeAttribute using a parameter of ComInterfaceType.InterfaceIsIDispatch.

DISPIDs are love

Now the interface itself is accessible to JavaScript, but the methods aren't. COM has a weird thing where every member of an interface has a number that identifies it called the DISIP. There are good reasons for this, but you really, really do not want to know. Trust me. So what we must now do is decorate each member with the DispIdAttribute. The parameter must be a number 1 or above, and each member must have a unique number. Technically you can give DISPIDs with lower values (way into the negatives even), but most of these have special meanings for COM, so I'd seriously advise against it.

So now we go to your control. Add members and events and stuff just as you normally would. Properties are proper properties, events are proper events. You must implement the items you declared in your interface, but do not implement the interface itself. The reason is that this interface is a special type of interface known as a COM source interface. What we'll do is decorate the control with the ComSourceInterfacesAttribute, passing in the fully qualified name of our IDispatch interface.

Time to USE this stuff

Okay, now we're ready for the JavaScript. We do all the steps to deploy our DLL to IIS, and into the web page as I discussed above, except now we can write script code that will access that object.

Some pit traps to avoid

There's one big caveat though. The assembly must have the "Security:Allow calls to unmanaged assemblies" permission. Probably the easiest way to do this is by granting FullTrust to the assembly via the .NET Framework Configuration Tool.

Oh, one other thing. Make sure all your assemblies have an explicit assembly version set (i.e. no *s in AssemblyVersion). If not, you may get some very weird compatibility errors between client and server.

Configuration

Now what about configuration? One would think that you might put the config for your control in the web.config file, but you'd be very wrong. You see, you're running Internet Explorer, not a web page, so the config has to be for IE. The good news is that the config file isn't on the client machine, but is on the web site. Just create a file called "iexplore.exe.config" and put it in the site root. Note, that's not the virtual directory, but the site root. So if it's localhost, then the config goes at http://localhost/iexplore.exe.config.

Conclusion

I hope this helps. Most of this information is available elsewhere, but trust me it can be a pain tracking it all down. Many other blogs have much more detailed information on the Code Access Security issues, or the Fusion binding issues, or the debugging, but I haven't yet found any with all the information easily summarised.

Code

To help out, I've posted a sample project at my web site. You can also find it as an attachment to this post.

Unzip it to a directory, and then build it. Create a new Virtual Directory on your web site, and copy the TestEvents.html page to that site. Also copy in the IEEvents.dll. Then copy the iexplore.exe.config to the root of your site. For example, C:\InetPub\wwwroot.

For those of you who read the article at sadeveloper, apologies. From what I can see, the article got a much lower distribution than the post about the article. So, I don't want to annoy what few readers I have, so here's the whole thing again:

In this article I'll look into the problems with the standard finalizer model, explore Constrained Execution Regions and how they can help us obviate these problems. Finally I'll delve into the CriticalFinalizerObject and how it implements CERs, and adds extra "help" for important finalizers.

Okay, before we delve into the murky world of Critical Finalizers, let's start by looking at what's wrong with normal finalizers. The simple answer is "not much", the more correct answer is "not much if you don't care about it always running". I'm sure many of you have had it drilled into you that finalizers are there to ensure that unmanaged resources are correctly disposed of, even if the idiot using your class doesn't call the Dispose method.

All well and good, but they won't always run. Which means that your unmanaged resources won't always get released. And therefore you'll sometimes get leaks. If you're writing a desktop app, then maybe you don't care, but if you're writing server-side stuff you sure as hell should.

Why won't Finalize run?

Well, there's a few reasons. Basically it all boils down to how finalizers are executed. Basically when you implement a finalizer on your class .NET registers it in a queue of finalizable items (the RegisteredForFinalization queue). During normal garbage collection, if your finalizable object is no longer referenced, the CLR will move your finalizable object to the ReadyToFinalize queue. Then, after a few other GC-related tasks, the Finalizer thread dequeues each finalizable object in this queue in turn, and executes the Finalize method.

All well and good. Besides telling us that Finalizers are expensive beasties (especially if you dig into that "few other GC-related tasks" thing), what's the problem? Well, if the process is terminating, the system will timeout the finalizer thread if it cannot finalize all the items in a reasonable amount of time. In this case your finalizer may not be called. Even if the finalizer thread does get to call your Finalize method there's no guarantee that any or all of your code will run.

All sorts of things could still go wrong. The finalizer thread may be timed out during the call to your finalizer. If the process is scarce on memory, its possible that the Just In Time Compiler won't have enough memory to compile your finalizer. It may have enough memory to JIT your Finalizer, but when you make a method call inside the finalizer, it may not be able to JIT that, or the runtime may not have enough stack space for the method.

In all these cases there is the possibility that your application will leak. Now, Windows is pretty good at cleaning up after process shutdowns, but what if we're just talking about an AppDomain shutdown? Perhaps your AppDomain is hosted in a high-availability process such as SQL Server 2005. In that case any intermittent leaks can cause massive problems down the line. Especially when you consider that SQL like to run near the edge of memory exhaustion, and loves aborting threads that take too long.

So what can we do?

Well, there's a new concept in Whidbey known as Constrained Execution Regions. What a CER does is ensure that the runtime will not throw an asynchronous exception inside that region. Asynchronous exceptions include: ThreadAbortException, OutOfMemoryException and StackOverflowException. The reason that they're referred to as asynchronous exceptions is that they could happen anywhere in your code. There is no way you could ever know where a ThreadAbortException could happen. An OutOfMemoryException could occur anywhere where an object is created. StackOverflowException could happen on any method call (and a few other places besides).

The CLR goes through quite a few hoops to accomplish this. First of all it pre-JITs the code in the CERs, and will also pre-JIT all the code the CER may call (if it can determine this). However, it is up to the developer to ensure that certain other conditions do not occur in the CER. As such you are not allowed to use the following in the CER: explicit allocations, locks, boxing, accessing multidimensional arrays, calling methods through Reflection, any security checks other than link demands, typeof and casts, accessing fields on a transparent proxy, serialization, and using delegates or function pointers. Whew, what a list!

So, given that you pretty much don't do anything interesting, the runtime will guarantee that your CER won't be unexpectedly exited.

So how do I define a CER?

Okay, it's quite simple really. All you do is call RuntimeHelpers.PrepareConstrainedRegions just before a try block. Now, the try block itself is not a CER, but its finally or catch block is. Why this is, I really do not know. So, any code running the catch/finally block will not suffer from asynchronous exceptions. Please note that you should never do anything that may cause a StackOverflowException in the try block itself. Most implementations I've seen of CERs using PrepareConstrainedRegions have an empty try block:

RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally {
 // CER
}

This is actually incredibly simple. A lot easier than remembering that huge list of no-nos (or even knowing what they all mean). Even easier, you can simply add a ReliabilityContractAttribute to your method with Cer.Success or Cer.MayFail. The Consistency enumeration defines exactly what it will mean if your method does wind up failing for whatever reason. Basically what happens here is that the runtime will do the PrepareConstrainedRegions call for you.

Great, so you've defined a CER. Wonderful. Now you can....

Not so fast! Here's a thought. What if your CER calls a virtual method on a member? The runtime can't determine at type load which virtual method you'll wind up calling. As such, it can't do all the funky preparation work its just done for the CER, and you might wind up with one of those nasty asynchronous exceptions after all.

Well, you have a couple of options here. You could decorate all the virtual method instances that you might call with the PrePrepareMethodAttribute. Alternatively you can explicitly call RuntimeHelpers.PrepareMethod. Note that this must be called before you enter the CER, otherwise its not doing much good is it? So ideally you'd call this just as soon as you had a reference to the member object. Calling it when the object containing the virtual method is assigned to your class is a good idea.

Right, now we're ready to proceed. So, we happily go along and slap a reliability contract on our finalizer and make sure all its code fulfills the CER requirements and also ensure that all the methods it will call are prepared.

What about CriticalFinalizerObject?

Okay, now that we've got all that out of the way, let's return to the CriticalFinalizerObject. This is a nice simple base class that you can inherit from that puts all that CER stuff around the Finalize method for you. It's still up to you to ensure that you behave correctly within the Finalize method, but you don't have to worry about setting up the ReliabilityContractAttribute. Just as an aside, CriticalFinalizerObject initializes this attribute with the Consistency.WillNotCorruptState and Cer.Success enumerations, so it's up to you to ensure that you fulfill this contract. In other words you must guarantee that the finalization will complete, and that the finalizer will not leave the object (or anything else) in an inconsistent state.

Now, there's one more little caveat about finalizers. There's no guarantee in which order they'll run. This may not be a problem for you, but in some circumstances it can be. An example commonly cited is that of file handles and buffers. Ideally on a finalize, the buffer should write its remaining contents to the file. Obviously, when the file handle finalizes it should close the file. Now, what if the buffer finalizes after the file handle is finalized? We're suddenly stuck with the situation where the buffer is trying to write to a file that is closed.

To address this the CriticalFinalizerObject adds an extra level of reliability to our finalizers over and above CERs. Simply put, critical finalizers execute only after normal finalizers are executed. So in our example, we would make the buffer a finalizable object, and the file handle a CriticalFinalizerObject. The buffer finalizer is now guaranteed to be run before the file handles' finalizer. Well, not really. Since the buffer finalizer is not a critical finalizer, there is no 100% guarantee that it will actually run. But we can guarantee that it won't finalize after the file handle finalizes.

Conclusion

So, we've had a look (in probably more detail than was strictly necessary) at some of the problems with finalizers. We've also had a look at Constrained Execution Regions and Critical Finalizers and we've examined the various requirements for writing code that will run in a CER. If you want to delve into scary detail about finalization, the absolute best resource anywhere is Chris Brumme's excellent Finalization post, from which much of the information in this article is sourced.

If you'd like to read more of my rants, raves and suchlike you can find me at my blog. You can always email me at My Email Address

I've just posted the first part of a series of articles on reliability on sadeveloper (a South African .NET online community). Actually, I had no intention of starting with this article, since I wanted to discuss something else entirely, but thought I'd better lay the groundwork first.

Mostly unrelated to the article itself, I was following a feed in Colin's blog, and saw a comment from Senkwe about how few decent technical articles there are in sadeveloper. Colin also complained about the tendency of many posters and article writers in dotnet.org.za and sadeveloper to just copy from source documents.

Well, I'll certainly try to add new spin on stuff. Whilst this first article on reliability is largely an aggregation of other people's work, it does aggregate much information that you won't find in one single place, so I hope it does add some value.

Ruari has also called for ideas for topics that we can get people to speak about, write about, and workshop. I've added my own suggestions for topics that are near and dear to my heart. I'm going to be writing about these topics anyway, but stupidly offered to give talks on them. I haven't done public speaking since Grade 9, so I'd probably just mutter and mumble. Hopefully they won't be so silly as to take me up on the offer.

PS. Just as an aside, I bumped into Ruari once (very briefly) during an sadeveloper talk. He didn't recognise me, since we last saw each other many many years ago. I went to school with his brother-in-law.

PPS. If anyone has any comments about me putting my articles on sadeveloper instead of on this feed, let me know. If it's not popular, I'll return to putting them on my main feed.

This is why I read Joel Spolskys blog. Yes, yes, I know I promised not to link to content every man and his dog will be linking to soon, but this is worth it, promise. Joel goes to the heart of the reason why companies like Microsoft succeed. To summarise, it's because they let developers get on with developing.

Are your developers doing admin? Why? Do you have developers running around collecting bug information? If so, you're insane. A development company should have its primary focus as keeping its developers productive from the time they enter the office to the time they leave. I've sat through some of the most ridiculous examples of corporate waste in this regard. One of Joels examples struck home hard. At a previous company I worked for, a colleagues laptop hard drive crashed.

Now, the problem was that we'd hit our limit for capital expenditure, and due to cost-cutting measures the new R1,000 ($150) hard drive would have to be approved by the Board of Directors. Of a massive publicly listed company. In a month. So here we had a developer who was costing the company more than that a day, doing nothing. We managed to speed up the process (with much fighting), and got him productive less than two weeks later. Cost to company: plus/minus R10,000 + R1,000.

Many cost-cutting measures or efficiency drives do the exact opposite. Another case in point; a different company implemented a paper-saving measure: we would print double sided. Now the only problem was that our printer didn't support that. So, you had to print all the even pages, go over to the printer, reverse the paper, hope to hell you reversed it the right way, go back to your desk, and print all the even pages. Then you'd run over to the printer to make sure you got it right. Invariably you hadn't, so you stop the print job, reprint the messed up pages and repeat. Paper savings after a month: R50. Increase in other costs: None. You see, the bean-counter considered the staff costs as "sunk", so our time was effectively (to them anyway) free.

It's not free. In a development company with many senior developers, your payroll costs are astronomical. You need to make sure you're getting the most bang for your buck. That means the developers develop, the marketers market, the sales guys sell, and the admin staff do the admin. If you're seeing crossovers between these roles, there's a problem. Too many companies focus on the costs, and too few on the productivity. Productivity is best achieved by getting rid of the things that hinder your staff in their jobs, and putting in place things that help them in their jobs.

Saw this piece in Wired News where they say that "the time and date, for the first time in all of humanity, will be 01:02:03 04/05/06". Wow! That's so impressive. Especially since it's a load of crap.

How about exactly 1000 years ago, when surprise, surprise it would have been 01:02:03 04/05/06? How about using a non-Gregorian calendar? Say, the Hebrew calendar, or the Islamic one, or the Chinese one, or any of the others?

They also go on to say "And, Pogue points out, this moment will never come again.". Umm, except in 1000 years? Perhaps 1000 years after that? Oh, wait, maybe even another 1000 years after that too?

So perhaps the right way of phrasing this would be "the time and date, for the first time in almost 1000 years, for cultures using the Gregorian Calendar, will be 01:02:03 04/05/06, and it won't happen again for almost 1000 years". A bit less impressive perhaps. Even more so when you consider that the year is not "06", but is in fact "2006", which means that the only time that date happened, by common reckoning, using the Gregorian Calendar, was in the year 06 A.D. almost 2000 years ago. Funnily enough, I don't think they had settled the whole Year 0 thing by then, so they probably didn't know it had happened. Poor them. I guess the whole Y1K thing would have really bit them on the ass.

About the only thing this article has going for it is that the utter drek that they so breathlessly exclaim as being a once in a lifetime event wasn't actually written by them. C'mon, if you're going to shamelessly rip off other people's work, at least pick stuff that isn't such blatant idiocy.

"And after that, it most definitely will never occur again."

Let's hope not... At least for another 1000 years or so.

This is a hard topic. Let's face it, we all see licensing as a neccesary evil. It doesn't add to the product, but rather detracts from it, and this is why many developers leave licensing issues right to the last. Many licensing schemes are poorly thought out, and slapped on as an afterthought. I believe that licensing issues should be a major part of the Requirements documentation, and built into every successive document and code artifact from that point on. I'm going to go over a couple of licensing options you should consider. By no means an exhaustive list, but let's get the ball rolling.

Licensing Schemes

Freeware, Shareware, Adware, OSS - Well, I'm a grasping greedy contractor, so these schemes hold little interest for me. In any case others have written far more eloquently and passionately than I can about these.

Per Server/Per CPU/Per Database - These kinds of licensing systems are the easiest to control. If you're slapping on licensing as an afterthought, I'd strongly suggest you go with this model. The advantage is that the licensing can be controlled by the installation  module, and licensing remains firmly in the hands of the IT department. The disadvantage is that licensing remains firmly in the hands of the IT department. Besides the per CPU option, this model also means that you only get licensing revenues from scale-out, not from scale-up.

Per Client Machine/Per User/Per Connection - This kind of licensing system is very common, and gives you a continually increasing revenue stream from a customer as their business grows. Since, in theory at least, your product is helping them grow their business, this is a win-win scenario (OMG, I hate that term, but it is possibly true in this case).

However, in this model, make damn sure that your turnaround on getting new licenses is very quick. No business likes to have a new staff member sitting around doing nothing whilst waiting for licenses from their vendor.

Per Module - Another pretty common one, especially with tools aimed at single users with different requirements. Development tools, CAD tools, etc all tend to use this model.

Hybrid - One common hybrid is Per Module/Per User, another would be Per Server/Per Connection.

Activation Schemes

Trust - Surprisingly common, this scheme means you give the installs to the business and trust that they don't abuse it.

Installation Key - CD-Keys fall into this category. Basically, you provide some kind of key, locked to the provided installation. This gives you a bit of an ability to track where pirated copies came from, but provides no real protection. If you are supporters of good privacy, you might not even be able to match the installation key up to a particular customer, rendering this whole scheme 100% worthless.

Computer Key - This is where the application/installation provides a key based on the computer, that is then transmitted to you. You then provide another key that unlocks the application. This can be a manual process or an automated one (ala Windows Activation). The upsides are a much stricter control than Installation Keys, and you can know exactly which machines use which keys (given aforesaid lack of privacy concerns). Even with good privacy protection, you can retain control. You may not know anything about the computer/person involved, but you do know that the key has been used on another computer.

The biggest downside here is that modifying the hardware often invalidates the computer key, and upgrading to a new PC, always does.

Renewal - From time to time the licenses have to be renewed. Maybe not paid for again, but somehow the license has to be refreshed or it becomes invalid.

Audit - Sorta like Trust, but you check the usage from time to time, either by going to the site or by getting information automatically. Raises all sorts of privacy concerns if automatic, and if not, what if the customer won't let you on site?

Control Schemes

Control schemes is my way of saying what you do when the licenses become invalid for whatever reason. This can be before or after activation.

Cripple Functionality - Basically you have some "premium" functionality that is only valid for valid licenses. If the application is not activated, or the license expires, the application cripples the functionality. The problem here is that you have to walk a very fine line. Have too much premium functionality and people will not try out your app, have too little and they won't upgrade.

Disable Application - Many applications do this, and it's a very valid approach. Just keep in mind what your licensing scheme is when you consider this. I know of one distributed application that uses a hybrid Per Server/Per User scheme, when you add more users than you have licenses for, it shuts down the entire application throughout the enterprise. Not good at all.

Warning - Pop up annoying warnings about the license being invalid. WinZip for example uses a hybrid Cripple/Warning approach very effectively.

Range - This is one I've been thinkg about a lot. Basically, it is for per user/per connection type applications. It will allow use beyond the license limits, for limited periods of time. Very useful for businesses that have occasional spikes of use. As an example, think of an accounting package. Let's say there are normally 10 users that use the app, but on month-end this rises to 15 for 2 days. In that case I'd offer a 10 user license, and the app would allow the occasional spike. Best used with a moving average analysis of usage to determine license validity.

Hybrid - As can be guessed this is a combination approach. It is most effective when used with grace periods. So, for example, you have access to the crippled product for 2 months (with warnings), and then it reverts to disabling the application.

Summary

I'd like to hear what other kinds of Licensing, Control, and Activation schemes people think are useful. My personal favourite (for the kind of enterprise apps I work with) is a Per User/Per Server/Per Module licensing hybrid (giving the customer a great deal of flexibility), with a Trust activation scheme (with maybe Audit/Renewal backups), and a ranged warning/disable control scheme.

Some "special" licenses to consider are Test/QA, and Development. My personal opinion is that these licenses should be fully functional and free, assuming we're not talking about dev/test applications of course. If you screw over developers by not allowing them to play with your application, then they won't want to integrate with it. If you make testing expensive, then you can say hello to tons more support calls.

As an example, one vendor charges per user for test licenses just as they do for production.The problem is that their application integrates tightly with Active Directory. So, to properly test against the system, you have to have the same AD users/groups as production, which means that if you have 100 production users, and 4 testers, you need 200 licenses. Alternatively, you can set up test AD groups, and hope to hell that nothing unexpected comes up in production.