試してみると、意外と素直に書けたのでメモ。
とあるプロジェクトで、フォームが100画面ほどある VB プロジェクトを作りました。
その VB プロジェクトを起動するときに、なんらかの形で、main window を切り替えたいという要望です。
# フォームごとにアセンブリを分ければ良いのですが、
# フォーム間で参照設定が多くて、結局ひとつのアセンブリにしないと循環参照が解決されない…という現象です。
# 本当は、メモリ使用量を減らすために、個別に exe を作るのがいいんでしょうが。
フォームが 100 画面ほどある exe にパラメータを指定して、
1 | FormCollection Form1 |
で起動します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Module Startup Public Sub main( ByVal args() As String ) ' 引数からクラス名を取得 Dim cname As String = args(0) cname = "FormCollection." + cname ' 指定フォームを作成 Dim t As Type = Type. GetType (cname) If t IsNot Nothing Then Dim obj As Object = System.Activator.CreateInstance(t) If obj IsNot Nothing Then ' アプリケーションを起動 Dim frm As Form = CType (obj, Form) Application.Run(frm) End If End If End Sub End Module |
ここでは、namespace が FormCollection なので、これを追加しています。
さて、本体 exe の名前を変えて Form1.exe, Form2.exe, Form3.exe … と作ってもよいのですが、本体 exe のサイズが大きい場合には、コピーすると HDD 容量が必要になります。
なので、起動用に別のプロジェクトを作って、次のような startup にします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Module Startup Public Sub main( ByVal args() As String ) ' クラス名を実行ファイルから取得 Dim cname As String = Application.ExecutablePath cname = cname.Substring( _ cname.LastIndexOf("\") + 1, _ cname.Length - cname.LastIndexOf("\") - 1) cname = cname.Substring(0, cname.LastIndexOf( "." )) cname = "FormCollection." + cname ' アセンブリのロード Dim asm As System.Reflection. Assembly = _ System.Reflection. Assembly .LoadFrom( "FormCollection.exe" ) ' 指定フォームを作成 Dim t As Type = asm. GetType (cname) If t IsNot Nothing Then Dim obj As Object = System.Activator.CreateInstance(t) If obj IsNot Nothing Then ' アプリケーションを起動 Dim frm As Form = CType (obj, Form) Application.Run(frm) End If End If End Sub End Module |
ってな風なのを考えた訳ですが、本体のロード時間を考えると必要なフォームだけをかき集めた exe を作るのがベストですね。
まぁ、本体が 3 MB 程度なので、これでよしとしますか。