Необходимо запретить доступ к определенной функции во время установки обновления - PullRequest
0 голосов
/ 01 февраля 2012

Наш продукт позволяет устанавливать обновления через установщик MSI. Обновление состоит из нескольких файлов, которые необходимо скопировать на диск, и добавления записей базы данных, которые установщик добавляет, запустив несколько сценариев SQL.

Обновления могут быть (и обычно) устанавливаются, когда основной исполняемый файл открыт. В связи с этим мне нужен способ предотвращения доступа к определенной функции, требующей интенсивного использования базы данных, в процессе обновления.

Мои нынешние мысли:

  1. Установщик добавляет ключ реестра при запуске.
  2. Обновление установлено.
  3. В случае успеха или неудачи ключ реестра удаляется.

Тем временем приложение (написанное на C #) запрашивает наличие раздела реестра, отображая диалоговое окно с сообщением об ошибке, если оно установлено.

Это надежно? Я обеспокоен тем, что произойдет, если пользователь убьет установщик через диспетчер задач, тогда ключ реестра никогда не будет удален, и пользователь будет навсегда заблокирован из функции. Также не уверен насчет условий гонки, к которым может привести приведенное выше решение.

Какие-либо предложения о том, возможен ли этот подход или лучше?

Ответы [ 3 ]

2 голосов
/ 01 февраля 2012

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

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

_MSIExecute Mutex


Обновление от @ LeopardSkinPillBoxHat

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

    static void Main(string[] args)
    {
        try
        {
            Mutex mutex = Mutex.OpenExisting(@"Global\_MSIExecute");
            if (!mutex.WaitOne(TimeSpan.FromSeconds(5), false))
            {
                Console.WriteLine("Installation in progress!");
                return;
            }
        }
        catch (AbandonedMutexException)
        {
            Console.WriteLine("Mutex was abandoned");
        }
        catch (WaitHandleCannotBeOpenedException)
        {
            Console.WriteLine("MSI installer not running");
        }

        // Perform operation here
    }
2 голосов
/ 01 февраля 2012

Было бы целесообразно использовать имя Mutex здесь? Требовать, чтобы интенсивные задачи и средство обновления сначала получили мьютекс перед выполнением.

РЕДАКТИРОВАТЬ: Я лгал насчет обертывания мьютекса в using, чтобы защитить вас от выключения диспетчера задач. Имеет смысл, вы не ожидаете, что блоки finally также будут выполняться. В итоге вы получите AbandonedMutex, который обсуждается в статье MSDN, на которую я ссылаюсь.

Также недавно увидел полезную небольшую статью об использовании Mutex для предотвращения выполнения нескольких экземпляров одной и той же программы.

1 голос
/ 01 февраля 2012
ALTER DATABASE <name> SINGLE_USER

Как описано здесь разорвет все остальные соединения и позволит вам продолжить обновление.

...