【问题标题】:C# GetProcAddress Returns 0 while calling vb6 COM dll functionC# GetProcAddress 在调用 vb6 COM dll 函数时返回 0
【发布时间】:2013-06-28 06:33:15
【问题描述】:

我有一个带有类 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;
 }
}

【问题讨论】:

  • 不能这样调用VB6库,它不会导出任何你可以导入的“C风格”函数。看看this link
  • 这是否意味着无法从 C# 动态调用 vb6 COM dll。
  • 不,你总是可以通过COM互操作调用它们,你只是不能DllImport(它或多或少相当于LoadLibrary + GetProcAddress)一个导出函数(其实是因为没有C风格的导出函数)。

标签: c# com vb6 marshalling com-interop


【解决方案1】:

当您尝试在 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 服务器的安装程序一起提供,因此它也可以在您的用户计算机上运行。

如果您不知道这些对象的外观,请单击“解决方案资源管理器”窗口中的“显示所有文件”图标,打开“引用”节点,右键单击您的 COM 服务器并选择“在对象浏览器中显示”。 IntelliSense 将进一步帮助您跌入成功的深渊。

【讨论】:

    猜你喜欢
    • 2017-12-16
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 2017-12-21
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 2011-02-07
    相关资源
    最近更新 更多