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
2024-01-23 14:01:04 +08:00

662 lines
26 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 "";
}
}
}
}