Архив за день: 24.09.2021



WPF: Запускать только один экземпляр приложения

Ранее я уже писал заметку «WPF: Запускать только одну копию приложения«. Было это, как оказалось, довольно «давно». Хоть и прошло всего полтора года, а часть ссылок уже недоступна и некоторые пункты контекстного меню изменились. Попробуем сделать аналогичное приложение немного другим способом.

Подключение пакета SingleInstanceCore

0. У нас уже должен быть открыт пустой проект WPF и здесь я не расписываю пошагово, как именно его нужно создавать.
1. Для начала нам нужно добавить в проект пакет «SingleInstanceCore» (этот пакет из состава NuGet, поэтому на этот раз нам пригодится пункт главного меню Visual Studio Community: NuGet Package Manager).

Хотя, данный пакет можно поставить и через NuGet Package Manager Console

Install-Package SingleInstanceCore -Version 2.2.0

 

2. Убедимся, что пакет был добавлен в проект, для чего раскроем дерево проекта на пункте DependenciesPackages:

3. Если приложение вызывается с аргументами, то мы их должны обрабатывать при каждом вызове (файл App.xaml.cs):

  public partial class App : Application, ISingleInstance
  {
    public void OnInstanceInvoked(string[] args)
    {
      //Здесь обрабатываются аргументы, которые передали приложению
      // Например так:
      // https://docs.microsoft.com/ru-ru/dotnet/api/system.windows.application.startup?view=net-5.0
    }
    // Что-то ещё
}

Чтобы не было ошибок, нужно добавить в начало файла строку:

using SingleInstanceCore;

 

4. В тот же файл добавим строчки для инициализации данного экземпляра приложения:

    private void Application_Startup(object sender, StartupEventArgs e)
    {
      bool isFirstInstance = this.InitializeAsFirstInstance("soheilkd_ExampleIPC");
      if (!isFirstInstance)
      {
        //If it's not the first instance, arguments are automatically passed to the first instance
        //OnInstanceInvoked will be raised on the first instance
        //You may shut down the current instance
        Current.Shutdown();
      }
    }

5. Чуть ниже не забудем добавить метод для очистки памяти при выходе из приложения:

    private void Application_Exit(object sender, ExitEventArgs e)
    {
      //Do not forget to cleanup
      SingleInstance.Cleanup();
    }

6. Далее нам нужно обратить внимание на файл App.xaml, здесь свойство StartupUri замещается подпиской на событие Startup, т.о. полный код этого файла теперь будет такой:

<Application x:Class="SingleInstanceApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:SingleInstanceApp"
             Startup="Application_Startup">
    <Application.Resources>
         
    </Application.Resources>
</Application>
Мы просто заменили дефолтовую строчку StartupUri="MainWindow.xaml" на Startup="Application_Startup"

 

Теперь при запуске приложения будет произведена проверка и, если это приложение уже было запущено ранее, то новое окно не будет открыто (процесс будет убит).

В данном примере рассмотрен способ запуска только одного экземпляра приложения, но при этом здесь не реализован вывод окна на передний план или восстановление его из свёрнутого состояния! Из-за простоты данного пакета, тут нет возможности обратиться к основному процессу.