A프로그램에서 B프로그램에게 요청하여 동작을 할 일이 있었습니다.
B프로그램은 초기화 되며 열려있는 창들이 닫혀야 했는데 이 부분에 대한 구현이 필요했습니다.
ex)
Program (B) 기능 -> OpenFileDialog (윈도우 API) Custom Form (사용자Form)
Program (B) 가 ShowDialog 로 잡혀있는 상황입니다.
윈도우API 종료는 SendMessage 를 사용해야 하고, Form은 Close를 통해 종료해 줄 수 있습니다.
(NamedPipe를 사용하였고, BlockingCollection Queue 를 사용하여 순서유지를 보장하였습니다.
코드가 좀 길어졌지만.. 남겨봅니다!
A프로그램 (명령 내리는 코드)
using System;
using System.IO;
using System.IO.Pipes;
using System.Windows.Forms;
namespace WindowsFormsApp6
{
public partial class Form2 : Form
{
private const string targetName = "A_Pipe";
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SendNamedPipe("CloseAPI");
}
private void button2_Click(object sender, EventArgs e)
{
SendNamedPipe("CloseSubForm");
}
private void SendNamedPipe(string message)
{
try
{
NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", targetName, PipeDirection.InOut);
namedPipeClientStream.Connect(10000); //10초
StreamWriter streamWriter = new StreamWriter(namedPipeClientStream);
streamWriter.WriteLine(message);
streamWriter.Flush();
streamWriter.Close();
namedPipeClientStream.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
B프로그램 (ShowDialog 하는 프로그램)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form3 : Form
{
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private const uint WM_CLOSE = 0x0010;
private const string myName = "A_Pipe"; //이름만 바꿔서 사용 가능
private BlockingCollection<string> queue = new BlockingCollection<string>();
private int queueCount = 0;
private void ProcessQueue()
{
//내부적으로 monitor lock 걸려있어 순서 및 단일 실행 보장
foreach (string message in queue.GetConsumingEnumerable())
{
if (message == "CloseAPI")
{
CloseAPI();
}
else if (message == "CloseSubForm")
{
CloseSubForm();
}
Invoke((MethodInvoker)delegate
{
queueCount++;
listBox1.Items.Add(string.Format("{0}_{1}", queueCount, message));
});
}
}
public Form3()
{
InitializeComponent();
//큐에서 관리
Task.Run(() =>
{
ProcessQueue();
});
//네임드파이프 통신
Task.Run(() =>
{
Receive();
});
}
private void Receive()
{
while (true)
{
try
{
NamedPipeServerStream namedPipeServerStream = new NamedPipeServerStream(myName, PipeDirection.InOut, 10);
namedPipeServerStream.WaitForConnection(); //데이터 받을때까지 기다립니다.
StreamReader streamReader = new StreamReader(namedPipeServerStream);
string message = streamReader.ReadLine();
queue.Add(message); //큐에 데이터 쌓아주기
streamReader.Close();
namedPipeServerStream.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "불러오기 테스트";
//테스트하기 위해 띄워주기만 함.
if (ofd.ShowDialog() == DialogResult.OK)
{
//정상 OK 눌렀을 때 실행
}
else
{
//강제 종료시 이 곳을 실행.
}
}
private void button2_Click(object sender, EventArgs e)
{
//테스트용으로 단순 띄워주기만 진행
new Form1().ShowDialog();
}
private void CloseAPI()
{
IntPtr hWnd = FindWindow(null, "불러오기 테스트"); //타이틀명으로 찾기
if (hWnd != IntPtr.Zero)
{
SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); //종료 메시지 보내기
}
}
private void CloseSubForm()
{
List<Form> formList = new List<Form>();
foreach (Form form in Application.OpenForms)
{
// 메인폼 제외
if (form is Form3 == false)
{
formList.Add(form);
}
}
foreach (Form form in formList)
{
Invoke((MethodInvoker)delegate
{
form.Close();
});
}
}
}
}
'C# > Windows Form' 카테고리의 다른 글
[C# Windows Form] Drag & Drop 기능 사용하기 (파일, 폴더 불러오기) (1) | 2025.08.15 |
---|---|
[C# Windows Form] Tray 아이콘 잔상 제거하기 (Win32 API 사용) (3) | 2025.07.29 |
[C# Windows Form] Win32 API EnumWindows 를 사용한 프로그램 타이틀 가져오기 (웹 브라우저 따라다니기) (1) | 2025.07.28 |
[C# Windows Form] 프로그램 Tray 아이콘 만들기, 감추기 (0) | 2025.07.16 |
[C# Window Forms] App.config, appsettings.json 파일 값 저장 (0) | 2025.06.25 |