Rick Strahl's Weblog
Rick Strahl's FoxPro and Web Connection Weblog
White Papers | Products | Message Board | News |

Doing .NET COM Interop with FoxPro? You need a .NET Disassembler


2 comments
November 17, 2011 •

So you're doing a bunch of COM Interop with .NET. Whether you're using plain COM Interop or the richer functionality offered by wwDotnetBridge, you probably already know that finding the approriate .NET type names is tedious. FoxPro code in either case must reference the full .NET typename which includes the namespace and class name.

For example check out this code that loops through personal certificate store on the local machine using wwDotnetBridge. I've highlighted all the .NET type names used in this small snippet in bold:

do wwDotNetBridge
LOCAL loBridge as wwDotNetBridge
loBridge = CreateObject("wwDotNetBridge","V4")

*** Create an instance of 509Store
loStore = loBridge.CreateInstance("System.Security.Cryptography.X509Certificates.X509Store")

*** Grab a static Enum value
leReadOnly = loBridge.GetEnumvalue("System.Security.Cryptography.X509Certificates.OpenFlags","ReadOnly")

*** Open the certificate store - results into loStore.Certificates
loStore.Open(leReadOnly)

*** Collection of Certificates
laCertificates = loStore.Certificates

*** Collections don't work over regular COM Interop
*** so use indirect access
lnCount = loBridge.GetProperty(laCertificates,"Count")

*** Loop through Certificates
FOR lnX = 1 TO lnCount -1
    *** Access collection item indirectly
    LOCAL loCertificate as System.Security.Cryptography.X509Certificates.X509Certificate2    
    loCertificate = loBridge.GetPropertyEx(loStore,"Certificates[" + TRANSFORM(lnX) + "]")
    
    IF !ISNULL(loCertificate)
        ? loCertificate.FriendlyName
        ? loCertificate.SerialNumber
        ? loBridge.GetPropertyEx(loCertificate,"IssuerName.Name")
    ENDIF
ENDFOR

RETURN

How the heck do you figure out all those type names used in this code?

Answer: You use a .NET disassembling tool that provides insight into a .NET assembly. Regardless of whether you're using a system component or custom .NET component of your own being able to look up exact type names is critical if you do .NET COM Interop.

.NET Reflector

My favorite tool to do this is Red Gate's .NET Reflector. .NET Reflector is free up to version 6.8 and a relatively cheap tool for all that it provides from version 7.0 forward. All the features described here work in 6.x although I'm using version 7.

Using Reflector basically allows you to point at any DLL on disk and show all the contained types and resources that are available. It can also load assemblies from the GAC and by default it loads up a number of common .NET runtime components.

Here's a view of Reflector with the X509Store class open and selected:

Reflector

Reflector provides a number of important pieces of information for Interop. It basically lets you browser the .NET component that you might want to access and call methods or access properties on. You can at a glance see what the component does and how you need to interact with it.

The next important thing is that you can get the full class name for any type. Notice in the bottom left window it gives the name of the type, its definition and the fully qualified type name that includes the full namespace and class. THIS is the type name you generally need for the wwDotnetBridge CreateInstance call.

loStore = loBridge.CreateInstance("System.Security.Cryptography.X509Certificates.X509Store")

I can't stress how important this particular piece of information is because while you might know what the name of a particular .NET class is often it's not so easy to figure out what the full name is. This is especially true if you're loading a third party assembly that might not be well documented. .NET components frequently omit detailed full type information documentation because .NET developers are used to Intellisense and Visual Studio helping them inject assembly and namespace references into their code. As FoxPro developers doing interop we don't have that luxury so for us using a tool like Reflector is vitally important.

Next you can also get detailed information about the methods that you call in .NET. Again this is vitally important as you have to ensure that you are passing the right parameters to .NET and that these types match the .NET signature. Type marshalling from FoxPro -> .NET doesn't always work as expected especially when dealing with numeric values (don't forget to use CAST()).

For the method view we get the full parameter signature plus a disassembled view of the actual code:

Reflector2

The disassembled code is very useful for .NET developers at times. As Fox developers all we care about is the method signature though. We can see all the parameters that are passed and all complex types (like the OpenFlags Enum here) are linked, so you can click on the link and directly navigate to the Enum type:

Reflector3

Now what's cool here is that you get to see the actual typename as before and we can now use wwDotnetBridge's Enum functionality to create the enum value in FoxPro code:

leReadOnly = loBridge.GetEnumvalue("System.Security.Cryptography.X509Certificates.OpenFlags","ReadOnly")
loStore.Open(leReadOnly)

You can see that I need the full type name here, and I can get that from the Name property in the window on the lower left.

However, there's actually an easier way: Since Reflector shows me the disassembled code it also shows me the Flag values for this particular enumeration. I can actually bypass the enumeration and just use the numeric value:

loStore.Open(0) && leReadOnly)

and it works just the same. Note that this will work as long the Enum is actually a flag value - not all enumerated values in .NET translate to a flag value so not all enums translated into numbers. You'll know because Reflector won't show the numbers if that's the case.

What's that Assembly Name from the GAC?

When loading assemblies with wwDotnetBridge from the GAC you need to specify a full assembly name rather than a filename. Actually you can use filename if you know the exact path in the GAC, but that's usually a rather long and obscure path. A better way to reference GAC components is via their full assembly name. For example earlier I needed to work with the .NET JavaScript serializer for long string serialization/deserialization. Here's a small code example that demon hat does this using wwDotNetBridge:

*** Load a GAC assembly (full .NET type name required)
loBridge.LoadAssembly("System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

*** Load a private assembly from disk by full file name
* ? loBridge.LoadAssemblY("c:\apps\myapp\myappassembly.dll")

*** Create an instance of the JavaScript Serializer
loSer = loBridge.CreateInstance("System.Web.Script.Serialization.JavaScriptSerializer")

lcValue = "Hello World\r\nHere's what I've got!"

*** Serialize string to JSON
lcJson = loSer.serialize(lcValue)
? lcJson

*** Create a .NET Type object for string
loType = loBridge.GetType("x")

*** Deserialize with the .NET type provided
? loSer.Deserialize(lcJson,loType)

To find this assembly in Reflector from the GAC I can use File | Open Global Assembly Cache and then look at the assembly in the list view:

Reflector4[4]

And now the strong assembly name shows up in the name property on the bottom which I can then use in my LoadAssembly call:

loBridge.LoadAssembly("System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

 

Note with GAC components - especially those from Microsoft - the hardest part often is to figure which assembly components live in. When in doubt punch in a search into your favorite search engine and look at MSDN entries. As ineffectual as MSDN documentation often is, it does provide you with the necessary type information most of the time:

MsdnLookup

You get the two important pieces of information you need: The assembly the component lives in and the full namespace. Once you load the assembly you can easily look up the namespace and find the class in Reflector.

Reflector in the real World

I have a tool called West Wind Web Service Proxy Generator, which is a tool that creates Web Service clients from a WSDL document for Visual FoxPro applications. This tool works by looking at a WSDL document and create a .NET proxy class, and a FoxPro class that calls this .NET proxy class. In the process we end up with a 1-1 mapping of Web Service methods to FoxPro class methods.

Web Services can get very complex and most of the time these Web Services include a slew of support types that make up the various message objects that are used to pass parameters to and from the Web Service. For example, if you look at the Amazon SOAP Web Services you'll find that there are hundreds of support objects! But even simpler services end up at least with a handful of objects. Since .NET imports the WSDL from the Web and dynamically generates these types as part of the import there is no explicit documentation for them. A tool like Reflector is a life saver to figure out what the service makes available.

Here's an example:

WebService

In this case there's one service class (at the bottom) and about a dozen message classes that are used as part of the requests. Figuring out the full type names for each of these types is not exactly obvious and finding out each of the object's properties isn't either. It's tremendously helpful to be able to look at Reflector and to look at the method I'm calling, following it to the message type that needs to be sent to get the object name and then be able to access each of the properties of each of these objects.

It's invaluable.

Reflect on this!

Ok, so Reflector is very cool, but Reflector has kind of a checkered history and it's not the only game in town anymore. Reflector started out as an open source tool by Lutz Roeder who maintained it until version 4.0. Red Gate took over the product and although they promised to keep it free eventually started forcing people to upgrade to Version 7.0 with a nasty forced upgrade. I've been bitten by this as I've been linking Reflector as part of the West Wind Web Service Proxy Generator, so lots of people actually used Reflector in conjunction with this tool. When Reflector 7 came out Red Gate tried to force people to upgrade and when they didn't they actually removed the running copy of Reflector - it self-destructed and broke some of the links in my tool. Argh! I was pissed.

Red Gate recently reversed that last bit and now Version 6.8 can be used for free (if you can find a copy of V6) and it won't ask to upgrade or self destruct, but the catch is that you have to have an existing copy of Reflector 6 to upgrade first (Red Gate took down Reflector 6 from their servers).

All that said I think that Reflector is a worthwhile tool to spend $35 on even if all you do is COM Interop. The latest version has a number of improvements you know you're running a tool that is kept up to date with the latest features and versions of the .NET runtime.

You can grab an eval copy of Reflector from here:

http://www.reflector.net/

For what it's worth I use Reflector 7 and have upgraded because it's worth it and I have dependencies on it. I don't regret that, but I am pretty miffed at the way Red Gate handled this whole upgrade process.

Other Options

Because of the way that Red Gate blundered their marketing on the move to version 7.0 a lot of people were pissed off and a number of alternatives have sprung up, all of them free. Most of these provide similar functionality as Reflector does although the user interface might be slightly different (out of these JustDecompile is probably closest to Reflector).

  • ILSpy
    Open source tool that provides all the basic functionality of Reflector, but the UI is a bit more low level. Little harder to find things.
    (requires .NET 4.0)
  • JustDecompile
    Telerik basically created a .NET Reflector clone using WPF. It's a nice and smooth application that provides the base features that .NET Reflector provides in a user interface that's very similar to Reflectors.
    (requires .NET 4.0)
  • DotPeek
    JetBrains also has a tool that competes in this space. It's more techy and provides many additional .NET features that won't be so useful to Interop developers. But as the others it provides the necessary tools to figure out type names and method signatures reliably.
    (requires .NET 4.0)

As you can see all the alternate tools require .NET 4.0 while Reflector 6 and 7 still run on Version 2.0 which is nice as .NET 2.0 is widely pre-loaded while 4.0 is still trying to reach critical mass. Otherwise each of these tools should do the trick of helping you in your development.

Posted in: FoxPro    .NET

Feedback for this Weblog Entry


re: Doing .NET COM Interop with FoxPro? You need a .NET Disassembler



Cesar
November 18, 2011

Great post Rick. Excellent sample, and as always, super well explained. Thanks very much for all this great stuff you've been posting about COM Interop with .NET BTW, your session on this subject in SWFOX 2010 was great as well, and opened many, many doors to me ??

Cheers

Cesar

re: Doing .NET COM Interop with FoxPro? You need a .NET Disassembler



Rick Strahl
November 19, 2011

Thanks Cesar. I'll be posting more FoxPro content over the next few weeks as I've been working more extensively in Fox recently (bunch of Web Connection stuff). I have a backload of posts scheduled to be posted here.

 
© Rick Strahl, West Wind Technologies, 2003 - 2024