我有一个带有类LoginClass和一个函数LoginUser的vb6 COM dll。我需要从C#动态调用此vb6 COM dll。我正在尝试使用C#代码动态访问它,但即使在LoadLibrary返回指针之后,GetProcAddress也返回0。
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;
}
}
答案 0 :(得分:2)
每当您尝试在DLL中调用函数时,首先在DLL上运行dumpbin.exe / exports。从Visual Studio命令提示符执行此操作。它显示了DLL导出的函数的名称。
在这种情况下,非常可能只会看到4个导出的函数,即任何与自动化兼容的COM服务器导出的函数。 DllGetClassObject,DllRegisterServer,DllUnregisterServer和DllCanUnloadNow。你会不看到LoginUser。 DllUn / RegisterServer由Regsvr32.exe调用,仅用于从注册表注册和删除服务器。 DllCanUnloadNow是Windows调用的函数,用于检查DLL是否可以从内存中卸载。 DllGetClassObject是大狗,它是类工厂函数并创建对象。使用任何COM服务器的必要起点是首先创建一个对象。然后你可以调用该对象的方法,其中一个无疑被命名为LoginUser。
要在VB.NET代码中使用这样的COM服务器,请从Project + Add Reference开始。单击“浏览”选项卡或按钮,然后导航到DLL。 Visual Studio将读取嵌入在DLL中的类型库,它包含服务器实现的对象和接口的声明。假设VB6 dll名为“foo.dll”,您将在构建目录中获得Interop.Foo.dll文件。将此程序与您的程序以及COM服务器的安装程序一起发送,因此它也可以在用户的计算机上运行。
如果您不知道这些对象是什么样的,请单击Solution Explorer窗口中的Show All Files图标,打开References节点,右键单击您的COM服务器并选择Show in Object Browser。 IntelliSense将进一步帮助您陷入成功之中。