Isso nem sempre funciona (depende de como o programa é carregado), mas normalmente você pode criar um arquivo em lote 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 que ele seja iniciado novamente.
A linha
echo Program terminated at %Date% %Time% with Error %ErrorLevel% >> c:\logs\program.log
não é necessário, mas registra toda vez que o programa é fechado em um arquivo, então pode ser útil diagnosticar o problema. O ErrorLevel pode não dizer muito, mas um programa deve retornar 0 se ele for fechado normalmente, e uma mensagem diferente de zero se não for
Note que você menciona que seu programa não faz nada se já estiver rodando. Isso geralmente significa que o aplicativo é iniciado, detecta que outra cópia já está em execução e é encerrada imediatamente. Se esse for o caso, e seu programa estiver em execução antes de iniciar esse arquivo em lote, o lote fará um loop e tentará iniciar seu programa a cada dez segundos.