1

サーバー上で実行する C# で記述されたアプリケーション (.NET コンソール アプリ) があります。ときどき (週に約 2 回) アプリケーションがクラッシュします。たとえば、ネットワークのダウンなどが原因である可能性がありますが、それは重要ではありませんが、私が望むのは、アプリケーションがクラッシュしたときです。単に静かに再起動します。ソースがないため、これを行うようにアプリケーションを書き直すことはできません。これに対する簡単な解決策が必要なので、次のようなバット ファイルを作成しようとしました。

:start
@BotR.TestR.exe
echo sleeping
@ping 123.45.67.89 -n 1 -w %1000 > nul
goto start

ただし、アプリケーション (BotR.TestR.exe) がクラッシュするたびに、アプリケーションがクラッシュしたことを知らせるポップアップ ウィンドウが表示され、アプリケーションの続行が停止され、再起動が停止されます。これを解決できる簡単な方法はありますか?

4

1 に答える 1

1

これが最善の方法かどうかはわかりませんが、 Mono Cecilを使用してアプリケーションを書き直して、次のようにすることができます。

ModuleDefinition module = ModuleDefinition.ReadModule(fileName);

var entryPoint = module.EntryPoint.Body;

var corlib = module.TypeSystem.Corlib;

var exceptionTypeReference = new TypeReference(
    "System", "Exception", null, corlib, false);
exceptionTypeReference = module.Import(exceptionTypeReference);

var entryPointIL = entryPoint.GetILProcessor();

var objectTypeReference = new TypeReference(
    "System", "Object", null, corlib, false);
objectTypeReference = module.Import(objectTypeReference);

var writeLineMethod =
    new MethodReference(
        "WriteLine",
        new TypeReference("System", "Void", null, corlib, true),
        new TypeReference("System", "Console", null, corlib, false))
    { Parameters = { new ParameterDefinition(objectTypeReference) } };
writeLineMethod = module.Import(writeLineMethod);

var callWriteLine = entryPointIL.Create(OpCodes.Call, writeLineMethod);
entryPointIL.Append(callWriteLine);

entryPointIL.Emit(OpCodes.Br, entryPoint.Instructions.First());

var exceptionHandler = new ExceptionHandler(ExceptionHandlerType.Catch)
                        {
                            CatchType = exceptionTypeReference,
                            TryStart = entryPoint.Instructions.First(),
                            TryEnd = callWriteLine,
                            HandlerStart = callWriteLine,
                            HandlerEnd = entryPoint.Instructions.Last()
                        };
entryPoint.ExceptionHandlers.Add(exceptionHandler);

module.Write(fileName);

このコードが行うことは、アプリケーションのエントリ ポイント (通常はMain()メソッド) を取得して、次のように書き直すことです。

static void Main()
{
    // some code
}

これに:

static void Main()
{
    while (true)
    {
        try
        {
            // some code
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
    }
}

編集:

メソッドと包含クラスが public である場合Main()、より簡単な方法があります。もう一方を参照として持つアプリケーションを作成し、そのMain(). このようなもの:

class Program
{
    void Main()
    {
        while (true)
        {
            try
            {
                OtherApplication.Program.Main();
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }
    }
}
于 2011-11-03T14:16:36.550 に答える