Handeling application crashes in a bat-file
-
20-02-2021 - |
Question
I have a application (.NET console app) written in C# that I run on a server. From time to time (about 2 times a week) the application crashes, this might for instance be caused by the network going down or something like that, but that's not important, what I want however, is that when the application crash I want it to simply silently restart. I can't rewrite the application to do this as I don't have the source, and I would like a simple solution to this, so I tried to create a bat file like this:
:start
@BotR.TestR.exe
echo sleeping
@ping 123.45.67.89 -n 1 -w %1000 > nul
goto start
However, whenever the application (BotR.TestR.exe) crashes, it pops up with a popup-window telling that the application crashed, witch stops it from continuing and thus stops it from restarting. Is there any simple way I can solve this?
Solution
I'm not sure this is the best way, but you can rewrite the application using Mono Cecil to do what you want like this:
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);
What this code does is to take the entry point of the application (usually the Main()
method) and rewrite it from this:
static void Main()
{
// some code
}
into this:
static void Main()
{
while (true)
{
try
{
// some code
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
EDIT:
If the Main()
method and the contain class are public, there is an easier way: create an application that has the other one as a reference and runs its Main()
. Something like this:
class Program
{
void Main()
{
while (true)
{
try
{
OtherApplication.Program.Main();
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
}