Перезапуск приложения конфликтует с ошибкой «программа уже запущена» - PullRequest
0 голосов
/ 30 октября 2009

Когда я вызываю метод Application.Restart (), появляется ошибка, которая определяет, запущено ли приложение в данный момент. Есть ли что-нибудь вокруг этого?

    static void Main(string[] args)
    {
        string proc = Process.GetCurrentProcess().ProcessName;
        Process[] processes = Process.GetProcessesByName(proc);
        if (processes.Length > 1)
        {
            MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

Ответы [ 5 ]

3 голосов
/ 30 октября 2009

Используйте мьютекс. например: Приложение для одного экземпляра, которое минимизируется в системный трей при закрытии . Этот пример более сложный, чем вам, вероятно, нужно, но базовая концепция использования Mutex для одного экземпляра работает хорошо.

1 голос
/ 09 апреля 2011

У меня была похожая проблема, но моя была связана с неуправляемой утечкой памяти, которую я не смог найти в приложении, которое должно работать 24/7. С клиентом я согласился, что безопасное время для перезапуска приложения было 3:00 утра, если потребление памяти превышало определенное значение.

Я пытался Application.Restart, но, поскольку он, похоже, использует какой-то механизм, который запускает новый экземпляр, когда он уже запущен, я выбрал другую схему. Я использовал прием, который обрабатывает файловая система, до тех пор, пока процесс, который их создал, не прекратит работу. Итак, из приложения я сбросил файл на диск, а не Dispose() дескриптор. Я использовал этот файл для отправки исполняемого и начального каталога «себя» (для большей гибкости).

Код:

_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
    FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
    WorkingDirectory = Application.StartupPath,
    Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();

Close() в конце может привести к закрытию приложения, и дескриптор файла, который я использовал для StreamWriter, будет оставаться открытым до тех пор, пока процесс не прекратится. Тогда ...

Restarter.exe вступает в действие. Он пытается прочитать файл в монопольном режиме, не давая ему получить доступ до тех пор, пока основное приложение не исчезнет, ​​затем запускает основное приложение, удаляет файл и существует. Я думаю, что это не может быть проще:

static void Main(string[] args)
{
    string filename = args[0];
    DateTime start = DateTime.Now;
    bool done = false;
    while ((DateTime.Now - start).TotalSeconds < 30 && !done)
    {
        try
        {
            StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
            string[] runData = new string[2];
            runData[0] = sr.ReadLine();
            runData[1] = sr.ReadLine();
            Thread.Sleep(1000);
            Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
            sr.Dispose();
            File.Delete(filename);
            done = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Thread.Sleep(1000);
    }
}
1 голос
/ 30 октября 2009

Самый эффективный способ сделать это - наследовать от WindowsFormsApplicationBase класса VB.Net, который также можно использовать в C #, и установить для свойства IsSingleInstance true. При этом используется мьютекс, и он продолжит работать, если файл EXE будет переименован.

0 голосов
/ 30 октября 2009

Попробуйте подключить код перезапуска к событию Application.ApplicationExit как метод прослушивателя. Затем вы вызовете Application.Exit, чтобы код выполнялся косвенно.

Редактировать : Добавлен пример кода:

Например, когда пользователь нажимает кнопку перезагрузки или приложение решает перезагрузить, вызовите этот метод RestartMeSmartly (). Вам не придется беспокоиться об обмане - он сработает.

void RestartMeSmartly() {
    Application.ApplicationExit += BeforeExiting;
    Application.Exit();
}

void BeforeExiting(object sender, EventArgs args) {
    Application.Restart();
}
0 голосов
/ 30 октября 2009

Самый простой способ сделать это - добавить задержку перед выходом.

Другими словами,

string proc = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(proc).Length > 1) {
    Thread.Sleep(500);      //500 milliseconds; you might need to wait longer
    if (Process.GetProcessesByName(proc).Length > 1) {
        MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
}    //no else
...