从VB6调用C dll,其中使用Visual Studio 2013编写dll

时间:2014-01-25 22:44:44

标签: c++ c dll vb6

这个问题将会很糟糕,但我正在大力推动我的车轮,而且我不确定如何更好地表达它。

我需要编写一个使用C的DLL,它将从VB6中调用。我正在使用Visual Studio Express 2013.我知道...... VB6很古老,我认为代码的管理者现在确信他们应该把它搞砸了。但与此同时,这需要做到。

首先,我试图编写一个带有单个函数的DLL,除了打印消息之外什么都不做,并且在使用VB.NET调用DLL时工作正常。

这是我对TinyDll.h的所作所为。

#ifdef TINYDLL_EXPORTS
#define TINYDLL_API __declspec(dllexport)
#else
#define TINYDLL_API __declspec(dllimport)
#endif

extern TINYDLL_API void __stdcall testdll();

这是TinyDll.cpp

#include "stdafx.h"
#include "TinyDll.h"
#include <stdexcept>

using namespace std;

void __stdcall testdll()
{
  printf("Got into the dll.\n");
}

顺便说一句,我已经尝试过这种情况,有没有__stdcall。我也尝试使用.def文件来解析dll中的名称,但现在我不清楚这应该有用。我发现的例子表明这应该有效

LIBRARY TinyDll
Exports
  testdll

但事实并非如此。 dll中的名称仍然是错误的形式:?testdll @@ YGXXZ。

我的测试代码相当简单,它与VB.NET完美配合,但它不适用于VB6。这个问题与VB6进程无法找到dll和/或找到它内部的函数有关。为了记录,这里是用于测试的VB6代码

Declare Sub testdll Lib "TinyDll.dll" Alias "?testdll@@YGXXZ" ()

Sub Main()
  testdll()
End Sub    

首先,我是否认为没有必要调用regsvr32或regasm? dll不是COM对象 - VB6正在调用我的C代码,而不是相反。当我们尝试执行这两项中的任何一项时,“找不到入口点DllRegisterServer”或“找不到指定的模块。”

最重要的是,VB6开发环境太旧,无法在我的Windows 7计算机上运行,​​并且尝试测试我的DLL的人处于另一种状态,并且严格来说是VB程序员。

我已经通过谷歌搜索阅读了所有可以找到的内容,所以我希望有人知道一个明确列出事实或展示工作实例的网站。

1 个答案:

答案 0 :(得分:0)

就像这种问题经常出现的情况一样(也就是说,一个涉及一个硬壳旧环境被用来做它从来没有意义的东西),它现在有效,但目前还不清楚为什么。

我们认为没有完整的dll路径,VB6找不到它。如果我们用

声明函数
Declare Function TestTinyDLL Lib "e:\full\path\down\to\TinyDll.dll" Alias "_testdll@0"

然后调用工作,但如果没有给出完整路径,无论dll在哪里,它都不起作用。我们还发现,我们可以通过如下“初始化”dll来避免提供完整路径(感谢:File not found when loading dll from vb6获取此线索):

Option Explicit

' Windows API method declarations
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias _
    "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, _
    ByVal msg As Any, ByVal wParam As Any, ByVal lParam As Any) _
    As Long
Private Declare Function FormatMessage Lib "kernel32" Alias _
    "FormatMessageA" (ByVal dwFlags As Long, lpSource As Long, _
    ByVal dwMessageId As Long, ByVal dwLanguageId As Long, _
    ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Any) _
    As Long

Declare Function BogusCall Lib "otherdll.dll" Alias "_BogusCall@0" () As Integer

Declare Function TestTinyDLL Lib "TinyDLL.dll" Alias "_testdll@0" () As Integer

Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000


Sub Main()

    InitializeDLL App.Path & "\" & "otherdll.dll", "_BogusCall@0"

    InitializeDLL App.Path & "\" & "TinyDLL.dll", "_testdll@0"

    Dim Version As String

    Version = "TinyDLLTestProgram" & vbCrLf & vbCrLf

    Version = Version & "BogusCall = " & CStr(BogusCall ()) & vbCrLf

    Version = Version & "TestTinyDLL= " & CStr(TestTinyDLL()) & vbCrLf

    Form1.txtOutput.Text = CStr(Version)

End Sub

Sub InitializeDLL(myDLL As String, myFunc As String)

    ' Locate and load the DLL. This will run the DllMain method, if present
    Dim dllHandle As Long
    dllHandle = LoadLibrary(myDLL)

    If dllHandle = 0 Then
        MsgBox "Error loading DLL" & vbCrLf & ErrorText(Err.LastDllError)
        Exit Sub
    End If

    ' Find the procedure you want to call
    Dim procAddress As Long
    procAddress = GetProcAddress(dllHandle, myFunc)

    If procAddress = 0 Then
        MsgBox "Error getting procedure address" & vbCrLf & ErrorText(Err.LastDllError)
        Exit Sub
    End If

    ' Finally, call the procedure
    CallWindowProc procAddress, 0&, "Dummy message", ByVal 0&, ByVal 0&

End Sub

' Gets the error message for a Windows error code
Private Function ErrorText(errorCode As Long) As String

    Dim errorMessage As String
    Dim result As Long

    errorMessage = Space$(256)
    result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, errorCode, 0&, errorMessage, Len(errorMessage), 0&)

    If result > 0 Then
        ErrorText = Left$(errorMessage, result)
    Else
        ErrorText = "Unknown error"
    End If

End Function

为什么这项工作很神秘,但确实如此。我希望这可以帮助其他人面对旧的VB6代码!