6

VB6で次の構文を使用してdll関数を宣言して呼び出しています。

'Declare the function
Private Declare Sub MYFUNC Lib "mylib.dll" ()

'Call the function
MYFUNC

関数を呼び出すと、エラーが発生しますFile not found: mylib.dll。これは、アプリケーションがvb6IDEまたはコンパイルされた実行可能ファイルから実行された場合に発生します。

dllは作業ディレクトリにあり、sysinternalsのProcMon.exeを使用して見つかったことを確認しました。ロードに失敗することはありませんが、Intel Fortran dllはロードされません(ProcMonトレースはそれ以前に停止しているようです)。

WinDbg.exeでアプリケーションを実行してみましたが、奇妙なことに、動作します。この回線に障害はありません。ProcMonトレースは、プログラムがこのように実行されたときにIntelFortrandllがロードされることを示しています。

dllは、Fortran ComposerXE2011でコンパイルされています。

誰かが助けを提供できますか?

4

5 に答える 5

7

DLL をロードするとき、「ファイルが見つかりません」と誤解されることがよくあります。依存している DLL またはファイルが見つからないことを意味している可能性がありますが、その場合は Process Monitor で問題を発見できたはずです。

多くの場合、「ファイルが見つかりません」というメッセージは、実際には DLL が見つかったことを意味しますが、DLL のロード時またはメソッドの呼び出し時にエラーが発生しました。

DLL でプロシージャを呼び出すには、実際には次の 3 つの手順があります。

  1. DLL を見つけてロードし、存在する場合は DllMain メソッドを実行します。
  2. DLL でプロシージャを見つけます。
  3. プロシージャを呼び出します。

エラーは、これらのどの段階でも発生する可能性があります。VB6 はこれらすべてを舞台裏で行うため、エラーがどこで発生しているかはわかりません。ただし、Windows API 関数を使用してプロセスを制御できます。これにより、エラーが発生している場所がわかります。ブレークポイントを設定し、Process Monitor を使用して各ポイントでプログラムの動作を調べることもできます。これにより、より多くの洞察が得られる場合があります。

次のコードは、Windows API を使用して DLL プロシージャを呼び出す方法を示しています。それを実行するには、コードを新しいモジュールに入れ、プロジェクトのスタートアップ オブジェクトを "Sub Main" に設定します。

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

Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000

Const MyFunc As String = "MYFUNC"
Const MyDll As String = "mylib.dll"

Sub Main()

    ' 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
于 2013-01-22T09:25:10.560 に答える
4

.dll は、現在の「作業」ディレクトリ (または登録済み) にある必要があります。そうでない場合、アプリケーションは実行時にそれを見つけることができません。

行う:

MsgBox "現在のディレクトリは " & CurDir

そして、それをあなたが期待していたものと比較してください。.dll はそのディレクトリにある必要があります。

于 2013-01-13T06:11:26.103 に答える
1

この問題に対する私の標準的な最初のアプローチは、ProcMon (または XP では FileMon) を分解することです。ファイルを検索している正確な場所を確認できるように、フィルターを設定します。他の場所でファイルを探しているか、別のファイル名を探している可能性があります。

于 2013-01-12T00:49:38.047 に答える