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 Microsoft.Owin.Hosting; 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(); })); } }); } } } }