it-swarm-tr.com

.NET'te belirli bir uygulamanın birden fazla örneğini engelle?

.NET'te, bir uygulamanın birden fazla örneğinin aynı anda çalışmasını önlemenin en iyi yolu nedir? Ve eğer "en iyi" bir teknik yoksa, her bir çözümde dikkate alınması gereken bazı uyarılar nelerdir?

114
C. Dragon 76

Mutex kullanın. GetProcessByName kullanarak yukarıdaki örneklerden biri birçok uyarıları vardır. İşte konuyla ilgili iyi bir makale:

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";
139
ImJustPondering
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;
}
17
Thomas Wagner

İşte sadece bir örneğin çalıştığından emin olmanız için gereken kod. Bu, adlandırılmış bir muteks kullanma yöntemidir. 

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

Hanselman, bunu yapmak için Microsoft.VisualBasic Assembly'den WinFormsApplicationBase sınıfını kullanarak post kullanıyor.

7
bdukes

Şimdiye kadar önerilen 3 temel teknik var gibi gözüküyor.

  1. Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase sınıfından türetin ve IsSingleInstance özelliğini true değerine ayarlayın. (Burada bir uyarının bunun WPF uygulamalarıyla çalışmayacağına inanıyorum, değil mi?)
  2. Adlandırılmış bir muteks kullanın ve daha önce oluşturulup oluşturulmadığını kontrol edin.
  3. Çalışan işlemlerin bir listesini alın ve işlemlerin adlarını karşılaştırın. (Bu, işlem adınızın, belirli bir kullanıcının makinesinde çalışan diğer işlemlere göre benzersiz olmasını gerektirme uyarısı vardır.)

Kaçırdığım herhangi bir uyarı var mı?

5
C. Dragon 76

Yürütülebilir bir proje oluştururken Visual Studio 2005 veya 2008'i kullanarak, "Uygulama" panelindeki özellikler pencerelerinde, uygulamayı tek bir örnek uygulamada dönüştürmek için etkinleştirebileceğiniz "Tek örnek uygulama yap" adlı bir onay kutusu vardır. .

İşte bahsettiğim pencerenin bir görüntüsü: enter image description here Bu bir Visual Studio 2008 windows uygulama projesidir.

4
Doliveras

burada tüm çözümleri denedim ve hiçbir şey C # .net 4.0 projemde işe yaramadı. Benim için işe yarayan çözümü burada birine yardım etmeyi umarak:

Ana sınıf değişkenleri olarak:

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

Uygulamanın zaten çalışıp çalışmadığını kontrol etmeniz gerektiğinde:

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
}

Diğer durumları sadece bazı koşullarla kapatmam gerekiyordu, bu benim amacım için işe yaradı.

4
HypeZ
3
Aaron Jensen

Bu makale, örneklerin sayısını denetleyen veya yalnızca tek bir örneği çalıştırabilen bir Windows uygulamasını nasıl oluşturabileceğinizi açıklar. Bu, bir iş uygulamasına çok tipik bir ihtiyaçtır. Bunu kontrol etmek için zaten birçok olası çözüm var. 

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

2
Jorge Ferreira

1 - program.cs içinde bir referans oluşturun -> 

using System.Diagnostics;

2 - Kodun ilk satırı olarak void Main() komutunu girin ->

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

Bu kadar.

2
user5289350

VB.NET kullanın! No: really;)

microsoft.VisualBasic.ApplicationServices kullanarak;

VB.Net'ten WindowsFormsApplicationBase, diğer Örnekleri belirleyen ve yalnızca bir Örneği çalıştırabilen bir "SingleInstace" Özelliği sağlar.

2
MADMap
1
tim_yates

Bu VB.Net'in kodu

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

Bu C # kodudur

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

System.Diagnostics.Process kullanmanız gerekir.

Çıkış: http://www.devx.com/tips/Tip/20044

1
Thomas Jespersen

(Not: bu eğlenceli bir çözüm! Çalışıyor ancak bunu başarmak için kötü GDI + tasarımını kullanıyor.)

Uygulamanıza bir resim yerleştirin ve başlangıçta yükleyin. Uygulama çıkana kadar basılı tutun. Kullanıcı 2. bir örneği başlatamaz. (Elbette mutex çözümü daha temizdir)

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

Birden fazla çözüm denedikten sonra ben soru. Burada WPF örneğini kullanarak sona erdi: http://www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one örnek/

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'de:

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

Basitçe bir StreamWriter kullanarak, buna ne dersiniz?

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

ve

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

Normalde adlandırılmış bir Mutex ile yapılır (yeni Mutex kullanın ("uygulama adınız", doğru) ve dönüş değerini kontrol edin), ancak Microsoft.VisualBasic.dll dosyasında sizin için yapabileceğiniz bazı destek sınıfları da vardır .

0
Tomer Gabel

Bu benim için saf C # ile çalıştı. try/catch, döngüdeki muhtemelen listedeki bir işlemden çıktığında gerçekleşir.

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

Kimden: Tek bir .NET Uygulaması örneği sağlama

ve: Tek Örnek Uygulama Mutex

@Smink ve @Imjustpondering'in bir twist ile aynı cevabı:

Jon Skeet'in FAQ C # 'da nedenini bulmak için GC.KeepAlive matters

0
Ric Tokyo

Bir uygulamayı tek bir örnekle kısıtlarken güvenliği göz önünde bulundurduğunuzdan emin olun:

Tam makale: https://blogs.msdn.Microsoft.com/oldnewthing/20060620-13/?p=30813

Tespit etmek için sabit bir isimle adlandırılmış bir muteks kullanıyoruz. Programın başka bir kopyası çalışıp çalışmadığını. Ama bu aynı zamanda bir .__ demektir. saldırgan önce muteks oluşturabilir ve böylece programımızı engelleyebilir. hiç kaçmadan! Bu tür hizmet reddine neden nasıl önleyebilirim? Saldırı?

...

Saldırgan, sizinki ile aynı güvenlik bağlamında çalışıyorsa. program çalışıyor (veya olabilir), sonra yapabileceğiniz hiçbir şey yok . Hangi "gizli el sıkışma" olursa olsun ortaya çıkıp çıkmadığına karar verin. programınızın başka bir kopyası çalışıyor, saldırgan taklit edebilir . Doğru güvenlik bağlamında çalıştığı için, yapabilir. “gerçek” programın yapabileceği herhangi bir şey.

...

Belli ki kendini M .__ 'da çalışan bir saldırgandan koruyamazsın. Aynı güvenlik ayrıcalığına sahip olsanız da, kendinizi hala diğer güvenlik ayrıcalıklarında çalışan ayrıcalıklı saldırganlar.

Muteksinize bir DACL ayarlamayı deneyin, işte .NET yolu: https://msdn.Microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110). aspx

0
Aardvark

Bu cevapların hiçbiri benim için işe yaramadı, çünkü bu monodevelop kullanarak Linux altında çalışmak için gerekli. Bu benim için harika çalışıyor:

Bu yöntemi benzersiz bir kimlik numarası vererek çağırın

    public static void PreventMultipleInstance(string applicationId)
    {
        // Under Windows this is:
        //      C:\Users\SomeUser\AppData\Local\Temp\ 
        // Linux this is:
        //      /tmp/
        var temporaryDirectory = Path.GetTempPath();

        // Application ID (Make sure this guid is different accross your different applications!
        var applicationGuid = applicationId + ".process-lock";

        // file that will serve as our lock
        var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);

        try
        {
            // Prevents other processes from reading from or writing to this file
            var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
            _InstanceLock.Lock(0, 0);
            MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);

            // todo investigate why we need a reference to file stream. Without this GC releases the lock!
            System.Timers.Timer t = new System.Timers.Timer()
            {
                Interval = 500000,
                Enabled = true,
            };
            t.Elapsed += (a, b) =>
            {
                try
                {
                    _InstanceLock.Lock(0, 0);
                }
                catch
                {
                    MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
                }
            };
            t.Start();

        }
        catch
        {
            // Terminate application because another instance with this ID is running
            Environment.Exit(102534); 
        }
    }         
0
Tono Nam