How do my .NET-based clients get the app's HINSTANCE to pass to my function?

来源:互联网 发布:js回调函数的执行顺序 编辑:程序博客网 时间:2024/05/22 10:26

Q I'm in the process of converting an existing C++ class library to the Managed Extensions so I can expose it to my .NET Framework-based clients. Some of my code calls API functions that require the HINSTANCE of the current running module. I don't want to use the HINSTANCE of my DLL; I want the caller to supply the HINSTANCE of the EXE calling my DLL. I can declare the HINSTANCE parameter as an IntPtr, but how do my .NET-based clients get the app's HINSTANCE to pass to my function? For example, how would they do it in C#?

Hunter Gerson

A Good question! This one stumped me for about 15 minutes. In MFC you can call AfxGetInstanceHandle(). MFC stores the HINSTANCE in its Application object, in CWinApp::m_hInstance. So if you're using the Microsoft® .NET Framework, you might think that you should take a look in the Application object for Application.HInstance or an Application property or some such thing. Why not? Because it's not there!

If you search the Framework documentation for "hinstance," you'll discover there's a method Marshal.GetHINSTANCE. Well, that sounds promising. This static Marshal method requires the module whose HINSTANCE you want to obtain:

// In C#
Module m;
...
IntPtr h = Marshal.GetHINSTANCE(m);

Now you know how to get the HINSTANCE—but where do you get the module? Again, you might think to look in the Application class for something like Application.GetModule. Or perhaps Application is derived from module, that would make sense. Alas, neither is true. Well, maybe there's a Module property. Nope. Well, not quite. There is a Module property, but it's not a property of the Application, it's a Type property. In the .NET Framework, every object has a Type and every Type has a Module. Type.Module represents whichever module implements the type. So to get the HINSTANCE of the calling module, your clients can write:

Type t = myObj.GetType();
Module m = t.Module;
IntPtr h = Marshal.GetHINSTANCE(m);

You can also use typeof (--typeof in C++)to get the type without an object instance, as in typeof(MyApp). Just tell your customers to make sure they use a type that's implemented in the calling module. If you use some other type—for example, one of the Framework types like String—you'll get the wrong module.

Figure 1 shows a simple C# console app, ShowModule, that illustrates this. Figure 2 shows it running. ShowModule displays module information including the HINSTANCE for two types: the MyApp class defined in the application itself and the String[] (String array) type defined in mscorlib.

Figure 2 Module Information
Figure 2 Module Information