기본 콘텐츠로 건너뛰기

[ TIPS ] 프로세스 검증 및 동일 경로 확인하기.

  진행 중인 프로젝트에서 동일 경로에 존재하는 동일한 어플리케이션이 중복 실행이 되지 않도록 하여야 하는 요구가 들어와서 프로세스를 검증하는 로직을 구성하였다. 아래의 예제에서는 자체적으로 구성한 프레임워크를 사용하는 것도 포함되어 있으므로 해당하는 구문은 알아서 전환 처리해야 한다.

Process 가져오기

  실행 중인 프로세스들은 다음과 같은 명령을 사용해서 동일한 명칭을 가지는 프로세스들을 가져온다.

Process[] processes = Process.GetProcessByName(Path.GetFileNameWithoutExtension(AppContext.ApplicationName));

현재 Process 를 제외한 나머지 검증

  프로세스의 이름이 동일하기 때문에 현재 자신의 프로세스도 포함이 된다. 따라서 아래와 같이 자신을 제외한 것들을 대상으로 하여야 한다.

Process[] processes = Process.GetProcessByName(Path.GetFileNameWithoutExtension(AppContext.ApplicationName));
foreach(Process p in processes) {
// 자기 자신 검증.
if (Process.GetCurrentProcess().Id != p.Id) {
...
}
}
}

  이제 작업 경로를 비교하여 동일한 경로에 속한 것만 중복 메시지로 처리한다.

Process[] processes = Process.GetProcessByName(Path.GetFileNameWithoutExtension(AppContext.ApplicationName));

foreach(Process p in processes) {
    // 자기 자신 검증.
    if (Process.GetCurrentProcess().Id != p.Id) {
        // 경로 검증
        if (Path.GetDirectoryName(p.MainModule.FileName) == AppContext.BaseDirectory) {
            // 기존 프로세스 중복 알림.
            MessageBox.Show(...);
            ...
        }
    }
}

대상 Bring to Front 처리하기

  동일 폴더의 동일 어플리케이션 중복을 검증하였으므로 기존 실행된 어플리케이션을 가장 앞으로 위치시켜 주고 현재 처리 중인 프로세스는 그냥 종료하면 된다.

...
using System.Runtime.InteropServices;
...
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
...

...
Process[] processes = Process.GetProcessByName(Path.GetFileNameWithoutExtension(AppContext.ApplicationName));

foreach(Process p in processes) {
    // 자기 자신 검증.
    if (Process.GetCurrentProcess().Id != p.Id) {
        // 경로 검증
        if (Path.GetDirectoryName(p.MainModule.FileName) == AppContext.BaseDirectory) {
            // 기존 프로세스 중복 알림.
            MessageBox.Show(...);
            // 기존 프로세스 Bring to Front
            IntPtr handle = p.MainWindowHandle;
            SetForegroundWindow(handle);
            return false;
        }
    }
}

  대략 이런 수준에서 처리를 해 주면 될 듯 하다. 혹여 대상 어플리케이션이 Minimize 되어 있는 경우는 SetForegroundWindow 로 나타나지 않으므로 아래와 같이 추가적인 설정을 해 주어야 한다.

...
using System.Runtime.InteropServices;
...
private const int SW_SHOWMAXIMIZED = 3;
...
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
...

...
Process[] processes = Process.GetProcessByName(Path.GetFileNameWithoutExtension(AppContext.ApplicationName));

foreach(Process p in processes) {
    // 자기 자신 검증.
    if (Process.GetCurrentProcess().Id != p.Id) {
        // 경로 검증
        if (Path.GetDirectoryName(p.MainModule.FileName) == AppContext.BaseDirectory) {
            // 기존 프로세스 중복 알림.
            MessageBox.Show(...);
            // 기존 프로세스 Bring to Front
            IntPtr handle = p.MainWindowHandle;
            SetForegroundWindow(handle);             // Bring to Front
            ShowWindow(handle, SW_SHOWMAXIMIZED);    // Maximize
            return false;
        }
    }
}

댓글