2

私が取り組んでいるプロジェクト用に 2 つのソリューションを作成しています。1 つはメイン サーバー用で、理想的には更新の必要なく継続的に実行されます。2 つ目の解決策は DLL です。プログラマはコードを継続的に変更および更新します。サーバー ソリューションは Windows アプリケーションであり、プログラマーのソリューション (常に変化するもの、別名 JupiterCode.dll) はクラス ライブラリです。

必要な telnet 経由でコードにアクセスし、そこにコマンドを入力します。入力文字列は、DLL ファイルへのリフレクションを介して実行されます (「ユーザーは 'smile' を入力しました。'smile' というコマンドはありますか? はい、わかりました。そのコードを実行しましょう。」)。私はすべての作業を行っており、順調に進んでいますが、実際に DLL を更新して、ユーザーが入力できるコマンドを増やしたい場合に問題が発生します。クラス ライブラリを再構築しても、サーバーはまだ新しい変更を反映していません。サーバーを再構築すると、サーバーは新しい変更のみを反映します。

ユーザーがtelnetサーバーにUPDATEを入力すると、ロードされたDLLが新しいDLLで更新されるようにしようとしていますが、次のようなことをしようとすると...

     string originalDllPath = "C:\\Users\\*****\\Documents\\PseudoGameClient\\bin\\Debug\\JupiterCode.dll";
 string newDllPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\.dll";
 string newDllBakPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeNewBak.dll";
 string oldDllPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCode.dll";
 string oldDllBakPath = "C:\\Users\\*****\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeBak.dll";

 try
 {
 File.Copy(originalDllPath, newDllPath, true);

 AppDomain.Unload(updatedCodeDomain);
 AppDomain sandbox = AppDomain.CreateDomain("Sandbox");
 Assembly assembly = sandbox.Load(oldDllBakPath);
 upToDateCode = assembly;
 File.Copy(oldDllPath, newDllBakPath, true);
 File.Copy(newDllPath, oldDllPath, true);

 AppDomain.Unload(sandbox);
 AppDomain newCodeDomain = AppDomain.CreateDomain("NewCode");
 assembly = newCodeDomain.Load(oldDllPath);
 upToDateCode = assembly;
 File.Copy(newDllBakPath, oldDllBakPath, true);

 File.Delete(newDllPath);
 File.Delete(newDllBakPath);
 updatedCodeDomain = newCodeDomain;
 }
 catch (Exception ex)
 {
 }

この方法では、

Assembly assembly = sandbox.Load(oldDllBakPath);

それは私に例外を与えます:

「ファイルまたはアセンブリ 'C:\\Users\\aderbedrosia\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeBak.dll' またはその依存関係の 1 つを読み込めませんでした。指定されたアセンブリ名またはコードベースが無効でした。( HRESULT からの例外: 0x80131047)":"C:\\Users\\aderbedrosia\\Documents\\PseudoServerStub\\bin\\Debug\\JupiterCodeBak.dll"} System.Exception {System.IO.FileLoadException

(注: Uptodatecode は、後でコマンドを実行するために参照するため、クラス フィールドとして保持されます。これもまた、更新できないことを除けば、完全に正常に動作しています。)

私も試しました:

 File.Copy(originalDllPath, newDllPath, true);
 Assembly assembly = Assembly.LoadFrom(oldDllBakPath);
 AppDomain.Unload(updatedCodeDomain);

 AppDomain sandbox = AppDomain.CreateDomain("sandbox");
 sandbox.Load(assembly.GetName());
 upToDateCode = null;
 upToDateCode = assembly;
 File.Copy(oldDllPath, newDllBakPath, true);
 File.Copy(newDllPath, oldDllPath, true);
 assembly = Assembly.LoadFrom(oldDllPath);
 AppDomain.Unload(sandbox);

 AppDomain sandbox2 = AppDomain.CreateDomain("secondarySandbox");
 sandbox2.Load(assembly.GetName());
 upToDateCode = assembly;
 File.Copy(newDllBakPath, oldDllBakPath, true);
 File.Delete(newDllPath);
 File.Delete(newDllBakPath);
 updatedCodeDomain = sandbox2;

そして、それはエラーになります

sandbox.Load(assembly.GetName());

"ファイルまたはアセンブリ 'JupiterCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a98a67e4d0b3db8' またはその依存関係の 1 つを読み込めませんでした。指定されたファイルが見つかりません.":"JupiterCode, Version=1.0.0.0, Culture =ニュートラル、PublicKeyToken=9a98a67e4d0b3db8"

繰り返しますが、実行時にアセンブリを動的に読み込むことはできますが、読み込まれた DLL をより最新のものに (実行時に、再構築せずに) 置き換えることは困難です。

4

1 に答える 1

0

同じ問題に直面している人のために、動的コンパイラを使用できました。CSharpCodeProvider と CSharpCodeProvider.CompileAssemblyFromFile を調べます。それは私が必要としていたすべてでした。

于 2013-03-24T16:15:33.353 に答える