using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Net;
using System.IO.Compression;
using System.IO;
using FCOMMON;
using System.Diagnostics;
namespace Project.Dialog
{
public partial class fSystemCheck : Form
{
private Timer checkTimer;
public bool environmentCheckCompleted = false;
public fSystemCheck()
{
InitializeComponent();
// 폼 설정
this.Text = "GroupWare 시작 중...";
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.ControlBox = false;
this.ShowInTaskbar = false;
this.TopMost = true;
// 타이머 설정
checkTimer = new Timer();
checkTimer.Interval = 100; // 0.1초
checkTimer.Tick += CheckTimer_Tick;
checkTimer.Start();
this.Load += FSystemCheck_Load;
}
private void FSystemCheck_Load(object sender, EventArgs e)
{
// 환경 체크 시작
this.Show();
Application.DoEvents();
Task.Run(() => PerformEnvironmentCheck());
}
private void SafeInvoke(Action action)
{
if (this.IsHandleCreated)
{
if (this.InvokeRequired)
this.Invoke(action);
else
action();
}
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
checkTimer?.Stop();
checkTimer?.Dispose();
if (components != null)
{
components.Dispose();
}
}
private void CheckTimer_Tick(object sender, EventArgs e)
{
if (environmentCheckCompleted)
{
checkTimer.Stop();
this.Hide();
// fWarning 폼 닫기
this.Close();
}
}
///
/// 실행환경 체크 수행
///
private async void PerformEnvironmentCheck()
{
try
{
// UI 업데이트
this.Invoke(new Action(() => {
label1.Text = "🔍 실행환경을 검사하고 있습니다...";
}));
await Task.Delay(500);
// 1. Pub 초기화
SafeInvoke(() => {
label1.Text = "⚙️ 시스템 초기화 중...";
});
Pub.init();
await Task.Delay(300);
// 0. WebView2Runtime 압축해제 체크
SafeInvoke(() => {
label1.Text = "🌐 WebView2 Runtime 확인 중...";
});
await CheckAndExtractWebView2Runtime();
// 2. WebView2 초기화 (메인 스레드에서 실행)
SafeInvoke(() => {
label1.Text = "🌐 WebView2 초기화 중...";
try
{
Pub.InitializeWebView2();
}
catch (Exception ex)
{
// COM 스레드 모드 오류 처리
if (ex.Message.Contains("RPC_E_CHANGED_MODE") || ex.Message.Contains("스레드 모드"))
{
Console.WriteLine($"WebView2 초기화 COM 오류 (무시됨): {ex.Message}");
// 이 오류는 무시하고 계속 진행 (fMain에서 다시 시도)
}
else
{
Console.WriteLine($"WebView2 초기화 오류: {ex.Message}");
// 다른 심각한 오류는 무시하고 계속 (fMain에서 처리)
}
}
});
await Task.Delay(500);
// 3. 데이터베이스 접속 정보 확인
SafeInvoke(() => {
label1.Text = "🗄️ 데이터베이스 연결 확인 중...";
});
CheckDatabaseConnection();
await Task.Delay(300);
//// 4. 포트 7979 사용 여부 체크
//SafeInvoke(() => {
// label1.Text = "🔌 포트 7979 상태 확인 중...";
//});
//CheckPort7979InUse();
//await Task.Delay(300);
// 5. 바코드 설정
SafeInvoke(() => {
label1.Text = "📊 바코드 설정 초기화 중...";
});
InitializeBarcodeSettings();
await Task.Delay(300);
// 6. 웹서버 시작 시뮬레이션 (실제 시작은 fMain에서)
SafeInvoke(() => {
label1.Text = "🚀 웹서버 준비 중...";
});
await Task.Delay(500);
// 7. SqlServerTypes 라이브러리 로드
SafeInvoke(() => {
label1.Text = "📚 Reporting System 로드 중...";
});
SqlServerTypes.Utilities.LoadNativeAssemblies(AppDomain.CurrentDomain.BaseDirectory);
await Task.Delay(300);
// 완료
SafeInvoke(() => {
label1.Text = "✅ 실행환경 검사 완료";
});
await Task.Delay(500);
environmentCheckCompleted = true;
}
catch (Exception ex)
{
var st = new System.Diagnostics.StackTrace(ex, true);
var frame = st.GetFrame(0);
var fileName = frame?.GetFileName() ?? "Unknown";
var lineNumber = frame?.GetFileLineNumber() ?? 0;
var errorMsg = $"실행환경 검사 중 오류가 발생했습니다:\n{ex.Message}\n\n파일: {System.IO.Path.GetFileName(fileName)}\n줄수: {lineNumber}";
SafeInvoke(() => {
MessageBox.Show(errorMsg, "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
});
}
}
///
/// 데이터베이스 연결 확인
///
private void CheckDatabaseConnection()
{
Pub.dbinfo = DatabaseConnectionString.Utility.Read();
if (Pub.dbinfo.IsValid == false)
{
this.Invoke(new Action(() => {
this.Visible = false;
MessageBox.Show("데이터베이스 접속정보가 존재하지 않습니다\n개발부서에 접속정보를 문의하세요",
"Alert", MessageBoxButtons.OK, MessageBoxIcon.Error);
Pub.dbinfo = DatabaseConnectionString.Utility.ShowForm();
if (Pub.dbinfo.IsValid == false)
{
MessageBox.Show("데이터 베이스 정보가 없습니다\n프로그램이 정상 작동하지 않을 수 있습니다",
"Alert", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.Visible = true;
}));
}
Properties.Settings.Default["CS"] = Pub.dbinfo.ToString();
Properties.Settings.Default["gwcs"] = Pub.dbinfo.ToString();
}
///
/// 포트 7979가 이미 사용중인지 체크하고 경고 표시
///
private void CheckPort7979InUse()
{
try
{
// 현재 사용중인 TCP 포트 목록 가져오기
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
IPEndPoint[] tcpListeners = ipGlobalProperties.GetActiveTcpListeners();
// 포트 7979가 이미 사용중인지 확인
bool port7979InUse = false;
// TCP 연결 중에서 7979 포트 사용하는지 확인
foreach (var tcpInfo in tcpConnInfoArray)
{
if (tcpInfo.LocalEndPoint.Port == 7979)
{
port7979InUse = true;
break;
}
}
// TCP 리스너 중에서 7979 포트 사용하는지 확인
if (!port7979InUse)
{
foreach (var listener in tcpListeners)
{
if (listener.Port == 7979)
{
port7979InUse = true;
break;
}
}
}
// 포트가 이미 사용중이면 경고 메시지 표시
if (port7979InUse)
{
this.Invoke(new Action(() => {
string warningMessage = "⚠️ 경고: 포트 7979가 이미 사용 중입니다!\n\n" +
"다른 프로그램이 포트 7979를 사용하고 있어서\n" +
"웹 서버가 정상적으로 시작되지 않을 수 있습니다.\n\n" +
"해결방법:\n" +
"1. 다른 GroupWare 프로그램을 종료하세요\n" +
"2. 작업관리자에서 관련 프로세스를 종료하세요\n" +
"3. 컴퓨터를 재시작하세요";
MessageBox.Show(warningMessage, "포트 충돌 경고", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}));
FCOMMON.Pub.log.Add($"포트 7979가 이미 사용 중입니다. 웹서버 시작에 문제가 발생할 수 있습니다.");
}
}
catch (Exception ex)
{
// 포트 체크 중 오류가 발생해도 프로그램 실행은 계속
FCOMMON.Pub.log.AddE($"포트 7979 체크 중 오류 발생: {ex.Message}");
Console.WriteLine($"Port check error: {ex.Message}");
}
}
///
/// 바코드 설정 초기화
///
private void InitializeBarcodeSettings()
{
Pub.barcode = new Device.Barcode();
if (!Pub.setting.Barcode.isEmpty())
Pub.barcode.PortName = Pub.setting.Barcode;
FCOMMON.info.camIndex = Pub.setting.CamIndex;
}
///
/// WebView2Runtime 압축해제 체크 및 실행
///
private async Task CheckAndExtractWebView2Runtime()
{
var fi = new System.IO.FileInfo("WebView2Runtime.zip");
if (!fi.Exists) return;
var existlen = 0;
var webruntimepath = new System.IO.DirectoryInfo("WebView2Runtime");
if (webruntimepath.Exists)
{
var filen = new System.IO.FileInfo("WebView2Runtime\\version.txt");
if (filen.Exists)
{
var verstr = System.IO.File.ReadAllText(filen.FullName);
int.TryParse(verstr, out existlen);
}
}
if (existlen != fi.Length)
{
this.Invoke(new Action(() => {
label1.Text = "📦 WebView2Runtime 압축해제 중...";
}));
await Task.Run(() => {
// fUnZip 폼을 메인 스레드에서 생성
fUnZip fprogress = null;
this.Invoke(new Action(() => {
fprogress = new fUnZip();
fprogress.TopMost = true;
fprogress.Show();
Application.DoEvents();
}));
try
{
if (webruntimepath.Exists)
{
this.Invoke(new Action(() => {
fprogress.label1.Text = "기존폴더삭제";
Application.DoEvents();
}));
webruntimepath.Delete(true);
}
var diruntime = new System.IO.DirectoryInfo("runtimes");
if (diruntime.Exists) diruntime.Delete(true);
webruntimepath.Create();
diruntime.Create();
using (var archive = ZipFile.OpenRead(fi.FullName))
{
int totalFiles = archive.Entries.Count;
int currentFile = 0;
long totalSize = archive.Entries.Sum(e => e.Length);
long extractedSize = 0;
foreach (var entry in archive.Entries)
{
currentFile++;
extractedSize += entry.Length;
int progress = (int)((extractedSize * 100) / totalSize);
this.Invoke(new Action(() => {
fprogress.label1.Text = $"압축 해제 중... ({currentFile}/{totalFiles})";
fprogress.label2.Text = $"{entry.FullName} ({progress}%)";
fprogress.progressBar1.Value = progress;
Application.DoEvents();
}));
string destinationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, entry.FullName);
string destinationDir = Path.GetDirectoryName(destinationPath);
if (!Directory.Exists(destinationDir))
Directory.CreateDirectory(destinationDir);
if (entry.Length > 0)
entry.ExtractToFile(destinationPath, true);
}
}
System.IO.File.WriteAllText("WebView2Runtime\\version.txt", fi.Length.ToString());
}
catch (Exception ex)
{
this.Invoke(new Action(() => {
fprogress.Hide();
MessageBox.Show($"WebView2 Runtime 압축 해제 중 오류가 발생했습니다: {ex.Message}",
"오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
}));
}
finally
{
this.Invoke(new Action(() => {
fprogress.Dispose();
}));
}
});
}
}
}
}