feat(service): Console_SendMail을 Windows 서비스로 변환

- MailService.cs 추가: ServiceBase 상속받는 Windows 서비스 클래스
- Program.cs 수정: 서비스/콘솔 모드 지원, 설치/제거 기능 추가
- 프로젝트 설정: System.ServiceProcess 참조 추가
- 배치 파일 추가: 서비스 설치/제거/콘솔실행 스크립트

주요 기능:
- Windows 서비스로 백그라운드 실행
- 명령행 인수로 모드 선택 (-install, -uninstall, -console)
- EventLog를 통한 서비스 로깅
- 안전한 서비스 시작/중지 처리

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ChiKyun Kim
2025-09-11 09:08:40 +09:00
parent 777fcd5d89
commit 6bd4f84192
49 changed files with 46882 additions and 102 deletions

View File

@@ -0,0 +1,293 @@
using FCM0000;
using Microsoft.Owin;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace Project.Web.Controllers
{
public class KuntaeController : BaseController
{
[HttpGet]
public HttpResponseMessage GetList(string sd = null, string ed = null)
{
var sql = string.Empty;
sql = "select idx,gcode,uid,dbo.getUserName(uid) as uname,cate,sdate,edate,term,termdr,drtime,DrTimePMS,crtime,title,contents, tag, extcate,extidx, wuid,wdate" +
" from Holyday" +
" where gcode = @gcode" +
" and uid = @uid" +
" and sdate between @sd and @ed" +
" order by wdate desc";
var cs = Properties.Settings.Default.gwcs;// "Data Source=K4FASQL.kr.ds.amkor.com,50150;Initial Catalog=EE;Persist Security Info=True;User ID=eeadm;Password=uJnU8a8q&DJ+ug-D!";
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
cmd.Parameters.AddWithValue("uid", FCOMMON.info.Login.no);
// 날짜 파라미터가 없으면 기본값 사용 (현재 월)
var startDate = !string.IsNullOrEmpty(sd) ? sd : DateTime.Now.AddDays(-7).ToString("yyyy-MM-dd");
var endDate = !string.IsNullOrEmpty(ed) ? ed : DateTime.Now.ToString("yyyy-MM-dd");
cmd.Parameters.AddWithValue("sd", startDate);
cmd.Parameters.AddWithValue("ed", endDate);
var da = new System.Data.SqlClient.SqlDataAdapter(cmd);
var dt = new System.Data.DataTable();
da.Fill(dt);
da.Dispose();
cmd.Dispose();
cn.Dispose();
var txtjson = JsonConvert.SerializeObject(dt, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var resp = new HttpResponseMessage()
{
Content = new StringContent(
txtjson,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
[HttpGet]
public HttpResponseMessage Index()
{
// 직접 파일을 읽어서 반환
var filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot", "kuntae", "index.html");
var contents = string.Empty;
if (System.IO.File.Exists(filePath))
{
contents = System.IO.File.ReadAllText(filePath, System.Text.Encoding.UTF8);
}
else
{
// 파일이 없으면 404 에러 페이지 또는 기본 메시지
contents = "<html><body><h1>404 - File Not Found</h1><p>The requested file was not found: " + filePath + "</p></body></html>";
}
var resp = new HttpResponseMessage()
{
Content = new StringContent(
contents,
System.Text.Encoding.UTF8,
"text/html")
};
return resp;
}
[HttpPost]
public HttpResponseMessage Insert([FromBody] KuntaeModel model)
{
try
{
var sql = @"INSERT INTO Holyday (gcode, uid, cate, sdate, edate, term, termdr, drtime, DrTimePMS, crtime, title, contents, tag, extcate, extidx, wuid, wdate)
VALUES (@gcode, @uid, @cate, @sdate, @edate, @term, @termdr, @drtime, @DrTimePMS, @crtime, @title, @contents, @tag, @extcate, @extidx, @wuid, @wdate)";
var cs = Properties.Settings.Default.gwcs;
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
cmd.Parameters.AddWithValue("uid", FCOMMON.info.Login.no);
cmd.Parameters.AddWithValue("cate", (object)model.cate ?? DBNull.Value);
cmd.Parameters.AddWithValue("sdate", model.sdate);
cmd.Parameters.AddWithValue("edate", (object)model.edate ?? DBNull.Value);
cmd.Parameters.AddWithValue("term", (object)model.term ?? DBNull.Value);
cmd.Parameters.AddWithValue("termdr", (object)model.termdr ?? DBNull.Value);
cmd.Parameters.AddWithValue("drtime", (object)model.drtime ?? DBNull.Value);
cmd.Parameters.AddWithValue("DrTimePMS", (object)model.DrTimePMS ?? DBNull.Value);
cmd.Parameters.AddWithValue("crtime", (object)model.crtime ?? DBNull.Value);
cmd.Parameters.AddWithValue("title", (object)model.title ?? DBNull.Value);
cmd.Parameters.AddWithValue("contents", (object)model.contents ?? DBNull.Value);
cmd.Parameters.AddWithValue("tag", (object)model.tag ?? DBNull.Value);
cmd.Parameters.AddWithValue("extcate", (object)model.extcate ?? DBNull.Value);
cmd.Parameters.AddWithValue("extidx", (object)model.extidx ?? DBNull.Value);
cmd.Parameters.AddWithValue("wuid", FCOMMON.info.Login.no);
cmd.Parameters.AddWithValue("wdate", DateTime.Now);
cn.Open();
var result = cmd.ExecuteNonQuery();
cn.Close();
cmd.Dispose();
cn.Dispose();
var response = new { success = true, message = "근태가 추가되었습니다." };
var json = JsonConvert.SerializeObject(response);
return new HttpResponseMessage()
{
Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json")
};
}
catch (Exception ex)
{
var response = new { success = false, message = "근태 추가 중 오류가 발생했습니다: " + ex.Message };
var json = JsonConvert.SerializeObject(response);
return new HttpResponseMessage()
{
Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json")
};
}
}
[HttpPut]
public HttpResponseMessage Update([FromBody] KuntaeModel model)
{
try
{
var sql = @"UPDATE Holyday SET cate = @cate, sdate = @sdate, edate = @edate, term = @term, termdr = @termdr,
drtime = @drtime, DrTimePMS = @DrTimePMS, crtime = @crtime, title = @title, contents = @contents,
tag = @tag, extcate = @extcate, extidx = @extidx
WHERE gcode = @gcode AND uid = @uid AND idx = @idx";
var cs = Properties.Settings.Default.gwcs;
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
cmd.Parameters.AddWithValue("uid", FCOMMON.info.Login.no);
cmd.Parameters.AddWithValue("cate", (object)model.cate ?? DBNull.Value);
cmd.Parameters.AddWithValue("sdate", model.sdate);
cmd.Parameters.AddWithValue("edate", (object)model.edate ?? DBNull.Value);
cmd.Parameters.AddWithValue("term", (object)model.term ?? DBNull.Value);
cmd.Parameters.AddWithValue("termdr", (object)model.termdr ?? DBNull.Value);
cmd.Parameters.AddWithValue("drtime", (object)model.drtime ?? DBNull.Value);
cmd.Parameters.AddWithValue("DrTimePMS", (object)model.DrTimePMS ?? DBNull.Value);
cmd.Parameters.AddWithValue("crtime", (object)model.crtime ?? DBNull.Value);
cmd.Parameters.AddWithValue("title", (object)model.title ?? DBNull.Value);
cmd.Parameters.AddWithValue("contents", (object)model.contents ?? DBNull.Value);
cmd.Parameters.AddWithValue("tag", (object)model.tag ?? DBNull.Value);
cmd.Parameters.AddWithValue("extcate", (object)model.extcate ?? DBNull.Value);
cmd.Parameters.AddWithValue("extidx", (object)model.extidx ?? DBNull.Value);
cmd.Parameters.AddWithValue("idx", model.idx);
cn.Open();
var result = cmd.ExecuteNonQuery();
cn.Close();
cmd.Dispose();
cn.Dispose();
var response = new { success = true, message = "근태가 수정되었습니다." };
var json = JsonConvert.SerializeObject(response);
return new HttpResponseMessage()
{
Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json")
};
}
catch (Exception ex)
{
var response = new { success = false, message = "근태 수정 중 오류가 발생했습니다: " + ex.Message };
var json = JsonConvert.SerializeObject(response);
return new HttpResponseMessage()
{
Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json")
};
}
}
[HttpDelete]
public HttpResponseMessage Delete(string id)
{
try
{
var sql = "DELETE FROM Holyday WHERE gcode = @gcode AND uid = @uid AND idx = @idx";
var cs = Properties.Settings.Default.gwcs;
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
cmd.Parameters.AddWithValue("uid", FCOMMON.info.Login.no);
cmd.Parameters.AddWithValue("idx", id);
cn.Open();
var result = cmd.ExecuteNonQuery();
cn.Close();
cmd.Dispose();
cn.Dispose();
var response = new { success = true, message = "근태가 삭제되었습니다." };
var json = JsonConvert.SerializeObject(response);
return new HttpResponseMessage()
{
Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json")
};
}
catch (Exception ex)
{
var response = new { success = false, message = "근태 삭제 중 오류가 발생했습니다: " + ex.Message };
var json = JsonConvert.SerializeObject(response);
return new HttpResponseMessage()
{
Content = new StringContent(json, System.Text.Encoding.UTF8, "application/json")
};
}
}
}
public class KuntaeModel
{
/*
idx : 데이터고유번호
gcode : 그룹코드(데이터 그룹간 식별)
uid : 사원번호
cate : 근태구분
sdate : 시작일
edate : 종료일
term : 사용일
termdr : 발생일
drtime : 발생시간,
crtime : 사용시간
DrTimePMS : PMS등록시간
title : 제목
contents : 내용
tag : 입력방식특이사항(clipboard=클립보드에서붙여넣었다)
extcate : 외부에서생성된 경우 외부 출처
extidx : 외부출처인경우 데이터고유번호
wuid : 데이터기록자 사원번호
wdate : 데이터를기록한일시
*/
public int idx { get; set; } // 데이터고유번호
public string gcode { get; set; } // 그룹코드(데이터 그룹간 식별)
public string uid { get; set; } // 사원번호
public string uname { get; set; } // 성명
public string cate { get; set; } // 근태구분
public string sdate { get; set; } // 시작일
public string edate { get; set; } // 종료일
public string term { get; set; } // 사용일
public string termdr { get; set; } // 발생일
public string drtime { get; set; } // 발생시간
public string DrTimePMS { get; set; } // PMS등록시간
public string crtime { get; set; } // 사용시간
public string title { get; set; } // 제목
public string contents { get; set; } // 내용
public string tag { get; set; } // 입력방식특이사항
public string extcate { get; set; } // 외부에서생성된 경우 외부 출처
public string extidx { get; set; } // 외부출처인경우 데이터고유번호
public string wuid { get; set; } // 데이터기록자 사원번호
public string wdate { get; set; } // 데이터를기록한일시
}
}