COM/.Net Interop Solutions

A quick update on the COM/Interop problems I’ve been writing about the past few months. As I mentioned in the extremely long post on 4/7, we came much closer to solving the problem than before. Previous solutions had been to account for all the COM objects and release all of them when the application close. However, this did not fix the problem only alleviate it.

In writing the next version and with the freedom associated with change a new version and not a patch, I decided to make one COM object that the whole web session would used. We were making an object next to the code that would use it, then releasing it when finished. The idea being if the make and release seemed error prone than reduce the number of times that happens.

The same call that takes the root level COM object from ASP creates the FieldManager. And the same call that closes the root level COM object destroys FieldManager. Then all references to the COM FieldManager get replaced with the .Net FieldManager. Suddenly, there’s one more layer between the working .Net code and the COM code.

Some cleanup was done after this; inheritance from a base object and replacing some COM FieldManager methods with a .Net version. Turns out one of the most heavily used aspects of FieldManager is to ask for more information about a field. And some of this information is hardcoded in a c++ object in the COM source code. A c# program was written to “translate” the relevant lines of the c++ code into equivalent c# code. There are about 1400 fields stored this way and changes from one version of the COM object to the next may go unnoticed byt the .Net team. So an automated solution was much prefered. Now, instead of a COM call for this information and .Net call for this information is used. If the information is not held in .Net then a COM call is made. For our most standard test file, all calls for field information were handled by the “translated” .Net code.

The last set of changes concerning the FieldManager field info are untested, but the other changes have already passed through QA into production and there seems to be no side affects. Hopefully, this addresses the problem and the solutions above turn out to be the correct way to handle COM/.Net interop.

P.S.
In making the import c++ code I discovered something interesting. Some lines in the c++ code imported as strings did not readily convert into integers in .Net. Maybe they were blank or an enum. The first method I tried was to use a try/catch. “try{ Int32.Parse()}catch{//you must be an enum}”. This personaly annoys the shit out of me. I should be able to evaluate a string that very likely is a string and maybe is an integer and decide what to do instead of waiting for it to fail a try/catch. VB.Net has IsNumeric() to do this. c# has nothing (thanks MS). So I referenced Microsoft.VisualBasic and then used “if (Microsoft.VisualBasic.Information.IsNumeric()){Int32.Parse}else{ //you must be an enum}”.

I was stunned by the performance difference. The results were the same, but the first solution using try/catch took over a minute to run. The second solution take ~15 seconds. This is huge. Cheers.

Leave a Reply

You must be logged in to post a comment.