Как убедиться, что запущен один экземпляр приложения

Я хочу проверить, когда пользователь дважды щелкает значок приложения, что ни один другой экземпляр этого приложения уже не запущен.

Я читал о My.Application, но до сих пор не знаю, что делать.


person BDeveloper    schedule 24.12.2008    source источник
comment
Вероятно, вам следует указать язык, фреймворк и/или операционную систему.   -  person cletus    schedule 24.12.2008
comment
Я пометил это как VB.Net, так как My.Application — это функция VB.Net.   -  person Keith    schedule 24.12.2008
comment
Добавлен тег singleton, так как кажется, что это то, что требуется.   -  person Abizern    schedule 24.12.2008
comment
Синглтон управляет одним экземпляром класса в одном экземпляре приложения. Вам нужно что-то CLR/системное, например мьютекс   -  person lacop    schedule 24.12.2008


Ответы (11)


Наиболее распространенным шаблоном для этого является использование шаблона Singleton. Поскольку вы не указали язык, я предполагаю, что вы имеете в виду C # здесь - если нет, принципы остаются теми же в большинстве языков OO.

Эта статья должна помочь вам.

person Pete OHanlon    schedule 24.12.2008
comment
Техника, описанная в ссылке Пита, также отлично работает в VB.NET. Я уже давно делаю свое приложение синглтоном в своем списке дел, так что это очень полезно, поэтому +1. - person ChrisA; 24.12.2008
comment
Синглтон — это шаблон класса. Один экземпляр — это шаблон app. - person Mark Brackett; 24.12.2008
comment
ссылка на статью дед, этот ответ бесполезен - person whiteshooz; 02.12.2015

Это то, что я использовал... (С# в .NET 2.0)

    [STAThread]
    private static void Main(string[] args)
    {
        //this follows best practices on
        //ensuring that this is a single instance app.
        string mutexName = "e50cf829-f6b9-471e-8d9f-67eac3699f09";
        bool grantedOwnership;
        //we prefix the mutexName with "Local\\" to allow this to run under terminal services.
        //The "Local\\" prefix forces this into local user space.
        //If we want to forbid this in TS, use the "Global\\" prefix.
        Mutex singleInstanceMutex = new Mutex(true, "Global\\" + mutexName, out grantedOwnership);
        try
        {
            if (!grantedOwnership)
            {
                MessageBox.Show("Error: X is already running.\n\nYou can only run one copy of X at a time.", "X", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                Application.Exit();
            }
            else
            {
                Application.Run(new X(args));
            }
        }
        finally
        {
            singleInstanceMutex.Close();
        }
    }
person Jon Dewees    schedule 24.12.2008
comment
спасибо, сэр, это было то, что я искал ... я также использовал мьютекс ... но, пожалуйста, скажите мне, что мне нужно вызвать в нем сторонний exe ... так что вы знаете, что он всегда предоставляется с определенным путем, например: - D:\\Documents and Settings\\Администратор\\Рабочий стол\\Драйверы\\имя файла\\имя файла\\bin\\Debug\\имя файла.exe, так как я могу сосредоточиться на этом всякий раз, когда я снова нажимаю кнопку .. - person zoya; 04.02.2010

В VB .NET есть IsSingleInstance. логическое свойство, которое делает всю работу за вас.

В VB (взято из здесь):

Public Class Program
        Inherits Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase

       Public Sub New()
            Me.IsSingleInstance = True
        End Sub



End Class

Вот как вы используете его в C# (взято из здесь ):

// SingleInstanceApplication.cs
class SingleInstanceApplication : WindowsFormsApplicationBase {

 // Must call base constructor to ensure correct initial 
 // WindowsFormsApplicationBase configuration
 public SingleInstanceApplication() {

  // This ensures the underlying single-SDI framework is employed, 
  // and OnStartupNextInstance is fired
  this.IsSingleInstance = true;
 }
}


// Program.cs
static class Program {
 [STAThread]
 static void Main(string[] args) {
  Application.EnableVisualStyles();
  SingleInstanceApplication application = 
   new SingleInstanceApplication();
  application.Run(args);
 }
}

Убедитесь, что в вашем проекте есть ссылка на Microsoft.VisualBasic.dll.

person Yuval Peled    schedule 24.12.2008
comment
Влияет ли это на работу с обычным классом Application, например, на установку Application.ThreadException и т. д.? Возможно, мьютекс — лучший способ, поскольку вам не нужно изменять архитектуру вашего приложения? - person Rory; 23.01.2009
comment
(Комментарий выше относится к С#) - person Rory; 23.01.2009
comment
Он по-прежнему использует тот же базовый материал цикла сообщений, это просто оболочка вокруг его вызова, потому что он может запускать основную форму или может просто выйти после того, как подаст сигнал существующему приложению обработать аргументы из нового. Часть установочного кода может быть перенесена в события в оболочке, но в целом все равно будет работать так же, если вы найдете правильное место для его размещения. - person Rob Parker; 19.04.2010
comment
Он не работает в гостевой учетной записи Windows. Выдает UnauthorizedAccessException - person Jader Dias; 15.09.2010

Откройте свойства проекта (вкладка "Приложение") и установите флажок Создать приложение с одним экземпляром.

На вкладке Приложение также можно нажать кнопку Просмотр событий приложения, чтобы создать класс ApplicationEvents.vb, в котором можно обрабатывать второе событие экземпляра:

Partial Friend Class MyApplication
    Private Sub MyApplication_StartupNextInstance(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
        ' Bring First Instance to Foreground
        e.BringToForeground = True
        ' Pass Second Instance Command Line to First Instance
        AppShared.DoSomethingWithCommandLine(e.CommandLine)
    End Sub
End Class
person Gordon Bell    schedule 24.12.2008

У Скотта Хансельмана есть хорошая статья об этом. Код написан на C#, но я думаю, его будет легко перенести на VB.

http://www.hanselman.com/blog/TheWeeklySourceCode31SingleInstanceWinFormsAndMicrosoftVisualBasicdll.aspx

Вот еще одна статья на эту тему на случай, если она вам не подойдет:

http://www.codeproject.com/KB/cs/cssingprocess.aspx

person lacop    schedule 24.12.2008

В VB.NET приложение с одним экземпляром — это просто флажок на странице свойств проекта. . Вы также можете перехватить событие My.Application.StartupNextInstance, чтобы один экземпляр делает что-то, когда запускается другая копия. Это можно использовать, например, для MDI-поведения при открытии запрошенного документа в исходном экземпляре.

За кулисами это инкапсулирует немало мьютекса и IPC-слизи — см. WindowsFormApplicationBase — также может использоваться из C#.

person Mark Brackett    schedule 24.12.2008

С помощью приведенных выше советов я узнал, как сделать свое приложение единым экземпляром, но мне все равно пришлось перейти на другой сайт, чтобы ТОЧНО узнать, как это сделать. Вот простая картинка, как мне это удалось. Это было легко, и я надеюсь, что это поможет другим с такой же потребностью, потому что я уверен, что ОП решил эту проблему 7 лет назад: введите здесь описание изображения

person cardmagik    schedule 23.08.2015

Используйте 1_. По сути, Mutex можно назвать строкой, и он уникален в среде CLR.

Образец кода:

try
{
mutex = Mutex.OpenExisting(mutexName);
//since it hasn’t thrown an exception, then we already have one copy of the app open.
MessageBox.Show(”A copy of Todo 3.0 is already open. Please check your system tray (notification area).”,
“Todo 3.0″, MessageBoxButtons.OK, MessageBoxIcon.Information);
Environment.Exit(0);
}
catch (Exception Ex)
{
//since we didn’t find a mutex with that name, create one
Debug.WriteLine(”Exception thrown:” + Ex.Message + ” Creating a new mutex…”);
mutex = new Mutex(true, mutexName);
}

Из этого запись:

person biozinc    schedule 24.12.2008

Если ваше приложение находится в VB.NET 2.0-3.5, самый простой способ поддерживать работу одного экземпляра программы — использовать «Свойства среды приложений Windows». Чтобы попасть туда, щелкните правой кнопкой мыши имя вашего проекта и перейдите в «Свойства». Оказавшись там, установите флажок «Создать приложение с одним экземпляром».

Вы также можете использовать ApplicationEvents.vb, чтобы показать пользователю, что он запустил вашу программу во второй раз. Вы можете легко создать/просмотреть это в том же окне свойств, нажав кнопку «Просмотр событий приложения». Там вы можете выбрать подпрограмму MyApplication_StartupNextInstance и ввести туда код, например:

Private Sub MyApplication_StartupNextInstance(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
    MessageBox.Show("This program is already running.  If you do not see the program running, please check your " _
        & "Windows Task Manager for this program name in the 'Processes' Tab." & vbNewLine & vbNewLine & "WARNING: " _
        & " If you terminate the process, you will terminate the only instance of this program!", My.Application.Info.ProductName.ToString _
        & " is Running!", MessageBoxButtons.OK, MessageBoxIcon.Warning)

End Sub

Позвольте мне знать, если это помогает! JFV

person JFV    schedule 24.12.2008

Назначьте своему приложению какой-нибудь уникальный идентификатор, например жестко заданный guid, и создайте экземпляр Mutex, в котором вы назначаете мьютексу этот идентификатор. Если он выдает исключение, значит, ваше приложение уже запущено (поскольку ему удалось создать мьютекс)

person Sean    schedule 24.12.2008

Я подумал, что будет проще иметь образец прямо здесь, а не ссылку.

    [STAThread]
    static void Main()
    {
        if (!IsAppAlreadyRunning())
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1()); /* Change Form1 for your main Form */
        }
        else
        {
            MessageBox.Show("Application is already running!");
        }
    }

    public static bool IsAppAlreadyRunning()
    {
        Process currentProcess = Process.GetCurrentProcess();
        return (IsAppAlreadyRunning(currentProcess.Id, 
                                    currentProcess.ProcessName));
    }

    private static bool IsAppAlreadyRunning(int ID, string Name)
    {
        bool isAlreadyRunning = false;
        Process[] processes = Process.GetProcesses();
        foreach (Process process in processes)
        {
            if (ID != process.Id)
            {
                if (Name == process.ProcessName)
                {
                    isAlreadyRunning = true;
                    break;
                }
            }
        }
        return isAlreadyRunning;
    }
person Cédric Guillemette    schedule 24.12.2008
comment
Я предполагаю, что проблема в том, что если кто-то переименует .exe, у него могут быть запущены два экземпляра. - person Rory; 23.01.2009
comment
Более сложная часть состоит в том, чтобы существующее приложение делало что-то полезное при выполнении команды, например, выдвигало себя на передний план (и, при необходимости, уменьшало минимизацию) или открывало указанный документ в существующем приложении. Если в таком поведении нет необходимости, вам может подойти простая уже запущенная проверка, подобная этой. - person Rob Parker; 19.04.2010