Initial commit to new repository

This commit is contained in:
2026-04-03 18:22:19 +09:00
commit 4458bb0f52
7672 changed files with 452440 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;
namespace AxCopilot.Handlers;
public class PortHandler : IActionHandler
{
private static readonly Dictionary<int, string> _procCache = new Dictionary<int, string>();
private static readonly Dictionary<int, int> _pidMap = new Dictionary<int, int>();
private static DateTime _cacheExpiry = DateTime.MinValue;
public string? Prefix => "port";
public PluginMetadata Metadata => new PluginMetadata("PortChecker", "포트 & 프로세스 점검 — port 뒤에 포트번호 또는 프로세스명", "1.0", "AX");
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
RefreshProcessCache();
TcpConnectionInformation[] activeTcpConnections;
try
{
IPGlobalProperties iPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
activeTcpConnections = iPGlobalProperties.GetActiveTcpConnections();
}
catch (Exception ex)
{
LogService.Warn("포트 조회 실패: " + ex.Message);
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("네트워크 정보를 가져올 수 없습니다", ex.Message, null, null, null, "\ue7ba")));
}
string text = query.Trim();
if (string.IsNullOrWhiteSpace(text))
{
List<LauncherItem> list = (from c in activeTcpConnections
where c.State == TcpState.Established || c.State == TcpState.Listen
orderby c.LocalEndPoint.Port
select c).Take(20).Select(delegate(TcpConnectionInformation c)
{
string processNameForPort = GetProcessNameForPort(c.LocalEndPoint.Port);
string text2 = ((c.State == TcpState.Listen) ? "LISTEN" : "ESTABLISHED");
return new LauncherItem($":{c.LocalEndPoint.Port} → {c.RemoteEndPoint}", text2 + " · " + processNameForPort + " · Enter로 포트번호 복사", null, c.LocalEndPoint.Port.ToString(), null, "\ue968");
}).ToList();
if (!list.Any())
{
list.Add(new LauncherItem("활성 연결 없음", "TCP 연결이 감지되지 않았습니다", null, null, null, "\ue968"));
}
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
if (int.TryParse(text, out var portNum))
{
List<TcpConnectionInformation> source = activeTcpConnections.Where((TcpConnectionInformation c) => c.LocalEndPoint.Port == portNum || c.RemoteEndPoint.Port == portNum).ToList();
if (!source.Any())
{
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem($"포트 {portNum} — 사용 중 아님", "해당 포트를 사용하는 TCP 연결이 없습니다", null, portNum.ToString(), null, "\ue946")));
}
List<LauncherItem> result = source.Select(delegate(TcpConnectionInformation c)
{
string processNameForPort = GetProcessNameForPort(c.LocalEndPoint.Port);
int pidForPort = GetPidForPort(c.LocalEndPoint.Port);
return new LauncherItem($":{c.LocalEndPoint.Port} ←→ {c.RemoteEndPoint}", $"{c.State} · {processNameForPort} (PID {pidForPort}) · Enter로 PID 복사", null, (pidForPort > 0) ? pidForPort.ToString() : portNum.ToString(), null, "\ue968");
}).ToList();
return Task.FromResult((IEnumerable<LauncherItem>)result);
}
string procLower = text.ToLowerInvariant();
List<LauncherItem> list2 = activeTcpConnections.Where(delegate(TcpConnectionInformation c)
{
string text2 = GetProcessNameForPort(c.LocalEndPoint.Port).ToLowerInvariant();
return text2.Contains(procLower);
}).Take(15).Select(delegate(TcpConnectionInformation c)
{
string processNameForPort = GetProcessNameForPort(c.LocalEndPoint.Port);
return new LauncherItem($"{processNameForPort} : {c.LocalEndPoint.Port} → {c.RemoteEndPoint}", $"{c.State} · Enter로 포트번호 복사", null, c.LocalEndPoint.Port.ToString(), null, "\ue968");
})
.ToList();
if (!list2.Any())
{
list2.Add(new LauncherItem("'" + text + "' — 연결 없음", "해당 프로세스의 TCP 연결이 없습니다", null, null, null, "\ue7ba"));
}
return Task.FromResult((IEnumerable<LauncherItem>)list2);
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (item.Data is string text)
{
try
{
Clipboard.SetText(text);
}
catch
{
}
}
return Task.CompletedTask;
}
private static void RefreshProcessCache()
{
if (DateTime.Now < _cacheExpiry)
{
return;
}
_procCache.Clear();
_pidMap.Clear();
try
{
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
try
{
_procCache[process.Id] = process.ProcessName;
}
catch
{
}
}
}
catch (Exception ex)
{
LogService.Warn("프로세스 목록 갱신 실패: " + ex.Message);
}
try
{
ProcessStartInfo startInfo = new ProcessStartInfo("netstat", "-ano")
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
using Process process2 = Process.Start(startInfo);
if (process2 != null)
{
string text = process2.StandardOutput.ReadToEnd();
process2.WaitForExit(2000);
string[] array = text.Split('\n');
foreach (string text2 in array)
{
string[] array2 = text2.Trim().Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (array2.Length < 5 || !int.TryParse(array2[^1], out var result))
{
continue;
}
string text3 = array2[1];
int num = text3.LastIndexOf(':');
if (num >= 0)
{
string text4 = text3;
int num2 = num + 1;
if (int.TryParse(text4.Substring(num2, text4.Length - num2), out var result2))
{
_pidMap.TryAdd(result2, result);
}
}
}
}
}
catch (Exception ex2)
{
LogService.Warn("netstat 실행 실패: " + ex2.Message);
}
_cacheExpiry = DateTime.Now.AddSeconds(5.0);
}
private static string GetProcessNameForPort(int port)
{
int pidForPort = GetPidForPort(port);
string value;
return (pidForPort > 0 && _procCache.TryGetValue(pidForPort, out value)) ? value : "알 수 없음";
}
private static int GetPidForPort(int port)
{
int value;
return _pidMap.TryGetValue(port, out value) ? value : (-1);
}
}