- 월별근무표: 휴일/근무일 관리, 자동 초기화 - 메일양식: 템플릿 CRUD, To/CC/BCC 설정 - 그룹정보: 부서 관리, 비트 연산 기반 권한 설정 - 업무일지: 수정 성공 메시지 제거, 오늘 근무시간 필터링 수정 - 웹소켓 메시지 type 충돌 버그 수정 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
414 lines
16 KiB
C#
414 lines
16 KiB
C#
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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 실행환경 체크 수행
|
|
/// </summary>
|
|
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();
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 데이터베이스 연결 확인
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 포트 7979가 이미 사용중인지 체크하고 경고 표시
|
|
/// </summary>
|
|
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}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 바코드 설정 초기화
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// WebView2Runtime 압축해제 체크 및 실행
|
|
/// </summary>
|
|
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();
|
|
}));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|