Isso nem sempre funciona (depende da forma como o programa se carrega), mas normalmente você pode criar um arquivo em lotes como este:
@Echo off
:Start
NotePad
echo Program terminated at %Date% %Time% with Error %ErrorLevel% >> c:\logs\program.log
echo Press Ctrl-C if you don't want to restart automatically
ping -n 10 localhost
goto Start
Eu usei o bloco de notas como um exemplo.
As linhas
echo Press Ctrl-C if you don't want to restart automatically
ping -n 10 localhost
são apenas um atraso (de 10 segundos) para dar ao usuário a chance de interromper o processo antes de iniciar novamente.
A linha
echo Program terminated at %Date% %Time% with Error %ErrorLevel% >> c:\logs\program.log
não é necessário, mas seria registrado cada vez que o programa era fechado em um arquivo, portanto, pode ser útil diagnosticar o problema. O ErrorLevel pode não lhe dizer muito, mas um programa deve retornar 0 se for fechado normalmente e não mensagem zero se isso não acontecer
Observe que você mencionou que seu programa não faz nada se já estiver em execução. Isso geralmente significa que o aplicativo inicia, detecta que outra cópia já está em execução e é encerrada imediatamente. Se for esse o caso, e seu programa estiver em execução antes de iniciar esse arquivo em lotes, o lote fará um loop e tentará iniciar o programa a cada dez segundos.