В .NET, какой лучший способ предотвратить одновременное запуск нескольких экземпляров приложения? И если нет "лучшей" техники, каковы некоторые из предостережений, которые следует учитывать при каждом решении?
Предотвратить несколько экземпляров данного приложения в .NET?
Ответ 1
Использовать Mutex. Один из приведенных выше примеров с использованием GetProcessByName имеет много предостережений. Вот хорошая статья по теме:
http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
[STAThread]
static void Main()
{
using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
Application.Run(new Form1());
}
}
private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
Ответ 2
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
AppLog.Write("Application XXXX already running. Only one instance of this application is allowed", AppLog.LogMessageType.Warn);
return;
}
Ответ 3
Вот код, необходимый для обеспечения работы только одного экземпляра. Это метод использования именованного мьютекса.
public class Program
{
static System.Threading.Mutex singleton = new Mutex(true, "My App Name");
static void Main(string[] args)
{
if (!singleton.WaitOne(TimeSpan.Zero, true))
{
//there is already another instance running!
Application.Exit();
}
}
}
Ответ 4
У Hanselman сообщение об использовании класса WinFormsApplicationBase из сборки Microsoft.VisualBasic для этого.
Ответ 5
Похоже, есть 3 фундаментальных метода, которые были предложены до сих пор.
- Выведите из класса Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase и установите для свойства IsSingleInstance значение true. (Я считаю, что здесь предостережение заключается в том, что это не будет работать с приложениями WPF, не так ли?)
- Использовать именованный мьютекс и проверить, было ли оно уже создано.
- Получить список запущенных процессов и сравнить имена процессов. (В этом есть предостережение о том, что ваше имя процесса уникально относительно любых других процессов, запущенных на данной пользовательской машине.)
Любые оговорки, которые я пропустил?
Ответ 6
Я попробовал все решения здесь, и ничего не работало в моем проекте С#.net 4.0. Надеясь помочь кому-то в этом решении, которое сработало для меня:
В качестве основных переменных класса:
private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;
Когда вам нужно проверить, запущено ли приложение:
bool mutexCreated;
mutex = new Mutex(true, "Global\\" + appGuid, out mutexCreated);
if (mutexCreated)
mutex.ReleaseMutex();
if (!mutexCreated)
{
//App is already running, close this!
Environment.Exit(0); //i used this because its a console app
}
Мне нужно было закрыть другие события только с некоторыми условиями, это хорошо сработало для моей цели
Ответ 7
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0 -Single-Instance_Detection_and_Management
Ответ 8
Используя Visual Studio 2005 или 2008 при создании проекта для исполняемого файла, в окнах свойств внутри панели "Приложение" имеется флажок "Сделать одно экземплярное приложение", который вы можете активировать, чтобы преобразовать приложение на одно экземплярное приложение.
Вот захват окна, о котором я говорю: Это проект приложения Windows Visual Studio 2008.
Ответ 9
В этой статье просто объясняется, как вы можете создать приложение Windows с контролем над количеством его экземпляров или запустить только один экземпляр. Это очень типичная потребность в бизнес-приложении. Уже существует множество других возможных решений для контроля этого.
http://www.openwinforms.com/single_instance_application.html
Ответ 10
Использовать VB.NET! Нет: действительно;)
с использованием Microsoft.VisualBasic.ApplicationServices;
WindowsFormsApplicationBase из VB.Net предоставляет вам свойство SingleInstace, которое определяет другие экземпляры и позволяет запускать только один экземпляр.
Ответ 11
http://www.codeproject.com/KB/cs/SingleInstancingWithIpc.aspx
Ответ 12
Вам нужно использовать System.Diagnostics.Process.
Ответ 13
Это код для VB.Net
Private Shared Sub Main()
Using mutex As New Mutex(False, appGuid)
If Not mutex.WaitOne(0, False) Then
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Application.Run(New Form1())
End Using
End Sub
Это код для С#
private static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid)) {
if (!mutex.WaitOne(0, false)) {
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Application.Run(new Form1());
}
}
Ответ 14
(Примечание: это веселое решение! Оно работает, но для достижения этого используется плохой дизайн GDI +.)
Поместите изображение в приложение и загрузите его при запуске. Удерживайте его, пока приложение не выйдет. Пользователь не сможет запустить второй экземпляр. (Конечно, решение мьютекса намного чище)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Ответ 15
После нескольких попыток решения. В итоге я использовал пример WPF: http://www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one-instance/
public partial class App : Application
{
private static Mutex _mutex = null;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "MyAppName";
bool createdNew;
_mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
//app is already running! Exiting the application
Application.Current.Shutdown();
}
}
}
В App.xaml:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Ответ 16
1 - Создайте ссылку в program.cs →
using System.Diagnostics;
2 - Поместите в void Main()
в качестве первой строки кода →
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
Что это.
Ответ 17
Просто используя StreamWriter
, как насчет этого?
System.IO.File.StreamWriter OpenFlag = null; //globally
и
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
Ответ 18
Обычно это выполняется с помощью имени Mutex (используйте новый Mutex ( "ваше имя приложения", "истина" ) и проверьте возвращаемое значение), но также есть классы поддержки в Microsoft.VisualBasic.dll, которые может сделать это для вас.
Ответ 19
[STAThread]
static void Main() // args are OK here, of course
{
bool ok;
m = new System.Threading.Mutex(true, "YourNameHere", out ok);
if (! ok)
{
MessageBox.Show("Another instance is already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
GC.KeepAlive(m); // important!
}
От: Обеспечение единого экземпляра приложения .NET
и: Мьютекс приложения с одним экземпляром
Тот же ответ, что и @Smink и @Imjustpondering с завихрением:
Jon Skeet FAQ на С#, чтобы узнать, почему GC.KeepAlive имеет значение
Ответ 20
Это работало для меня в чистом С#. try/catch - когда возможно, что процесс в списке завершается во время вашего цикла.
using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
int procCount = 0;
foreach (Process pp in Process.GetProcesses())
{
try
{
if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
{
procCount++;
if(procCount > 1) {
Application.Exit();
return;
}
}
}
catch { }
}
Application.Run(new Form1());
}
Ответ 21
Обязательно рассмотрите безопасность при ограничении приложения на один экземпляр:
Полная статья: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
Мы используем именованный мьютекс с фиксированным именем для обнаружения выполняется ли другая копия программы. Но это также означает злоумышленник может сначала создать мьютекс, тем самым предотвращая нашу программу от бега на всех! Как я могу предотвратить этот тип отказа в обслуживании атака?
...
Если злоумышленник работает в том же контексте безопасности, что и ваш программа (или будет) запущена, тогда вы ничего не сможете сделать. Какое бы "секретное рукопожатие" вы придумали, чтобы определить, другая копия вашей программы запущена, злоумышленник может имитировать ее. Поскольку он работает в правильном контексте безопасности, он может все, что может сделать "настоящая" программа.
...
Очевидно, что вы не можете защитить себя от злоумышленника, работающего на такая же привилегия безопасности, но вы все равно можете защитить себя от непривилегированные злоумышленники, выполняющие другие привилегии безопасности.
Попробуйте установить DACL на ваш мьютекс, здесь путь .NET: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx