.NET में दिए गए ऐप के कई उदाहरणों को रोकें?


123

.NET में, एक ऐप के कई उदाहरणों को एक ही समय में चलने से रोकने का सबसे अच्छा तरीका क्या है? और अगर कोई "सर्वश्रेष्ठ" तकनीक नहीं है, तो प्रत्येक समाधान के साथ विचार करने के लिए कुछ कैवेट क्या हैं?

जवाबों:


151

म्यूटेक्स का उपयोग करें। 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";

1
एक म्यूटेक्स का उपयोग करना नॉन नेट कोड के लिए भी काम करता है (हालाँकि वाक्य रचना अलग-अलग होगी)
क्रैश 28

8
यहाँ कुछ अच्छी टिप्पणियों के साथ थोड़ा और भरा हुआ संस्करण है: stackoverflow.com/questions/229565/…
रिचर्ड वाटसन

2
@ क्लार्ककेंट: सिर्फ एक यादृच्छिक स्ट्रिंग ताकि म्यूटेक्स नाम किसी अन्य एप्लिकेशन से नाम से न टकराए।
जुगफिन

क्या यह कुछ निश्चित उदाहरणों तक भी सीमित रह सकता है?
अलेजांद्रो डेल रीओ

3
अपने ऐप गाइड को बदलते या बदलते समय बेहतर नियंत्रण रखने के लिए, आप इसका उपयोग कर सकते हैं: string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), true)[0]).Value;जिसे
एसेम्बलिंग

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

1
मुझे लगता है कि इसे देखना चाहिए: odetocode.com/blogs/scott/archive/2004/08/20/…
SubmarineX

@SubmarineX आपको कैसे यकीन है कि यह लेख सही है? यह म्यूटेक्स और कोडप्रोजेक्ट.com
जॉन गुयेन

अद्भुत अपने समय और प्रयासों के लिए एकदम सही धन्यवाद
अहमद महमूद

2
-1 जबकि यह त्वरित समाधान है, यह भी बहुत आसान है a.exe को रोकना b.exe के लिए बदला जा सकता है और दोनों चलेंगे। + अन्य मामले जहां यह बस के रूप में अभ्यस्त काम नहीं करेगा। सावधानी से प्रयोग करें!
लार्स नीलसन

यह मोनो-डेवलपमेंट के साथ काम नहीं करता है। विंडोज़ वातावरण के तहत यह बहुत अच्छा काम करता है।
टोनो नाम

20

यहां वह कोड है जो आपको यह सुनिश्चित करने की आवश्यकता है कि केवल एक उदाहरण चल रहा है। यह नामांकित म्यूटेक्स का उपयोग करने की विधि है।

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

2
WPF अनुप्रयोग के लिए Application.Current.Shutdown () का उपयोग करें; यह तरीका एक आकर्षण की तरह काम करता है। धन्यवाद Terrapin।
जेफ

यहाँ मुख्य बात यह है कि आप म्यूटेक्स को स्थिर बनाते हैं। साथ ही अन्य मामले में जीसी इसे एकत्र करेगा।
ओलेक्सी

मैंने म्यूटेक्स नाम की सादगी और स्पष्टता का आनंद लिया। यह कोड संक्षिप्त और प्रभावी है।
चाड

7

Hanselman के पास Microsoft से WinFormsApplicationBase वर्ग का उपयोग करने के लिए एक पोस्ट है


मैं कुछ वर्षों से इसका उपयोग कर रहा हूं, लेकिन अब मैं म्यूटेक्स-आधारित समाधान को बदलना चाहता हूं। मेरे पास ऐसे ग्राहक हैं जो इसके साथ मुद्दों की रिपोर्ट करते हैं और मुझे संदेह है कि यह करने के लिए रीमोटिंग का उपयोग कर रहा है।
रिचर्ड वॉटसन

5

ऐसा लगता है कि 3 मौलिक तकनीकें हैं जो अब तक सुझाई गई हैं।

  1. Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase वर्ग से प्राप्त करें और IsSingleInstance गुण को सही पर सेट करें। (मुझे विश्वास है कि यहाँ एक चेतावनी है कि यह WPF अनुप्रयोगों के साथ काम नहीं करेगा, है ना?)
  2. एक नामित म्यूटेक्स का उपयोग करें और जांचें कि क्या यह पहले से ही बनाया गया है।
  3. चल रही प्रक्रियाओं की एक सूची प्राप्त करें और प्रक्रियाओं के नाम की तुलना करें। (इसमें किसी उपयोगकर्ता की मशीन पर चलने वाली किसी अन्य प्रक्रिया के सापेक्ष आपकी प्रक्रिया का नाम अद्वितीय होने की आवश्यकता का विवरण है।)

मुझे याद किया किसी भी चेतावनी?


3
मुझे नहीं लगता कि 3 बहुत कुशल है। मैं म्यूटेक्स को वोट करूंगा, कई बार समस्याओं के बिना इसका इस्तेमाल किया। मैंने आइटम 1 का उपयोग कभी नहीं किया है यकीन नहीं है कि जब आप सी # में होते हैं तो वह कैसे उड़ता है।
टाइपमिज़्मचैच

2
विकल्प 1 अभी भी WPF के साथ काम करता है यह अभी थोड़ा अधिक शामिल है। msdn.microsoft.com/en-us/library/ms771662.aspx
ग्रीम ब्रैडबरी

5

1 - program.cs -> में एक संदर्भ बनाएँ

using System.Diagnostics;

2 - void Main()कोड की पहली पंक्ति के रूप में डालें ->

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

बस।


इससे क्या फर्क पड़ता है Mutex? क्या कोई पकड़ है?
हरमाबे अटैक हेलीकॉप्टर

यह प्रक्रिया के नाम का उपयोग कर रहा है। यदि नाम दोहराया जाता है तो यह एक झूठा झंडा पैदा करेगा। किसी भी अन्य मामले में, यह म्यूटेक्स की तुलना में क्लीनर है
मैगलैन्स

4

विजुअल स्टूडियो 2005 या 2008 का उपयोग करते हुए जब आप "एप्लिकेशन" पैनल के अंदर गुणों वाली खिड़कियों पर एक निष्पादन योग्य के लिए एक प्रोजेक्ट बनाते हैं, तो "एक उदाहरण एप्लिकेशन बनाएं" नाम का एक चेक बॉक्स होता है जिसे आप एप्लिकेशन को एकल उदाहरण एप्लिकेशन पर परिवर्तित करने के लिए सक्रिय कर सकते हैं ।

यहाँ मैं जिस विंडो की बात कर रहा हूँ उस पर कब्जा है: यहाँ छवि विवरण दर्ज करें यह एक विजुअल स्टूडियो 2008 विंडोज़ एप्लीकेशन प्रोजेक्ट है।


3
मैंने अपने C # / WPF ऐप के लिए आपके द्वारा बताए गए इस चेकबॉक्स की तलाश की, और कोई भी ऐसा नहीं है।
HappyNomad

3
मैं इसे अपने VS 2008 C # / WinForms ऐप के गुणों में नहीं देखता।
जेसी मैकग्रे

VS2005 में भी नहीं। उसे पुराने VB स्टूडियो का उल्लेख करना चाहिए।
नवफाल

हां विकल्प मौजूद है, मैंने उस विंडो की कैप्चर जोड़ने के लिए पोस्ट को संशोधित किया है जिसमें आप यह विकल्प पा सकते हैं।
Doliveras

6
विकल्प केवल VB.NET एप्लिकेशन के लिए मौजूद है, C # के लिए नहीं। जाहिरा तौर पर विकल्प ही Microsoft से WinFormsApplicationBase वर्ग का उपयोग करता है। विजुअलबेसिक असेंबली।
अमोलबक

4

मैं यहाँ सभी समाधानों की कोशिश की और कुछ भी मेरी सी # .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
}

मुझे केवल कुछ शर्तों के साथ अन्य istances बंद करने की आवश्यकता थी, इसने मेरे उद्देश्य के लिए अच्छी तरह से काम किया


आपको वास्तव में म्यूटेक्स को प्राप्त करने और इसे जारी करने की आवश्यकता नहीं है। आपको बस इतना पता होना चाहिए कि क्या किसी अन्य ऐप ने पहले ही ऑब्जेक्ट (यानी, इसकी कर्नेल संदर्भ गणना> = 1) बना ली है।
माइकल गोल्डस्मिन


3

कई समाधान की कोशिश के बाद मैं सवाल। मैं यहाँ 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"

2

यह आलेख सरलता से बताता है कि आप अपने इंस्टेंस की संख्या पर नियंत्रण के साथ एक विंडोज़ एप्लिकेशन कैसे बना सकते हैं या केवल एकल उदाहरण चला सकते हैं। यह एक व्यावसायिक अनुप्रयोग की बहुत विशिष्ट आवश्यकता है। इसे नियंत्रित करने के लिए पहले से ही कई अन्य संभावित समाधान मौजूद हैं।

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


लिंक टूट गया है।
चाड

2

VB.NET का प्रयोग करें! सच में नहीं ;)

Microsoft.VisualBasic.ApplicationServices का उपयोग कर;

VB.Net से WindowsFormsApplicationBase आपको एक "SingleInstace" संपत्ति प्रदान करता है, जो अन्य इंस्टेंसेस को निर्धारित करता है और केवल एक इंस्टेंस को चलाने देता है।


2

यह 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

यह 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

(नोट: यह एक मजेदार समाधान है! यह काम करता है लेकिन इसे प्राप्त करने के लिए खराब GDI + डिज़ाइन का उपयोग करता है।)

अपने ऐप के साथ एक छवि रखें और इसे स्टार्टअप पर लोड करें। ऐप से बाहर निकलने तक इसे दबाए रखें। उपयोगकर्ता दूसरा उदाहरण शुरू करने में सक्षम नहीं होगा। (बेशक म्यूटेक्स समाधान ज्यादा साफ है)

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

यह वास्तव में अपनी सादगी में शानदार है, और यह बहुत ही किसी भी तरह की फ़ाइल के साथ काम करता है, न कि केवल चित्र। मुझे लगता है कि म्यूटेक्स समाधान "साफ" से बहुत दूर है। यह बेहद जटिल है और जाहिर तौर पर इसे "सही" न करने के कारण विफल होने के कई तरीके हैं। इसके लिए एक Main()विधि की भी आवश्यकता होती है जो कि WPF के काम करने के तरीके के खिलाफ जाती है।
काइल डेलाने

यह बग का उपयोग करने की तरह है। यह काम करता है लेकिन यह उस उद्देश्य के लिए नहीं बनाया गया है। मैं इसे एक पेशेवर के रूप में उपयोग नहीं करूंगा।
Bitterblue

हाँ, यह दुर्भाग्यपूर्ण है कि हमारे पास अपवादों पर भरोसा किए बिना इस प्रभावी और सरल समाधान नहीं है।
काइल डेलानी

हालांकि यह बिल्कुल बग नहीं है। यह अभी भी .NET है जैसा कि इरादा है।
काइल डेलाने

1
[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 को एक ट्विस्ट के रूप में समान उत्तर दें:

Cc पर जॉन स्कीट के अक्सर पूछे जाने वाले प्रश्न यह जानने के लिए कि GC.KeepAlive क्यों मायने रखता है


-1, क्योंकि आप म्यूटेक्स के साथ एक ब्लॉकिंग ब्लॉक का उपयोग करने में विफल रहते हैं, जो कि KeepAlive को सुपरफ्लस बना देगा। और हां, मुझे लगता है कि जॉन स्कीट को यह गलत लगा। वह विस्तृत नहीं करता कि इस मामले में म्यूटेक्स को निपटाना गलत क्यों होगा।

1

बस एक का उपयोग 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);
}

0

आम तौर पर यह एक नामित म्यूटेक्स (नए म्यूटेक्स ("आपके ऐप का नाम", सत्य) का उपयोग करें) और रिटर्न वैल्यू की जांच) के साथ किया जाता है, लेकिन Microsoft में कुछ समर्थन कक्षाएं भी हैंविस्सुअलबासिकयह आपके लिए कर सकता है


0

इसने मेरे लिए शुद्ध C # में काम किया। कोशिश / पकड़ तब है जब संभवतः सूची में एक प्रक्रिया आपके लूप के दौरान बाहर निकल जाती है।

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

किसी एप्लिकेशन को किसी एकल आवृत्ति पर प्रतिबंधित करते समय सुरक्षा पर विचार करना सुनिश्चित करें:

पूरा लेख: https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813

हम एक निश्चित नाम के साथ एक नामित म्यूटेक्स का उपयोग कर रहे हैं ताकि यह पता लगाया जा सके कि कार्यक्रम की एक और प्रतिलिपि चल रही है या नहीं। लेकिन इसका मतलब यह भी है कि एक हमलावर पहले म्यूटेक्स बना सकता है, जिससे हमारे कार्यक्रम को बिल्कुल भी चलने से रोका जा सके! मैं इस प्रकार के सेवा हमले से कैसे रोक सकता हूं?

...

यदि हमलावर उसी सुरक्षा संदर्भ में चल रहा है जैसा कि आपका कार्यक्रम है (या होगा) में चल रहा है, तो ऐसा कुछ भी नहीं है जो आप कर सकते हैं। जो भी "गुप्त हैंडशेक" आप यह निर्धारित करने के लिए करते हैं कि क्या आपके कार्यक्रम की एक और प्रतिलिपि चल रही है, हमलावर इसकी नकल कर सकते हैं। चूंकि यह सही सुरक्षा संदर्भ में चल रहा है, यह कुछ भी कर सकता है जो "वास्तविक" कार्यक्रम कर सकता है।

...

स्पष्ट रूप से आप अपने आप को एक ही सुरक्षा विशेषाधिकार पर चलने वाले हमलावर से नहीं बचा सकते हैं, लेकिन आप अभी भी अन्य सुरक्षा विशेषाधिकारों पर चल रहे अनपेक्षित हमलावरों से खुद की रक्षा कर सकते हैं।

अपने mutex पर एक DACL सेट करने का प्रयास करें, यहां .NET तरीका है: https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.1v).aspx


0

इस जवाब में से किसी ने भी मेरे लिए काम नहीं किया क्योंकि मुझे मोनोकोडेल का उपयोग करके लिनक्स के तहत काम करने की आवश्यकता थी। यह मेरे लिए बहुत अच्छा काम करता है:

इसे पास करने वाली इस विधि को एक विशिष्ट आईडी कहें

    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); 
        }
    }         
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.