This repo is archived. You can view files and clone it, but cannot push or open issues or pull requests.
SXS20240115/SRC/MESAgent/MESAutoLoader/AutoLoaderService_Base/AutoLoaderService.cs

662 lines
26 KiB
C#
Raw Permalink Normal View History

2024-01-23 14:01:04 +08:00
using System;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.ServiceProcess;
using System.Xml;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
namespace AutoLoaderService_Base
{
public class Service1 : ServiceBase
{
// //建立AutoLoaderJob所使用的DataTable
private DataTable dtAutoLoaderJob;
// //Trace & Log
private bool blnLogFile = false;
private bool blnTraceFile = false;
private string strLogFilePath = string.Empty;
private string strTraceFilePath = string.Empty;
// //取出Job檔案路徑
private string strJobFilePath = "";
// 取回JOB LIST 到 JOB QUEUE的時間間隔(單位:分鐘) '20211015 13871,修正為*1000是秒, *60才是分鐘
private int MonitorjoblistDuration = (int)Math.Round(Conversions.ToDouble(modWIN.GetAppSettings("MonitorjoblistDuration")) * 1000d *60d );
// 到JOB QUEUE 檢查是否有要執行的job的時間間隔(單位:分鐘) '20211015 13871,修正為*1000是秒, , *60才是分鐘
private int MonitorQueueDuration = (int)Math.Round(Conversions.ToDouble(modWIN.GetAppSettings("MonitorQueueDuration")) * 1000d * 60d);
private const string JOB_FILE_NAME = "AutoLoaderJob_Base.xml";
#region
public Service1() : base()
{
// 此為元件設計工具所需的呼叫。
InitializeComponent();
// 在 InitializeComponent() 呼叫之後加入所有的初始化作業
}
// UserService 覆寫 Dispose 以清除元件清單。
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
// 處理序的主進入點
[MTAThread()]
public static void Main()
{
ServiceBase[] ServicesToRun;
// 在同一個處理序中可以執行多個 NT 服務; 若要在這個處理序中
// 加入另一項服務,請修改以下各行
// 以建立第二個服務物件。例如,
//
// ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
//
ServicesToRun = new ServiceBase[] { new Service1() };
//RunInteractive(ServicesToRun); //for debug
Run(ServicesToRun);
}
private static void RunInteractive(ServiceBase[] servicesToRun)
{
var onStartMethod = typeof(ServiceBase).GetMethod("OnStart", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
foreach (ServiceBase service in servicesToRun)
{
Console.Write("Starting {0}...", service.ServiceName);
onStartMethod.Invoke(service, new object[] { new string[] { } });
Console.Write("Started");
}
Console.WriteLine("Press any key to stop the services");
Console.ReadKey();
var onStopMethod = typeof(ServiceBase).GetMethod("OnStop", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
foreach (ServiceBase service in servicesToRun)
{
Console.Write("Stopping {0}...", service.ServiceName);
onStopMethod.Invoke(service, null);
Console.WriteLine("Stopped");
}
}
// 為元件設計工具的必要項
private System.ComponentModel.IContainer components;
// 注意: 以下為元件設計工具所需的程序
// 您可以使用元件設計工具進行修改,
// 請勿使用程式碼編輯器進行修改。
private System.Timers.Timer _TimerCheckJobList;
internal virtual System.Timers.Timer TimerCheckJobList
{
[MethodImpl(MethodImplOptions.Synchronized)]
get
{
return _TimerCheckJobList;
}
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
if (_TimerCheckJobList != null)
{
_TimerCheckJobList.Elapsed -= TimerCheckJobList_Elapsed;
}
_TimerCheckJobList = value;
if (_TimerCheckJobList != null)
{
_TimerCheckJobList.Elapsed += TimerCheckJobList_Elapsed;
}
}
}
private System.Timers.Timer _TimerCheckQueue;
internal virtual System.Timers.Timer TimerCheckQueue
{
[MethodImpl(MethodImplOptions.Synchronized)]
get
{
return _TimerCheckQueue;
}
[MethodImpl(MethodImplOptions.Synchronized)]
set
{
if (_TimerCheckQueue != null)
{
_TimerCheckQueue.Elapsed -= TimerCheckQueue_Elapsed;
}
_TimerCheckQueue = value;
if (_TimerCheckQueue != null)
{
_TimerCheckQueue.Elapsed += TimerCheckQueue_Elapsed;
}
}
}
[DebuggerStepThrough()]
private void InitializeComponent()
{
this._TimerCheckJobList = new System.Timers.Timer();
this._TimerCheckQueue = new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this._TimerCheckJobList)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this._TimerCheckQueue)).BeginInit();
//
// _TimerCheckJobList
//
this._TimerCheckJobList.Interval = 2000D;
this._TimerCheckJobList.Elapsed += new System.Timers.ElapsedEventHandler(this.TimerCheckJobList_Elapsed);
//
// _TimerCheckQueue
//
this._TimerCheckQueue.Interval = 3000D;
this._TimerCheckQueue.Elapsed += new System.Timers.ElapsedEventHandler(this.TimerCheckQueue_Elapsed);
//
// Service1
//
this.ServiceName = "MES AutoLoader Service (Production)";
((System.ComponentModel.ISupportInitialize)(this._TimerCheckJobList)).EndInit();
((System.ComponentModel.ISupportInitialize)(this._TimerCheckQueue)).EndInit();
}
#endregion
protected override void OnStart(string[] args)
{
// // 在此加入啟動服務的程式碼,這個方法必須設定已啟動的
// // 事項,否則可能導致服務無法工作。
// //取出是否需要將Trace的Log產生檔案
try
{
string strTemp = modWIN.GetAppSettings("JobFilePath") == null ? "" : modWIN.GetAppSettings("JobFilePath");
if (strTemp.Contains(":"))
strJobFilePath = Path.Combine(strTemp, JOB_FILE_NAME);
else
strJobFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strTemp, JOB_FILE_NAME);
}
catch (Exception)
{
strJobFilePath = JOB_FILE_NAME;
modWIN.WriteLog("defaultPath" + strJobFilePath, iMESLog.iMESLogLevel.Trace);
}
try
{
blnTraceFile = bool.Parse(modWIN.GetAppSettings("TraceFile"));
}
catch (Exception ex)
{
blnTraceFile = false;
}
// //取出是否需要將Fail的Log產生檔案
try
{
blnLogFile = bool.Parse(modWIN.GetAppSettings("LogFile"));
}
catch (Exception ex)
{
blnLogFile = false;
}
// //取出是Trace產生檔案路徑
try
{
if (blnTraceFile == true)
{
string strTemp = modWIN.GetAppSettings("TraceFilePath") == null ? "" : modWIN.GetAppSettings("TraceFilePath");
if (strTemp.Contains(":"))
strTraceFilePath = strTemp;
else
strTraceFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strTemp);
}
}
catch (Exception ex)
{
// 暫時
strTraceFilePath = @"C:\Temp\";
}
// //取出是Log產生檔案路徑
try
{
if (blnLogFile == true)
{
string strTemp = modWIN.GetAppSettings("LogFilePath") == null ? "" : modWIN.GetAppSettings("LogFilePath");
if (strTemp.Contains(":"))
strLogFilePath = strTemp;
else
strLogFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strTemp);
}
}
catch (Exception ex)
{
// 暫時
strLogFilePath = string.Empty;
}
if (blnTraceFile == true)
{
//funWriteTxtFile("Service Starting...");
modWIN.WriteLog("Service Starting...", iMESLog.iMESLogLevel.Trace);
}
dtAutoLoaderJob = new DataTable("AutoLoaderJob");
// 2021/8/10 Steven Mantis: 0097110: AuoLoader Service 錯誤攔截優化
try
{
//改成用读取节点的方式获取xml值
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strJobFilePath);
XmlNodeList autoLoaderJobList = xmlDoc.GetElementsByTagName("AutoLoaderJob");
foreach (XmlNode autoLoaderJobNode in autoLoaderJobList)
{
DataRow drAdd;
drAdd = dtAutoLoaderJob.NewRow();
foreach (XmlNode item in autoLoaderJobNode.ChildNodes)
{
if (!dtAutoLoaderJob.Columns.Contains(item.Name))
{
dtAutoLoaderJob.Columns.Add(item.Name);
}
drAdd[item.Name] = funLoadXml(autoLoaderJobNode, item.Name);
}
dtAutoLoaderJob.Rows.Add(drAdd);
}
//dtAutoLoaderJob.ReadXmlSchema(strJobFilePath);
//dtAutoLoaderJob.ReadXml(strJobFilePath);
}
catch (Exception ex)
{
modWIN.WriteLog("[" + Strings.Format(DateTime.Now, "yyyy/MM/dd HH:mm:ss") + "]" + "AutoLoaderJob_Base.xml不存在或格式不正確,請確認" + Constants.vbCrLf, iMESLog.iMESLogLevel.Error );
//modAutoLoader.WriteLogFile(strLogFilePath, "[" + Strings.Format(DateTime.Now, "yyyy/MM/dd HH:mm:ss") + "]" + "AutoLoaderJob_Base.xml不存在或格式不正確,請確認" + Constants.vbCrLf);
}
// //Init Status = 0
int i = 0;
var loopTo = dtAutoLoaderJob.Rows.Count - 1;
for (i = 0; i <= loopTo; i++)
{
dtAutoLoaderJob.Rows[i].BeginEdit();
dtAutoLoaderJob.Rows[i]["Status"] = 0;
dtAutoLoaderJob.Rows[i].EndEdit();
}
// '//Init Process
// Call InitProcess()
// 每隔n分鐘, 取回一次JOB LIST 到 JOB QUEUE
TimerCheckJobList.Interval = MonitorjoblistDuration;
TimerCheckJobList.Enabled = true;
// 每隔n分鐘,到 JOB QUEUE 檢查是否有要執行的
TimerCheckQueue.Interval = MonitorQueueDuration;
TimerCheckQueue.Enabled = true;
}
protected override void OnStop()
{
// //在此加入停止服務所需執行的終止程式碼。
dtAutoLoaderJob.WriteXml(strJobFilePath);
dtAutoLoaderJob.Dispose();
TimerCheckJobList.Enabled = false;
TimerCheckQueue.Enabled = false;
if (blnTraceFile == true)
{
modWIN.WriteLog("Service Stopping...", iMESLog.iMESLogLevel.Trace);
//funWriteTxtFile("Service Stopping...");
}
}
private void TimerCheckJobList_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
// //............................
// //每一秒鐘檢查是否有Job要執行
// //............................
// Me.TimerCheckJobList.Enabled = False
if (blnTraceFile == true)
{
//funJobFile("Start CheckJobList");
modWIN.WriteLog("Start CheckJobList", iMESLog.iMESLogLevel.Trace);
}
// //變更需要執行的Job Status
funGetJob2Queue();
if (blnTraceFile == true)
{
modWIN.WriteLog("End CheckJobList", iMESLog.iMESLogLevel.Trace);
//funJobFile("End CheckJobList");
}
TimerCheckJobList.Enabled = true;
}
catch (Exception ex)
{
modWIN.WriteLog("CheckJobList fail"+ex.Message , iMESLog.iMESLogLevel.Error );
TimerCheckJobList.Enabled = true;
}
}
private void TimerCheckQueue_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
// //............................
// //每一秒鐘取出需要執行的Job
// //............................
// Me.TimerCheckQueue.Enabled = False
if (blnTraceFile == true)
{
modWIN.WriteLog("Start CheckQueue",iMESLog.iMESLogLevel.Trace );
// funQueueFile("Start CheckQueue");
}
// //執行Job
funRunJob();
if (blnTraceFile == true)
{
modWIN.WriteLog("End CheckQueue", iMESLog.iMESLogLevel.Trace);
//funQueueFile("End CheckQueue");
}
TimerCheckQueue.Enabled = true;
}
catch (Exception ex)
{
modWIN.WriteLog("CheckQueue fail:"+ ex.Message , iMESLog.iMESLogLevel.Error );
TimerCheckQueue.Enabled = true;
}
}
#region Private Function
/// <summary>
/// 将status 改为1 待执行
/// </summary>
public void funGetJob2Queue()
{
lock (this)
{
// //判斷目前的Job中是否需要排入執行
DataRow[] drSel;
int idx = 0;
var ArriveTime = DateTime.Now;
try
{
// //
drSel = dtAutoLoaderJob.Select("Status = 0"); // 未執行Job
var loopTo = drSel.Length - 1;
for (idx = 0; idx <= loopTo; idx++)
{
// 2023/4/21,Ning,129075: [博升] AutoLoader 日志报错, 執行頻率(Frequency)單位改為分鐘, 即秒*60
//if (Conversions.ToBoolean(Operators.ConditionalCompareObjectGreater(DateAndTime.DateDiff(DateInterval.Second, Conversions.ToDate(drSel[idx]["LastRunTime"]), ArriveTime), Conversions.ToInteger(drSel[idx]["Frequency"]) * 60, false)))
//If DateDiff(DateInterval.Second, drSel(idx)("LastRunTime"), ArriveTime) > (drSel(idx)("Frequency") * 60) Then
//检查上一次的时间与当配置的时间差
if (DateAndTime.DateDiff(DateInterval.Second, Convert.ToDateTime(drSel[idx]["LastRunTime"]), ArriveTime) > Convert.ToInt32(drSel[idx]["Frequency"]) * 60)
{
drSel[idx].BeginEdit();
drSel[idx]["Status"] = 1; // 待執行Job
drSel[idx].EndEdit();
if (blnTraceFile == true)
{
//funJobFile(Conversions.ToString("JobNo:" +
// drSel[idx]["JobNo"] + " -- " + drSel[idx]["LastRunTime"] + " ~ " + ArriveTime + " = " + DateAndTime.DateDiff(DateInterval.Second, Conversions.ToDate(drSel[idx]["LastRunTime"]), ArriveTime)));
modWIN.WriteLog(Conversions.ToString("JobNo:" +
drSel[idx]["JobNo"] + " -- " + drSel[idx]["LastRunTime"] + " ~ " + ArriveTime + " = " + DateAndTime.DateDiff(DateInterval.Second, Conversions.ToDate(drSel[idx]["LastRunTime"]), ArriveTime)), iMESLog.iMESLogLevel.Trace);
}
}
}
}
catch (Exception ex)
{
//modAutoLoader.WriteLogFile(strLogFilePath, ex.Message + Constants.vbCrLf);
modWIN.WriteLog("funGetJob2Queue fail :" +strLogFilePath + ex.Message, iMESLog.iMESLogLevel.Error );
}
finally
{
// //
drSel = null;
}
}
}
public void funRunJob()
{
lock (this)
{
DataRow[] drSel;
int idx = 0;
var ArriveTime = DateTime.Now;
try
{
drSel = dtAutoLoaderJob.Select("Status = 1"); // 待執行Job
if (blnTraceFile == true)
{
// funQueueFile("Queue Count:" + drSel.Length);
modWIN.WriteLog("Queue Count:" + drSel.Length, iMESLog.iMESLogLevel.Trace);
}
var loopTo = drSel.Length - 1;
for (idx = 0; idx <= loopTo; idx++)
{
if (blnTraceFile == true)
{
// funWriteTxtFile("Start Job..." + drSel[idx]["JobNo"].ToString());
modWIN.WriteLog("Start Job..." + drSel[idx]["JobNo"].ToString(), iMESLog.iMESLogLevel.Trace);
}
// //將Job改成執行中
drSel[idx].BeginEdit();
drSel[idx]["Status"] = 2; // 執行中
drSel[idx].EndEdit();
if (blnTraceFile == true)
{
// funWriteTxtFile("Status:Running");
modWIN.WriteLog("Status:Running", iMESLog.iMESLogLevel.Trace);
}
// //建立傳入執行緒之參數物件
var objJobData = new modAutoLoader.SomeStateType();
objJobData.SomeState(drSel[idx]["JobExecutionFile"].ToString(), drSel[idx]["JobNo"].ToString(), drSel[idx]["Jobfunction"].ToString(), drSel[idx]["SourcePath"].ToString(), drSel[idx]["DestinationPath"].ToString(), drSel[idx]["QueuePath"].ToString(), drSel[idx]["FailPath"].ToString(), strLogFilePath, Conversions.ToLong(drSel[idx]["SplitFileSize"].ToString()), Conversions.ToLong(drSel[idx]["SplitRecordsLimit"].ToString()), drSel[idx]["JobName"].ToString(), drSel[idx]["JobFunction"].ToString(), drSel[idx]["Parameter1"].ToString(), drSel[idx]["Parameter2"].ToString(), drSel[idx]["Parameter3"].ToString(), drSel[idx]["Parameter4"].ToString(), drSel[idx]["Parameter5"].ToString(), drSel[idx]["Parameter6"].ToString(), drSel[idx]["Parameter7"].ToString(), drSel[idx]["Parameter8"].ToString(), drSel[idx]["Parameter9"].ToString(), drSel[idx]["Parameter10"].ToString());
// //開始執行
if (System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(modAutoLoader.funProcessJob), objJobData) == false)
{
modWIN.WriteLog("Job Fail:" + drSel[idx]["JobNo"].ToString(), iMESLog.iMESLogLevel.Trace);
// //funWriteTxtFile("Job Fail:" & drSel(idx)("JobNo").ToString)
}
// //將Job改成Queue
drSel[idx].BeginEdit();
drSel[idx]["Status"] = 0; // Queue
drSel[idx]["LastRunTime"] = Strings.Format(ArriveTime, "yyyy/MM/dd HH:mm:ss"); // 執行時間
drSel[idx].EndEdit();
if (blnTraceFile == true)
{
modWIN.WriteLog("Status:Complete," +"End Job..." + drSel[idx]["JobNo"].ToString(), iMESLog.iMESLogLevel.Trace);
//funWriteTxtFile("Status:Complete");
//funWriteTxtFile("End Job..." + drSel[idx]["JobNo"].ToString());
}
}
}
catch (Exception ex)
{
// //
drSel = dtAutoLoaderJob.Select("Status = 2"); // 執行中
var loopTo = drSel.Length - 1;
for (idx = 0; idx <= loopTo; idx++)
{
// //將Job改成待執行
drSel[idx].BeginEdit();
drSel[idx]["Status"] = 0; // Queue
drSel[idx]["LastRunTime"] = Strings.Format(ArriveTime, "yyyy/MM/dd HH:mm:ss"); // 執行時間
drSel[idx].EndEdit();
}
modWIN.WriteLog(ex.Message + Constants.vbCrLf, iMESLog.iMESLogLevel.Error );
//modAutoLoader.WriteLogFile(strLogFilePath, ex.Message + Constants.vbCrLf);
}
finally
{
drSel = null;
}
}
}
public void InitProcess()
{
try
{
// //開始執行
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(modAutoLoader.funInitProcess));
}
catch (Exception ex)
{
}
}
private string funWriteTxtFile(string WriteTxt)
{
try
{
string path = Path.Combine(strTraceFilePath, Strings.Format(DateTime.Now, "yyyyMMdd").ToString() + "_T3.Log");
if (!string.IsNullOrEmpty(strTraceFilePath) && !Directory.Exists(strTraceFilePath))
Directory.CreateDirectory(strTraceFilePath);
lock (this)
{
var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var w = new StreamWriter(fs);
w.BaseStream.Seek(0L, SeekOrigin.End);
w.WriteLine("日期時間:" + Strings.Format(DateTime.Now, "yyyy/MM/dd HH:mm:ss") + "--" + WriteTxt);
w.Close();
fs.Close();
}
}
catch (Exception ex)
{
}
return default(string);
}
private string funQueueFile(string WriteTxt)
{
try
{
string path = Path.Combine(strTraceFilePath, Strings.Format(DateTime.Now, "yyyyMMdd").ToString() + "_T1.Log");
if (!string.IsNullOrEmpty(strTraceFilePath) && !Directory.Exists(strTraceFilePath))
Directory.CreateDirectory(strTraceFilePath);
lock (this)
{
var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var w = new StreamWriter(fs);
w.BaseStream.Seek(0L, SeekOrigin.End);
w.WriteLine("日期時間:" + Strings.Format(DateTime.Now, "yyyy/MM/dd HH:mm:ss") + "--" + WriteTxt);
w.Close();
fs.Close();
}
}
catch (Exception ex)
{
}
return default(string);
}
private string funJobFile(string WriteTxt)
{
try
{
string path = Path.Combine(strTraceFilePath, Strings.Format(DateTime.Now, "yyyyMMdd").ToString() + "_T2.Log");
if (!string.IsNullOrEmpty(strTraceFilePath) && !Directory.Exists(strTraceFilePath))
Directory.CreateDirectory(strTraceFilePath);
lock (this)
{
var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
var w = new StreamWriter(fs);
w.BaseStream.Seek(0L, SeekOrigin.End);
w.WriteLine("日期時間:" + Strings.Format(DateTime.Now, "yyyy/MM/dd HH:mm:ss") + "--" + WriteTxt);
w.Close();
fs.Close();
}
}
catch (Exception ex)
{
}
return default(string);
}
#endregion
private string funLoadXml(XmlNode autoLoaderJobNode, string tag)
{
if (autoLoaderJobNode.SelectNodes(tag).Count > 0)
{
return autoLoaderJobNode.SelectSingleNode(tag).InnerText;
}
else
{
return "";
}
}
}
}