it-swarm-eu.dev

Zabránit více instancí řešení aplikace v .NET?

V .NET, jaký je nejlepší způsob, jak zabránit tomu, aby několik instancí aplikace fungovalo současně? A pokud neexistuje "nejlepší" technika, jaké jsou některé z úvah, které je třeba zvážit s každým řešením?

114
C. Dragon 76

Použijte Mutex. Jeden z výše uvedených příkladů pomocí GetProcessByName má mnoho výhrad. Zde je dobrý článek na toto téma:

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

Zde je kód, který potřebujete zajistit, aby byla spuštěna pouze jedna instance. Toto je metoda použití pojmenovaného mutexu. 

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 má post na použití třídy WinFormsApplicationBase od Microsoft.VisualBasic shromáždění k tomu.

7
bdukes

Zní to, jako by byly doposud navrženy 3 základní techniky.

  1. Odvozte se z třídy Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase a nastavte vlastnost IsSingleInstance na hodnotu true. (Domnívám se, že je třeba upozornit, že to nebude fungovat s aplikacemi WPF, že?)
  2. Použijte pojmenovaný mutex a zkontrolujte, zda již byl vytvořen.
  3. Získejte seznam běžících procesů a porovnejte názvy procesů. (To má za následek požadavek, aby byl název vašeho procesu jedinečný ve vztahu k jiným procesům běžícím na počítači daného uživatele.)

Jakékoliv varování, které jsem zmeškal?

5
C. Dragon 76

Pomocí aplikace Visual Studio 2005 nebo 2008 při vytváření projektu pro spustitelný soubor je v oknech s vlastnostmi v panelu "Aplikace" zaškrtnuto políčko "Vytvořit aplikaci s jednou instancí", kterou můžete aktivovat k převodu aplikace na aplikaci jedné instance. .

Zde je zachycení okna, o kterém mluvím: enter image description here Toto je projekt aplikace Visual Studio 2008 pro Windows.

4
Doliveras

zkoušel jsem všechna řešení zde a nic nefungovalo v mém projektu C # .net 4.0. Doufám, že pomůže někomu tu řešení, které pro mě fungovalo:

Jako proměnné hlavní třídy:

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

Pokud potřebujete zkontrolovat, zda je aplikace již spuštěna:

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
}

Potřeboval jsem zavřít ostatní, jen s nějakými podmínkami, to fungovalo dobře pro můj účel

4
HypeZ
3
Aaron Jensen

Tento článek jednoduše vysvětluje, jak můžete vytvořit aplikaci systému Windows s ovládáním počtu instancí nebo spustit pouze jednu instanci. To je velmi typická potřeba podnikové aplikace. Existuje mnoho dalších možných řešení, jak to zvládnout. 

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

2
Jorge Ferreira

1 - Vytvořte odkaz v programu.cs -> 

using System.Diagnostics;

2 - Vložte do void Main() jako první řádek kódu ->

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

A je to.

2
user5289350

Použijte VB.NET! Ne: opravdu;)

pomocí Microsoft.VisualBasic.ApplicationServices;

WindowsFormsApplicationBase z VB.Net poskytuje vlastnost "SingleInstace", která určuje jiné instance a nechat spustit pouze jednu instanci.

2
MADMap
1
tim_yates

Toto je kód 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

Toto je kód pro 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());
    }
}
1
Shruti

Musíte použít System.Diagnostics.Process.

Podívejte se na: http://www.devx.com/tips/Tip/20044

1
Thomas Jespersen

(Poznámka: to je zábavné řešení! Funguje to, ale používá špatné GDI + design k dosažení tohoto cíle.)

Vložte obrázek do aplikace a načtěte jej při spuštění. Podržte jej, dokud aplikace nedokončí. Uživatel nebude schopen spustit druhou instanci. (Samozřejmě je mutexové řešení mnohem čistší)

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

Po vyzkoušení více řešení i otázka. Skončil jsem s použitím příkladu pro WPF zde: http://www.c-sharpcorner.com/UploadFile/f9f215/how-to-re-repli--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();  
        }  

    }          
}  

V aplikaci App.xaml:

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

Jednoduše pomocí StreamWriter, jak o tom?

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

a

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

Normálně je to s pojmenovaným Mutexem (použijte nový Mutex ("název vaší aplikace", true) a zkontrolujte návratovou hodnotu), ale v Microsoft.VisualBasic.dll je také několik podpůrných tříd, které mohou pro vás udělat .

0
Tomer Gabel

Toto fungovalo pro mě v čistém C #. pokus/úlovek je, když je možné, že proces v seznamu skončí během smyčky.

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!
}

Od: Zajištění jediné instance aplikace .NET

a/ Jediná instance aplikace Mutex

Stejná odpověď jako @Smink a @Imjustpondering s twist:

Jon Skeet je FAQ na C # zjistit proč GC.KeepAlive záležitosti

0
Ric Tokyo

Při omezování aplikace na jednu instanci nezapomeňte zvážit zabezpečení:

Celý článek: https://blogs.msdn.Microsoft.com/oldnewthing/20060620-13/?p=30813

Používáme pojmenovaný mutex s pevným názvem, abychom zjistili , Zda je spuštěna další kopie programu. To ale také znamená, že útočník Může vytvořit mutex jako první, čímž zabrání našemu programu Běžet vůbec! Jak mohu zabránit tomuto typu útoku ?

...

Pokud útočník běží ve stejném kontextu zabezpečení, ve kterém je (nebo by byl) program Spuštěn, pak není nic, co byste mohli udělat. Jakýkoliv "tajný handshake" přijde s Určete, zda je spuštěna další kopie programu, útočník může napodobovat. Jelikož je spuštěn ve správném kontextu zabezpečení, může provést cokoli, co „skutečný“ programu.

...

Je jasné, že se nemůžete chránit před útočníkem, který běží na stejném bezpečnostním oprávnění , Ale můžete se chránit před nepřítelskými útočníky Běžícími na jiných bezpečnostních právech.

Zkuste nastavit DACL na vašem mutexu, zde je způsob .NET: https://msdn.Microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110) ) .aspx

0
Aardvark

Žádná z těchto odpovědí pro mě nepracovala, protože jsem to potřeboval pro práci v Linuxu pomocí monodevelop. To pro mě skvěle funguje:

Volání této metody předáním jedinečné ID

    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