0

I have a vb6 COM dll with a class LoginClass and a function LoginUser in it. I need to dynamically call this vb6 COM dll from C#. I am trying below C# code to access it dynamically but the GetProcAddress is returning 0 even after a pointer returned by LoadLibrary.

static class NativeMethods
{
    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

    [DllImport("kernel32")]
    public static extern bool FreeLibrary(IntPtr hModule);
}
class COMCommands
{    
 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
 private delegate string Login(string userName, string Password, bool Result);

 public string CallLoginCommand(string UserName, string Password, ref bool Result)
 {
  IntPtr pDll = NativeMethods.LoadLibrary(@"D:\MyCOMdll.dll");

  IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "LoginUser");

  Login CallLogin = (Login)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(Login));

  string theResult = CallLogin(UserName, Password, Result);

  bool result = NativeMethods.FreeLibrary(pDll);
  return theResult;
 }
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Mohammad Nadeem
  • 9,134
  • 14
  • 56
  • 82
  • 2
    You **can not** call a VB6 library like that, it **does not export any "C style" function** you can import. Take a look to [this link](http://stackoverflow.com/questions/2257883/using-a-vb6-class-in-c-sharp). – Adriano Repetti Jul 01 '13 at 07:37
  • Does this mean a vb6 COM dll can't be dynamically called from C#. – Mohammad Nadeem Jul 01 '13 at 08:58
  • 1
    No, you can always **call them through COM interop**, you just **can not DllImport** (it's more or less equivalent to LoadLibrary + GetProcAddress) an exported function (actually because **there is not a C style exported function**). – Adriano Repetti Jul 01 '13 at 09:02

1 Answers1

2

Whenever you try to pinvoke a function in a DLL, first run dumpbin.exe /exports on the DLL. Do so from the Visual Studio Command Prompt. It shows you the names of the functions exported by the DLL.

In this case, it is very likely that you'll see only 4 exported functions, the ones that any Automation compatible COM server exports. DllGetClassObject, DllRegisterServer, DllUnregisterServer and DllCanUnloadNow. And you will not see LoginUser. DllUn/RegisterServer are called by Regsvr32.exe, only used to register and remove the server from the registry. DllCanUnloadNow is a function called by Windows to check if the DLL can be unloaded from memory. DllGetClassObject is the big dog, it is a class factory function and creates objects. A necessary starting point to use any COM server is to create an object first. Then you can call methods on that object, one of which no doubt is named LoginUser.

To use a COM server like this in your VB.NET code, start with Project + Add Reference. Click the Browse tab or button and navigate to the DLL. Visual Studio will read the type library that's embedded in the DLL, it contains the declarations of the objects and interfaces implemented by the server. You'll get an Interop.Foo.dll file in your build directory, assuming the VB6 dll is named "foo.dll". Ship this along with your program, as well as an installer for the COM server, so it works on your user's machine as well.

If you have no idea what those objects look like then click the Show All Files icon in the Solution Explorer window, open the References node, right-click your COM server and select Show in Object Browser. IntelliSense will further help you fall in the pit of success.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536