2009-05-25 6 views
4

나는 Windows 응용 프로그램 (C#)이 있으며 그 응용 프로그램에서 한 인스턴스를 실행하도록 구성해야합니다. 즉, 한 명의 사용자가 .exe 파일을 클릭하여 응용 프로그램이 실행되고 사용자는 실행중인 응용 프로그램의 첫 번째 인스턴스를 닫지 않았으므로 다음 인스턴스를 실행하여 첫 번째 인스턴스가 나타나야하며 새 인스턴스를 열지 않아야합니다.응용 프로그램에서 하나의 인스턴스 실행

어떻게 할 수 있습니까?

미리 감사드립니다.

답변

10

나는 종종 같은 다른 프로세스를 확인하여이 문제를 해결 이름. 이 장점/단점은 당신 (또는 사용자)이 exe의 이름을 변경하여 수표에서 "옆으로"물러날 수 있다는 것입니다. 당신이 원한다면 아마 반환 된 Process-object를 사용할 수있을 것이다. 그것은 당신의 필요에 따라

string procName = Process.GetCurrentProcess().ProcessName; 
    if (Process.GetProcessesByName(procName).Length == 1) 
    { 
     ...code here... 
    } 

, 나는 그것 (가끔 서비스로 실행되는 서버 프로세스의) 재 컴파일 우유없는 검사를 우회하는 편리한 것 같아요.

+0

+1 접근 방식을 사용합니다 –

+0

이 방법은 부분적으로 신뢰할 수있는 코드에서는 사용할 수 없습니다. 글로벌 C# 예제로서 이것은 가난한 접근 방식입니다. – Shaamaan

1

편집 : 질문에 C#이 포함되도록 수정되었습니다. 내 대답은

응용 프로그램의 여러 인스턴스를 실행하지 못하도록 단일 인스턴스 응용 프로그램 확인란을 만들기를 선택에만 vb.net 응용 프로그램에 대해 작동합니다. 이 확인란의 기본 설정이 지워져 응용 프로그램의 여러 인스턴스가 실행될 수 있습니다.

당신은 프로젝트에서이 작업을 수행 할 수 있습니다 -> 속성 - C 번호를 사용하면 가정> 응용 프로그램 탭

Source

+1

Afaik 이것은 VB에만 적용되며 C#에는 적용되지 않습니다. –

+0

C#에서 VB 솔루션을 사용하는 방법에 대한 내 제안을 참조하십시오. 체크 박스를 체크하는 것보다 조금 더 많은 것이지 많은 것은 아닙니다. –

0

 static Mutex mx; 
     const string singleInstance = @"MU.Mutex"; 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      try 
      { 
       System.Threading.Mutex.OpenExisting(singleInstance); 
       MessageBox.Show("already exist instance"); 
       return; 
      } 
      catch(WaitHandleCannotBeOpenedException) 
      { 
       mx = new System.Threading.Mutex(true, singleInstance); 

      } 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new MainForm()); 
     } 
+1

이것은 오용을 다루는 예외의 예입니다. 그리고 당신은 뮤텍스를 처분하지 않습니다 :] – nothrow

+1

Exisitng 뮤텍스를 체크하기 위해 try 캐치를 사용하는 끔찍한 사용법. – leppie

+0

더 나은 뮤텍스 처리를 위해 http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567#229567을 참조하십시오. –

1

정확히 같은 문제가있었습니다. Google은 프로세스 접근 방식을 시도했지만 사용자가 관리자가 아닌 다른 프로세스에 대한 정보를 읽을 권한이없는 경우 실패합니다. 그래서 우리는 아래의 솔루션을 구현했습니다.

기본적으로 독점적 인 읽기 전용 파일을 열려고합니다. 이것이 실패하면 (인스턴스가 이미 이것을 수행했기 때문에) 예외가 발생하고 앱을 종료 할 수 있습니다.

 bool haveLock = false; 
     try 
     { 
      lockStream = new System.IO.FileStream(pathToTempFile,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,System.IO.FileShare.None); 
      haveLock = true; 
     } 
     catch(Exception) 
     { 
      System.Console.WriteLine("Failed to acquire lock. "); 
     } 
     if(!haveLock) 
     { 
      Inka.Controls.Dialoge.InkaInfoBox diag = new Inka.Controls.Dialoge.InkaInfoBox("App has been started already"); 
      diag.Size = new Size(diag.Size.Width + 40, diag.Size.Height + 20); 
      diag.ShowDialog(); 
      Application.Exit(); 
     } 
4

VB.Net 팀은 이미 솔루션을 구현했습니다. Microsoft.VisualBasic.dll에 종속성을 가져야하지만, 그렇게해도 문제가되지 않는다면 좋은 해결책이 될 것입니다. 다음 문서의 끝 부분을 참조하십시오 Single-Instance Apps

다음은 기사에서 관련 부분입니다 :

1)가 microsoft.visualbasic.dll 2에 대한 참조를 추가) 프로젝트에 다음 클래스를 추가합니다.

public class SingleInstanceApplication : WindowsFormsApplicationBase 
{ 
    private SingleInstanceApplication() 
    { 
     base.IsSingleInstance = true; 
    } 

    public static void Run(Form f, StartupNextInstanceEventHandler startupHandler) 
    { 
     SingleInstanceApplication app = new SingleInstanceApplication(); 
     app.MainForm = f; 
     app.StartupNextInstance += startupHandler; 
     app.Run(Environment.GetCommandLineArgs()); 
    } 
} 

열린 프로그램.CS는 다음 using 문을 추가 :

using Microsoft.VisualBasic.ApplicationServices; 

변경합니다 클래스를 다음과 :

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     SingleInstanceApplication.Run(new Form1(), StartupNextInstanceEventHandler); 
    } 

    public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e) 
    { 
     MessageBox.Show("New instance"); 
    } 
} 
+2

이것은 간단한 접근 방법이지만 Scott Hanselman의 블로그 게시물 (http://www.hanselman.com/blog/TheWeeklySourceCode31SingleInstanceWinFormsAndMicrosoftVisualBasicdll.aspx –

+0

)의 토론에서 언급 된 함정이 있음을 지적 해 주셨습니다. 그것의. 연결된 게시물에서 한 가지 함정 만 볼 수 있었으며 Windows가 안전 모드에서 실행 중일 때이 솔루션이 작동하지 않는다는 것이 었습니다. 많은 응용 프로그램에는 아무렇게나 정상 모드로 실행해야하는 기능이 있습니다. 그러면 많은 단점이 없을 수 있습니다. 어쨌든, 문제가 있다는 것을 아는 것이 좋습니다. –

0

내가이 시나리오에 대한 Mutex을 사용하십시오. 또는 Semaphore도 사용할 수 있습니다 (단 Mutex).

여기 (WPF 응용 프로그램에서, 그러나 동일한 원리는 다른 프로젝트 유형에 적용한다) 내 예제 :

public partial class App : Application 
{ 
    const string AppId = "MY APP ID FOR THE MUTEX"; 
    static Mutex mutex = new Mutex(false, AppId); 
    static bool mutexAccessed = false; 

    protected override void OnStartup(StartupEventArgs e) 
    { 
     try 
     { 
      if (mutex.WaitOne(0)) 
       mutexAccessed = true; 
     } 
     catch (AbandonedMutexException) 
     { 
      //handle the rare case of an abandoned mutex 
      //in the case of my app this isn't a problem, and I can just continue 
      mutexAccessed = true; 
     } 

     if (mutexAccessed) 
      base.OnStartup(e); 
     else 
      Shutdown(); 
    } 

    protected override void OnExit(ExitEventArgs e) 
    { 
     if (mutexAccessed) 
      mutex?.ReleaseMutex(); 

     mutex?.Dispose(); 
     mutex = null; 
     base.OnExit(e); 
    } 
} 
0

내가이 code을 발견, 그것은 작품입니다!

/// <summary> 
     /// The main entry point for the application. 
     /// Limit an app.to one instance 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      //Mutex to make sure that your application isn't already running. 
      Mutex mutex = new System.Threading.Mutex(false, "MyUniqueMutexName"); 
      try 
      { 
       if (mutex.WaitOne(0, false)) 
       { 
        // Run the application 
        Application.EnableVisualStyles(); 
        Application.SetCompatibleTextRenderingDefault(false); 
        Application.Run(new Form1()); 
       } 
       else 
       { 
        MessageBox.Show("An instance of the application is already running.", 
         "An Application Is Running", MessageBoxButtons.OK, MessageBoxIcon.Information); 
       } 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message, "Application Error 'MyUniqueMutexName'", 
        MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 
      finally 
      { 
       if (mutex != null) 
       { 
        mutex.Close(); 
        mutex = null; 
       } 
      } 
     } 
관련 문제