C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

DLLがない場合のエラーメッセージ

[トピック内 14 記事 (1 - 14 表示)]  << 0 >>

■100091 / inTopicNo.1)  DLLがない場合のエラーメッセージ
  
□投稿者/ とり (1回)-(2022/07/02(Sat) 23:23:21)

分類:[.NET 全般] 



VB.NETを使用しております


EXEファイルと同じフォルダーにDLLファイルが入っており
それを参照して読み込むプログラムを作成しています。

もし、DLLファイルがない状態でEXEファイルを起動しようとすると
エラーメッセージも無しでクラッシュして終了してしまいます。

そのため、他の人に使ってもらった際に
○○のDLLが必要です、というエラーメッセージを表示した方が
親切だと考えています。

起動時に、DLLを参照する前に
DLLが存在するかチェックしてメッセージボックスを表示するにはどうしたら良いでしょうか?




引用返信 編集キー/
■100092 / inTopicNo.2)  Re[1]: DLLがない場合のエラーメッセージ
□投稿者/ KOZ (247回)-(2022/07/03(Sun) 01:22:38)
No100091 (とり さん) に返信
> EXEファイルと同じフォルダーにDLLファイルが入っており
(略)
> DLLが存在するかチェックしてメッセージボックスを表示するにはどうしたら良いでしょうか?

EXE ファイルのフルパスは System.Reflection.Assembly.GetEntryAssembly().Location で取得できるので、
そこから DLL ファイルのフルパスを求めて存在チェックをし、なければメッセージボックスを表示するだけです。

何が分からなくてつまっているのでしょうか?

引用返信 編集キー/
■100093 / inTopicNo.3)  Re[2]: DLLがない場合のエラーメッセージ
□投稿者/ 774RR (888回)-(2022/07/03(Sun) 05:30:02)
普通はファイルを単独で配布するなどありえないっス
インストーラを構成して必要なファイルは過不足なくコピーするものです

だから必要なファイルがない・・・なんてことはないはずなんだけど。


引用返信 編集キー/
■100094 / inTopicNo.4)  Re[3]: DLLがない場合のエラーメッセージ
□投稿者/ KOZ (248回)-(2022/07/03(Sun) 07:02:11)
−本当にあった怖い話−

むかしむかし、Win9x が動いていたころの話。

私がプログラムを作って先輩が納品したんですが(ハンディーターミナルからデータを吸い上げて ORACLE に登録するものだった)
ある日「データベースに接続できませんでした」というメッセージを出して動かなくなったそうです。
なにか心当たりはないか聞かれたのですが、ファイルサーバーには接続できるらしく、LAN ケーブルが断線したとかそういうのでもないらしい。
現地に飛んだ先輩が見たものは・・・

ORACLE のインストールフォルダがごみ箱につっこんであったそうです。(^_^;)
おそらく複数の人が同じPCを共有して使ってるような環境だったんじゃないかなーと今になって思うんですけどね。

そのお客さんが偉かったのは(えらいのか?)なにかあるかもしれないから、ごみ箱に入れただけだったらしい。
ごみ箱から取り出すと、プログラムは無事に動いたそうです。めでたしめでたし。

こんなお客さんに対峙していると、こういう発想にもなるのかなぁ・・・と思った次第

引用返信 編集キー/
■100095 / inTopicNo.5)  Re[4]: DLLがない場合のエラーメッセージ
□投稿者/ とり (2回)-(2022/07/03(Sun) 10:42:59)
No100094 (KOZ さん) に返信


ありがとうございます。

>何が分からなくてつまっているのでしょうか?


もちろんファイルのチェック方法は知っていますが


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

の最初にファイルチェックを入れたとしても、
これよりも前の段階でDLL読み込みが行われるため、
ファイルチェックする前にプログラムが落ちてしまうのですが・・・
どこに記述すれば良いですか?
引用返信 編集キー/
■100096 / inTopicNo.6)  Re[5]: DLLがない場合のエラーメッセージ
□投稿者/ radian (63回)-(2022/07/03(Sun) 11:12:07)
No100095 (とり さん) に返信
> Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
>
> の最初にファイルチェックを入れたとしても、
> これよりも前の段階でDLL読み込みが行われるため、
> ファイルチェックする前にプログラムが落ちてしまうのですが・・・
> どこに記述すれば良いですか?

読み込まれる前にチェックすればいいんじゃないですか?
エラー発生時のスタックトレースはどこが発生元になっていますか?
Loadより早い場所だと、Formのコンストラクタ、
もしくはエントリポイントを作成してそこからフォームを起動するようにして、
フォーム起動より前にチェックすれば良いと思いますが。

[アプリケーションのエントリポイントを自作する]
https://dobon.net/vb/dotnet/programing/makeentrypoint.html
引用返信 編集キー/
■100097 / inTopicNo.7)  Re[5]: DLLがない場合のエラーメッセージ
□投稿者/ KOZ (249回)-(2022/07/03(Sun) 11:13:48)
No100095 (とり さん) に返信
> これよりも前の段階でDLL読み込みが行われるため、
> ファイルチェックする前にプログラムが落ちてしまうのですが・・・
> どこに記述すれば良いですか?

プロジェクトのプロパティを表示すると、「アプリケーション」タブに 「Windows アプリケーション フレームワーク プロパティ」というのがあると思います。

その中に、「アプリケーション イベントの表示」というボタンがあるので、それをクリックすると ApplicationEvents.vb というファイルが作られます。

作成された MyApplication クラスの OnStartup メソッドをオーバーライドし、その中に処理を記述します。

メソッドの戻り値として False を返すと、プログラムは起動せず終了します。

Imports Microsoft.VisualBasic.ApplicationServices

Namespace My
    ' 次のイベントは MyApplication に対して利用できます:
    ' Startup:アプリケーションが開始されたとき、スタートアップ フォームが作成される前に発生します。
    ' Shutdown:アプリケーション フォームがすべて閉じられた後に発生します。このイベントは、アプリケーションが異常終了したときには発生しません。
    ' UnhandledException:ハンドルされない例外がアプリケーションで発生したときに発生します。
    ' StartupNextInstance:単一インスタンス アプリケーションが起動され、それが既にアクティブであるときに発生します。 
    ' NetworkAvailabilityChanged:ネットワーク接続が接続されたとき、または切断されたときに発生します。
    Partial Friend Class MyApplication

        Protected Overrides Function OnStartup(eventArgs As StartupEventArgs) As Boolean
            ' ここに処理を書く
            Return MyBase.OnStartup(eventArgs)
        End Function

    End Class
End Namespace




引用返信 編集キー/
■100099 / inTopicNo.8)  Re[6]: DLLがない場合のエラーメッセージ
□投稿者/ とり (3回)-(2022/07/03(Sun) 13:50:31)
2022/07/03(Sun) 13:51:04 編集(投稿者)
ありがとうございます。

試してみたのですが
うまくいきません。


https://dobon.net/vb/dotnet/programing/makeentrypoint.html

を参考にして、

    Module Program
        <STAThread()>
        Sub Main()

            If File.Exists(DLL_Path) = True Then

                Application.EnableVisualStyles()
                Application.SetCompatibleTextRenderingDefault(False)
                Application.Run(New Form1())

            Else

                MsgBox("Error")
            End If

        End Sub
    End Module

のようにしてみました。

DLLがある場合に、普通に起動できます。

しかし、DLLがない場合には、メッセージボックスを表示せずに
プログラムはクラッシュしてしまいます。

Application.Run(New Form1())
の部分だけコメントアウトすると、メッセージボックスは表示されます。

どうも、DLLが存在しない場合、

Application.Run(New Form1())
というコードがMainの中に入っていると、
Mainを実行する前にプログラムは強制終了してしまうようです。

これは一体どうすれば良いでしょうか?

引用返信 編集キー/
■100100 / inTopicNo.9)  Re[7]: DLLがない場合のエラーメッセージ
□投稿者/ radian (64回)-(2022/07/03(Sun) 14:25:04)
No100099 (とり さん) に返信

> どうも、DLLが存在しない場合、
>
> Application.Run(New Form1())
> というコードがMainの中に入っていると、
> Mainを実行する前にプログラムは強制終了してしまうようです。
>
> これは一体どうすれば良いでしょうか?

Try-Catchで例外処理したらどうでしょう。
情報を小出しにせずに、詳細なエラーの内容を載せてください。
引用返信 編集キー/
■100101 / inTopicNo.10)  Re[7]: DLLがない場合のエラーメッセージ
□投稿者/ KOZ (250回)-(2022/07/03(Sun) 14:29:49)
No100099 (とり さん) に返信
> Application.Run(New Form1())
> の部分だけコメントアウトすると、メッセージボックスは表示されます。

dll の中に カスタム Form があり、Form1 はそれを継承して作っていませんか?
New Form1 の部分を別のメソッドにするか、別のモジュールに持っていくかすれば解消するかもしれません。


引用返信 編集キー/
■100103 / inTopicNo.11)  Re[8]: DLLがない場合のエラーメッセージ
□投稿者/ とり (4回)-(2022/07/03(Sun) 14:38:50)
ありがとうございます。

> 情報を小出しにせずに、詳細なエラーの内容を載せてください

エラーメッセージは表示されずに、プログラムは強制終了してしまいます。



> dll の中に カスタム Form があり、Form1 はそれを継承して作っていませんか?

継承して作っていません。



> New Form1 の部分を別のメソッドにするか、別のモジュールに持っていくかすれば解消するかもしれません。

仰る通り、別のメソッドにするとエラーなく実行できるようになりました。

これって一体どういう理屈なのでしょうか?
できれば、原因をお教えいただけないでしょうか?



引用返信 編集キー/
■100104 / inTopicNo.12)  Re[9]: DLLがない場合のエラーメッセージ
□投稿者/ KOZ (251回)-(2022/07/03(Sun) 14:48:43)
No100103 (とり さん) に返信
>>dll の中に カスタム Form があり、Form1 はそれを継承して作っていませんか?
> 継承して作っていません。

dll のインターフェイスも実装したりしてないですか?
とすると貼られているカスタムコントロールが Public になっているとかでしょうか?

>>New Form1 の部分を別のメソッドにするか、別のモジュールに持っていくかすれば解消するかもしれません。
> 仰る通り、別のメソッドにするとエラーなく実行できるようになりました。
> これって一体どういう理屈なのでしょうか?
> できれば、原因をお教えいただけないでしょうか?

原因は不明ですが、Form1 という型を参照する行為そのものが、dll の何かの部分を必要としているのでしょうね。
引用返信 編集キー/
■100105 / inTopicNo.13)  Re[10]: DLLがない場合のエラーメッセージ
□投稿者/ とり (5回)-(2022/07/03(Sun) 15:01:01)
ありがとうございます。

確かにDLLの中のインターフェースをForm1で使用しています。

ただし、New Formが実行されるまでは
DLL内のインターフェースのインスタンスは生成されないはずなので、
エラーになっている理由が分かりませんでした。

恐らく、New Formというコードがある場合、
コードの最初の段階でForm内のインターフェースがあるかについてもチェックしているのですね。きっと。


解決済み
引用返信 編集キー/
■100106 / inTopicNo.14)  Re[9]: DLLがない場合のエラーメッセージ
□投稿者/ Azulean (1246回)-(2022/07/03(Sun) 16:47:26)
2022/07/03(Sun) 16:49:46 編集(投稿者)

No100103 (とり さん) に返信
> 仰る通り、別のメソッドにするとエラーなく実行できるようになりました。
> これって一体どういう理屈なのでしょうか?
> できれば、原因をお教えいただけないでしょうか?

.NET Framework は C# や VB.NET の言語をコンパイルして、MSIL という中間言語コードを生み出して、DLL/EXE ファイルに含めています。
中間言語コードは、実行時に JIT という仕組みで実行可能なコードに変換しています。
この JIT が動いたときに解釈される「範囲(メソッドとかクラスとか)」に存在する「型」を解釈するために、DLL の読み込みが行われますので、その段階で DLL が見つからないなら例外となります。

今回の場合、元のコードの Main に Form1 という型が出現するので、Form1 に関する情報の読み込みが進む中で、DLL が足りなかったということでしょう。
メソッドを分ければ、1 度の JIT のスコープから外れるかもしれませんが、この挙動は仕様として保証されているわけではないと思うので、いつでも成り立つとは限りません。

できる範囲で取り組むことは否定しませんが、恒久的に実現できる仕様として約束しない方が良いと思います。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ