私が取り組んでいるプロジェクト用に 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 をより最新のものに (実行時に、再構築せずに) 置き換えることは困難です。