Impedir várias instâncias de um determinado aplicativo no .NET?

No .NET, qual é a melhor maneira de impedir que várias instâncias de um aplicativo sejam executadas ao mesmo tempo? E se não houver uma técnica “melhor”, quais são algumas das advertências a serem consideradas em cada solução?

   

Use Mutex. Um dos exemplos acima usando GetProcessByName tem muitas ressalvas. Aqui está um bom artigo sobre o assunto:

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"; 
 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; } 

Aqui está o código que você precisa para garantir que apenas uma instância esteja em execução. Este é o método de usar um mutex nomeado.

 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(); } } } 

Hanselman tem uma postagem sobre como usar a class WinFormsApplicationBase do assembly Microsoft.VisualBasic para fazer isso.

Parece que existem 3 técnicas fundamentais que foram sugeridas até agora.

  1. Derive da class Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase e defina a propriedade IsSingleInstance como true. (Eu acredito que uma ressalva aqui é que isso não funcionará com aplicativos WPF, será?)
  2. Use um mutex nomeado e verifique se ele já foi criado.
  3. Obtenha uma lista de processos em execução e compare os nomes dos processos. (Isso tem a condição de exigir que o nome do seu processo seja exclusivo em relação a qualquer outro processo em execução na máquina de um determinado usuário.)

Alguma advertência que eu perdi?

Eu tentei todas as soluções aqui e nada funcionou no meu projeto c # .net 4.0. Esperando ajudar alguém aqui a solução que funcionou para mim:

Como principais variables ​​de class:

 private static string appGuid = "WRITE AN UNIQUE GUID HERE"; private static Mutex mutex; 

Quando você precisa verificar se o aplicativo já está em execução:

 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 } 

Eu precisava fechar outras istâncias apenas com algumas condições, isso funcionou bem para o meu propósito

Usando o Visual Studio 2005 ou 2008 quando você cria um projeto para um executável, nas janelas de propriedades dentro do painel “Aplicativo” há uma checkbox de seleção chamada “Criar aplicativo de instância única” que você pode ativar para converter o aplicativo em um único aplicativo de instância. .

Aqui está uma captura da janela da qual estou falando: insira a descrição da imagem aqui Este é um projeto de aplicativo de janelas do Visual Studio 2008.

Este artigo explica simplesmente como você pode criar um aplicativo do Windows com controle sobre o número de suas instâncias ou executar apenas uma única instância. Essa é uma necessidade muito típica de um aplicativo de negócios. Já existem muitas outras soluções possíveis para controlar isso.

http://www.openwinforms.com/single_instance_application.html

Use VB.NET! Não mesmo 😉

using Microsoft.VisualBasic.ApplicationServices;

O WindowsFormsApplicationBase de VB.Net fornece uma propriedade “SingleInstace”, que determina outras instâncias e permite que apenas uma instância seja executada.

Você tem que usar System.Diagnostics.Process.

Confira: http://www.devx.com/tips/Tip/20044

Este é o código para o 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 

Este é o código para c #

 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()); } } 

(Nota: esta é uma solução divertida! Funciona, mas usa um design GDI + ruim para conseguir isso.)

Coloque uma imagem no seu aplicativo e carregue-a na boot. Segure até o aplicativo sair. O usuário não poderá iniciar uma segunda instância. (Claro que a solução mutex é muito mais limpa)

 private static Bitmap randomName = new Bitmap("my_image.jpg"); 

Depois de tentar várias soluções é a pergunta. Acabei usando o exemplo para o WPF aqui: 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(); } } } 

Em App.xaml:

 x:Class="*YourNameSpace*.App" StartupUri="MainWindow.xaml" Startup="App_Startup" 

1 – Crie uma referência em program.cs ->

 using System.Diagnostics; 

2 – Coloque em void Main() como a primeira linha de código ->

  if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1) return; 

É isso aí.

Simplesmente usando um StreamWriter , que tal isso?

 System.IO.File.StreamWriter OpenFlag = null; //globally 

e

 try { OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning"); } catch (System.IO.IOException) //file in use { Environment.Exit(0); } 

Normalmente, ele é feito com um Mutex nomeado (use o novo Mutex (“nome do seu aplicativo”, true) e verifique o valor de retorno), mas há também algumas classs de suporte no Microsoft.VisualBasic.dll que podem fazer isso por você .

Isso funcionou para mim em C # puro. o try / catch é quando possivelmente um processo na lista sai durante o seu loop.

 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()); } 
 [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! } 

De: Garantindo uma única instância do aplicativo .NET

e: Mutex de aplicativo de instância única

A mesma resposta de @Smink e @Imjustpondering com um toque:

Perguntas frequentes de Jon Skeet sobre C # para descobrir por que o GC.KeepAlive é importante

Certifique-se de considerar a segurança ao restringir um aplicativo a uma única instância:

Artigo completo: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813

Estamos usando um mutex nomeado com um nome fixo para detectar se outra cópia do programa está sendo executada. Mas isso também significa que um atacante pode criar o mutex primeiro, evitando assim que o nosso programa seja executado. Como posso evitar esse tipo de ataque de negação de serviço?

Se o invasor estiver executando no mesmo contexto de segurança do seu programa (ou estaria) sendo executado, não há nada que você possa fazer. Seja qual for o “handshake secreto” que você tenha para determinar se outra cópia do seu programa está sendo executada, o invasor pode imitá-lo. Como está sendo executado no contexto de segurança correto, ele pode fazer qualquer coisa que o programa “real” possa fazer.

É claro que você não pode se proteger de um invasor que esteja executando o mesmo privilégio de segurança, mas ainda pode se proteger contra invasores sem privilégios que estejam executando outros privilégios de segurança.

Tente definir uma DACL no seu mutex, aqui está a maneira .NET: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx