상세 컨텐츠

본문 제목

C# Winform 프로그램 중복 실행 차단 기능 구현하기

프로그래밍/C#

by TickTack 2024. 1. 8. 16:50

본문

이번에는 C#의 Winform에서 프로그램을 중복으로 실행하는 것을 방지하기 위한

기능을 추가하는 방법에 대하여 알아보겠습니다.

해당 기능은 프로그램을 처음 실행 시 화면을 띄우기 전에 확인해야 하므로,

기본적으로 프로젝트를 만들면 생성되는 Program.cs 파일에 추가해야 합니다.

 

방법은 크게 2가지가 있으며, 각 방법에 대한 설명이 기재되어 있습니다.

프로젝트를 만든 후 자동으로 생성되는 클래스이기에 별도의 Class 및 namespace는 기재하지 않고

using문Main, 중복 검사 함수만 기재하였으니 참고해주세요.

 

- Processes 리스트를 모두 탐색

먼저 기능 동작 및 테스트 내용 확인을 위해 필요한 전체 코드입니다.

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

[STAThread]
private static void Main()
{
    Process[] process = Process.GetProcesses();
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    Console.WriteLine("Stopwatch 시작");
    if (IsExistProcess(process))
    {
        MessageBox.Show("프로그램이 이미 실행중입니다.");
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        try
        {
            Console.WriteLine($"[{process.Length}]" + stopwatch.Elapsed.TotalSeconds);
            Application.Run(new MainForm());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

private static bool IsExistProcess(Process[] processList)
{
    int count = 0;

    // 현재 Process 이름과 같은 것을 찾아서 검증하는 방식임
    foreach (Process process in processList)
    {
        if (process.ProcessName == Process.GetCurrentProcess().ProcessName)
        {
            count++;
            Console.WriteLine($"동일한 Process Name 발견 (Count : {count})");
        }

        // 중복 실행 발견 시
        if (count > 1)
        {
            return true;
        }
    }
    return false;
}

 

이렇게 한 후 실행하면 현재 프로그램을 실행한 PC에서

돌아가고 있는 프로세스 개수에 따라 걸린 시간을 확인할 수 있습니다.

제가 테스트했을 때는 다음과 같은 결과가 나왔습니다.

 

프로세스 개수가 301개일 때 중복 실행 여부 확인까지 약 292초 정도 소요된 것으로 보입니다.

다른 PC에서 실행했을 때는 프로세스 개수가 280개 가량 되었어도 오래 걸리지 않아 큰 문제가 없었으나,

현재 PC에서 갑자기 실행되기까지 너무 오래 걸려 확인한 결과

위와 같은 내용이 발견되어 해당 기능이 문제인 것으로 보고 수정에 들어갔습니다.

(2024-04-30 추가 : PC를 재부팅 한 이후로 위의 방법으로 진행하였을 때 비정상적으로 오래 걸리는 현상이 사라졌습니다. 다른 문제가 원인으로 보이는데 오래 켜놓으면 PC가 느려지는 현상과 연관이 있어 보입니다. 이 포스팅은 모두 PC를 몇 달 동안 켜놓은 상태에서 돌린 결과입니다.)

 

그렇게 수정을 진행한 내용이 Mutex를 통해 검사하는 방법입니다.

 

- Mutex 클래스를 통한 같은 이름의 프로세스간 소유권 확인

그래서 다른 방법을 사용해야 하는데 이 때 사용하는 방식이 Mutex로 판단하는 방식입니다.

이에 대한 코드는 다음과 같습니다.

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

private static Mutex mutex = null;

[STAThread]
private static void Main()
{
    Process[] process = Process.GetProcesses();
    string processName = Process.GetCurrentProcess().ProcessName;
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    Console.WriteLine("Stopwatch 시작");
    if (IsExistProcessMutex(processName))
    {
        MessageBox.Show("프로그램이 이미 실행중입니다.");
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        try
        {
            Console.WriteLine(stopwatch.Elapsed.TotalSeconds + $"초 소요됨. (총 Process 개수 : {process.Length}개)");
            Application.Run(new MainForm());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

private static bool IsExistProcessMutex(string processName)
{
    mutex = new Mutex(true, processName, out bool createdNew);
    if (createdNew)
    {
        return false;
    }
    else
    {
        return true;
    }
}

 

위의 코드를 테스트했을 때 결과입니다.

 

프로세스 개수가 일부 줄어들긴 하였으나 282개에 0.002초 가량 소요되었습니다.

이는 엄청난 차이이며 일반적인 PC는 프로세스 사용 개수가 1만, 10만개 단위까지 올라가지는 않을 것이므로

큰 문제 없이 사용할 수 있을 것으로 보입니다.

해당 코드에서 사용된 Mutex의 인자는 3개까지 존재하고 오버로드되어 1개, 2개인 생성자도 있으므로

필요한 만큼 부여해서 사용하면 됩니다.

 

다음은 MSDN에 있는 Mutex의 설명을 주관적으로 해석한 내용이므로 참고만 해주세요.

- initiallyOwned : 초기 소유권을 가져야 하는지에 대한 값이라고 하여 true, false 둘 다 적용해서 테스트해 보았으나 똑같이 중복 실행을 차단하는 것으로 보아 소유권의 개념이 살짝 다른 것으로 보입니다.

- name : Mutex를 생성할 때 구별할 수 있게 하는 문자열입니다. null이나 공백으로 하면 다른 프로세스와 공유하지 않는다고 합니다.

- createdNew : Mutex 생성 시 name 인자 값과 일치하는 Mutex가 있으면 false, Mutex가 새로 생성된 경우 true를 반환하므로, 같은 프로그램이 실행되어 있으면 false이고 아니라면 true가 됩니다.

 

아래는 MSDN Mutex 인자에 대한 원본 링크입니다.

 

Mutex 생성자 (System.Threading)

Mutex 클래스의 새 인스턴스를 초기화합니다.

learn.microsoft.com

 

Mutex 방식 기준으로 기능 동작을 위한 필수 코드는 아래와 같습니다.

using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

private static Mutex mutex = null;

[STAThread]
private static void Main()
{
    string processName = Process.GetCurrentProcess().ProcessName;
    if (IsExistProcessMutex(processName))
    {
        MessageBox.Show("프로그램이 이미 실행중입니다.");
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }
}

private static bool IsExistProcessMutex(string processName)
{
    mutex = new Mutex(true, processName, out bool createdNew);
    if (createdNew)
    {
        return false;
    }
    else
    {
        return true;
    }
}

 

이상으로 Winform에서 프로그램 중복 실행을 차단하는 방법에 대하여 알아보았습니다.

관련글 더보기

댓글 영역