none
アプリケーション起動時に「エントリポイントが見つかりません」のエラーをチェックしたい RRS feed

  • 質問

  • いつもお世話になっております。
    arubi-momoと申します。

    Windows10 64bit VisualStudio2017 VC++ で開発しております。

    現在改修しているアプリケーションは、アプリケーション.exeと独自DLLで構成されており、独自DLLも場合によっては改修することがあります。

    独自DLLのインターフェースが変更になり、新しいアプリケーションから古いDLLを参照した場合、新しいアプリ内で使用している関数が古いDLLには存在しないことから、エラー「エントリポイントが見つかりません」が表示されます。

    このエラーを出している場所で、エラーを判別して、「DLLのバージョンが異なる」ことを知らせるメッセージを出せないかと考えました。

    デバッグモードでどのタイミングでDLLを参照しているのか確認しようとしましたが、ブレイクポイントをメインフレームの生成やアプリケーション起動時に設定しても、上記の「エントリポイントが見つかりません」のエラーが先に表示されてしまいます。

    アプリケーション内でこのような処理をいれることは不可能なのでしょうか?

    ご存じの方がいらっしゃいましたら、ご教示いただければ幸いです。

    よろしくお願いいたします。

    2021年7月1日 6:24

回答

  • DLLの関数ポインターをテストする方法なら以下の通りです。

     (1)明示的に HINSTANCE hInst = LoadLibraryEx(「DLLのパス」); して、インスタンスハンドルを得る。
     (2)明示的に FARPROC Proc = GetProcAddress( hInst, 「関数名」);して関数ポインタ Proc を得る
     (3)上記が「Proc == NULL」ならば、その関数は無い。そうでなければ有る(引数がわかればそのポインターをコールできる)

    のような手順です。
    エラーが発生する箇所ではなく、ロード直後に全てチェックする方法です。
    C言語インターフェースのDLLでかつエクスポート名を指定している場合には、
    関数名が自明なので楽ですけど、そうでない場合は調べる必要があるかもしれません。

    DLLにバージョンを付け加えれば(リソースで)、これを参照するだけで機能を判別できます。
    一般的な運用では、これで管理します。

    2021年7月1日 7:19
  • DelayLoad指定して__HrLoadAllImportsForDll呼んで、構造化例外を捕まえればいいのでは。

    リンカーによる DLL の遅延読み込み


    jzkey

    • 回答としてマーク arubi_momo 2021年7月2日 0:28
    2021年7月1日 10:21
  • デバッグモードでどのタイミングでDLLを参照しているのか確認しようとしましたが、ブレイクポイントをメインフレームの生成やアプリケーション起動時に設定しても、上記の「エントリポイントが見つかりません」のエラーが先に表示されてしまいます。

    そもそも必要なDLLが読み込みできていないため、プロセスが開始されていません(厳密には開始前の停止状態かな…?)。開始されていない以上、何もできません。

    そのため、まず最初の対策としてDLLを読み込まないことです。その上で、DLLをどう読み込むか、です。

    仲澤@失業者さんの紹介された方法が本質的ですが、リンカーによる DLL の遅延読み込みを利用することで大部分について支援を受けることができます。これがjzkeyさんの紹介された方法です。

    • 回答としてマーク arubi_momo 2021年7月2日 0:28
    2021年7月1日 10:46

すべての返信

  • DLLの関数ポインターをテストする方法なら以下の通りです。

     (1)明示的に HINSTANCE hInst = LoadLibraryEx(「DLLのパス」); して、インスタンスハンドルを得る。
     (2)明示的に FARPROC Proc = GetProcAddress( hInst, 「関数名」);して関数ポインタ Proc を得る
     (3)上記が「Proc == NULL」ならば、その関数は無い。そうでなければ有る(引数がわかればそのポインターをコールできる)

    のような手順です。
    エラーが発生する箇所ではなく、ロード直後に全てチェックする方法です。
    C言語インターフェースのDLLでかつエクスポート名を指定している場合には、
    関数名が自明なので楽ですけど、そうでない場合は調べる必要があるかもしれません。

    DLLにバージョンを付け加えれば(リソースで)、これを参照するだけで機能を判別できます。
    一般的な運用では、これで管理します。

    2021年7月1日 7:19
  • DelayLoad指定して__HrLoadAllImportsForDll呼んで、構造化例外を捕まえればいいのでは。

    リンカーによる DLL の遅延読み込み


    jzkey

    • 回答としてマーク arubi_momo 2021年7月2日 0:28
    2021年7月1日 10:21
  • デバッグモードでどのタイミングでDLLを参照しているのか確認しようとしましたが、ブレイクポイントをメインフレームの生成やアプリケーション起動時に設定しても、上記の「エントリポイントが見つかりません」のエラーが先に表示されてしまいます。

    そもそも必要なDLLが読み込みできていないため、プロセスが開始されていません(厳密には開始前の停止状態かな…?)。開始されていない以上、何もできません。

    そのため、まず最初の対策としてDLLを読み込まないことです。その上で、DLLをどう読み込むか、です。

    仲澤@失業者さんの紹介された方法が本質的ですが、リンカーによる DLL の遅延読み込みを利用することで大部分について支援を受けることができます。これがjzkeyさんの紹介された方法です。

    • 回答としてマーク arubi_momo 2021年7月2日 0:28
    2021年7月1日 10:46
  • 仲澤@失業者様
    jzkey様

    ご回答いただきまして誠にありがとうございます。

    また、佐祐理様、補足いただきましてありがとうございます。とても理解しやすく助かりました。

    今現在のつくりでは、アプリ側では何も判別できないことが理解できました。しかし、方法を伺うことできましたので実装が可能ということもわかりましたので、どちらの方法がよいか確認して実装していこうと思います。

    また不明点がございましたら、フォーラムでご相談するかもしれませんが、こちらの質問はクローズにさせていただきます。

    皆様、ありがとうございました。今後ともどうぞよろしくお願いいたします。


    2021年7月2日 0:28