지원 Framework: 프레임워크, .Net 6에서 확인함.
"싱글 인스턴스가 뭐냐?"라는 질의 보다 이것을 왜 사용했는지부터 알아보겠습니다.
프로그램을 실행할 때 아규먼트를 받아서 처리하는 프로그램을 개발할 때, 이미 떠 있는 프로세스에 아규먼트를 전달 할 방법이 뭐가 있을까?
이 방법 이전에는 프로그램이 떠있는지 체크해서 Send Message Win32 API를 통해 아규먼트를 전달하는 방법을 사용했는데 이 경우 별도의 프로그램을 중간매개로 만들어야 했습니다.
C# 프로젝트를 생성하면 program.cs가 자동생성되고
Application.Run(new Form1());
위 코드를 사용해 폼을 띄웁니다. 프로그램이 시작된 상태에서 다시 실행파일을 실행하면 위 코드를 통해 똑같은 프로그램이 뜨겠죠. 이를 다중 인스턴스라 명명하겠습니다. 같은 프로그램을 두개 이상 띄울 수 있다고 하여 ....
다시 돌아와서 싱글로 기존에 떠있는 프로세스를 Static으로 다시 사용할 방법을 설명드립니다.
program.cs를 다음과 같이 교체해주세요. logger는 nLog를 사용했습니다. 콘솔로 변경해주셔도 무방합니다.
internal static class Program
{
private static Frmmain1 _Frmmain;
private static readonly NLog.Logger logger = NLog.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString());
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_Frmmain = new Frmmain1();
SingleInstanceApplication.Run(_Frmmain, NewInstanceHandler);
}
public static void NewInstanceHandler(object sender, StartupNextInstanceEventArgs eventArgs)
{
try
{
logger.Debug("## NewInstanceHandler ##");
_Frmmain.AfterLoginProc(eventArgs);
eventArgs.BringToForeground = true;
}
catch (Exception ex)
{
logger.Error(ex);
}
}
public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}
public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
{
try
{
SingleInstanceApplication app = new SingleInstanceApplication();
app.MainForm = f;
app.StartupNextInstance += startupHandler;
app.Run(Environment.GetCommandLineArgs());
}
catch (Exception ex)
{
logger.Error(ex);
}
}
protected override bool OnStartup(StartupEventArgs eventArgs)
{
try
{
//MessageBox.Show(eventArgs.CommandLine.Count.ToString());
logger.Debug("## SingleInstanceApplication.OnStartup ##");
_Frmmain.AfterLoginProc(eventArgs);
}
catch (Exception ex)
{
logger.Error(ex);
}
return true;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
try
{
// Subsequent launches
base.OnStartupNextInstance(eventArgs);
}
catch (Exception ex)
{
logger.Error(ex);
}
}
}
}
아규먼트를 실행되어 있는 프로세스에 어떻게 전달하는가를 테스트하는 것이기 때문에 폼에 아규먼트를 확인할 수 있는 장치 (리스트 박스에 아규먼트 뿌리기)를 해둡니다.
// 아규먼트 구조체를 1개만 쓸 것이지 왜 두개를 만들어서... 오버라이드로 함수 1개 더 추가합니다.
public void AfterLoginProc(StartupEventArgs EventArgs)
{
if (EventArgs != null && EventArgs.CommandLine != null && EventArgs.CommandLine.Count > 0)
{
lstArgs.Items.Clear();
foreach (string line in EventArgs.CommandLine)
{
lstArgs.Items.Add(line);
}
}
}
public void AfterLoginProc(StartupNextInstanceEventArgs EventArgs)
{
if (EventArgs != null && EventArgs.CommandLine != null && EventArgs.CommandLine.Count > 0)
{
lstArgs.Items.Clear();
foreach (string line in EventArgs.CommandLine)
{
lstArgs.Items.Add(line);
}
}
}
디버그 상태로 테스트하기가 힘들기에 빌드 후, 실행파일을 통해 바로가기 아이콘을 두개 만든 후, 대충 아규먼트를 다르게 해서 변경합니다.
그리고 차례대로 바로가기를 실행하면 실행되는 프로세스는 한개에 리스트 박스에 변경되는 아규먼트를 보실 수 있습니다. 이것을 이용해서 궂이 Mutex를 이용해 이중실행 방지를 하지 않아도 되지 않을까 합니다.
'개발 > C#' 카테고리의 다른 글
.net6에서 process.start로 다른 프로그램 또는 브라우저 실행 시 오류해결 (0) | 2024.01.08 |
---|---|
바닐라 ListBox 항목 별 색깔 바꾸기 (0) | 2023.08.17 |
Pfx인증서 파일을 PC에 설치하기 (1) | 2023.06.28 |
폼에 모든 라벨의 ForeColor 변경하기 (0) | 2023.06.27 |
C# 클래스 라이브러리 작성 시 다중 타겟 프레임워크 지원 (0) | 2023.06.22 |