diff --git a/DDUtilityApp/DDUtilityApp.csproj b/DDUtilityApp/DDUtilityApp.csproj
index 112416f..e9b17f7 100644
--- a/DDUtilityApp/DDUtilityApp.csproj
+++ b/DDUtilityApp/DDUtilityApp.csproj
@@ -35,7 +35,7 @@
index.htm
true
1
- 2025.04.09.1
+ 2025.04.24.1
false
true
true
diff --git a/DDUtilityApp/LOGPARSER/DATA/EisEquipment.cs b/DDUtilityApp/LOGPARSER/DATA/EisEquipment.cs
index 0fdb158..cea72bc 100644
--- a/DDUtilityApp/LOGPARSER/DATA/EisEquipment.cs
+++ b/DDUtilityApp/LOGPARSER/DATA/EisEquipment.cs
@@ -61,7 +61,7 @@ namespace DDUtilityApp.LOGPARSER.DATA
string value = string.Empty;
foreach(string name in this.DisplayNameOrder.Split(';'))
{
- value = this.PropertyGet(name);
+ value = this.PropertyGet(name).ToString();
if (!string.IsNullOrEmpty(value)) break;
}
return value;
diff --git a/DDUtilityApp/LOGPARSER/FrmLogParser.cs b/DDUtilityApp/LOGPARSER/FrmLogParser.cs
index 90a8d20..60d921c 100644
--- a/DDUtilityApp/LOGPARSER/FrmLogParser.cs
+++ b/DDUtilityApp/LOGPARSER/FrmLogParser.cs
@@ -794,7 +794,7 @@ namespace DDUtilityApp.LOGPARSER
string propertyName = values[0].Trim();
string valueB = values[1].Trim().Replace("'", "");
- string valueA = data.PropertyGet(propertyName);
+ string valueA = data.PropertyGet(propertyName).ToString();
if (valueA != valueB) flag = false;
}
diff --git a/DDUtilityApp/LOGPARSER/FrmLogParser03.cs b/DDUtilityApp/LOGPARSER/FrmLogParser03.cs
index ef66853..865a470 100644
--- a/DDUtilityApp/LOGPARSER/FrmLogParser03.cs
+++ b/DDUtilityApp/LOGPARSER/FrmLogParser03.cs
@@ -566,7 +566,7 @@ namespace DDUtilityApp.LOGPARSER
string propertyName = values[0].Trim();
string valueB = values[1].Trim().Replace("'", "");
- string valueA = data.PropertyGet(propertyName);
+ string valueA = data.PropertyGet(propertyName).ToString();
if (valueA != valueB) flag = false;
}
diff --git a/DDUtilityApp/LOGPARSER/PARSER/EisParser0.cs b/DDUtilityApp/LOGPARSER/PARSER/EisParser0.cs
index f9cfe68..7620515 100644
--- a/DDUtilityApp/LOGPARSER/PARSER/EisParser0.cs
+++ b/DDUtilityApp/LOGPARSER/PARSER/EisParser0.cs
@@ -609,11 +609,13 @@ namespace DDUtilityApp.LOGPARSER.PARSER
{
if (this.SECSDefine != null) this.SECSDefine.SetInformation(rootSECS);
this.LogString_Append(rootSECS.ToFullString());
+ string ceid = string.Empty;
// CEID
secsItem = rootSECS.GetItemByName("CEID").FirstOrDefault();
if (secsItem == null && rootSECS.ChildItems.Count == 3) secsItem = rootSECS[1];
standardData.Value = $"CEID: {secsItem.Value}" + (string.IsNullOrEmpty(secsItem.Description) ? "" : $" {secsItem.Description}");
+ ceid = secsItem.Value;
// LOTID
secsItems = rootSECS.GetItemByName("LOT_ID", "LOTID", "LotID", "LEFT_LOTID", "RIGHT_LOTID");
@@ -675,6 +677,15 @@ namespace DDUtilityApp.LOGPARSER.PARSER
standardData.ModuleID += item.Value;
}
+ // 308:ModuleIn, 309:ModuleOut 'Name' 항목을 추가한다.
+ if (new string[] { "308", "309" }.Contains(ceid))
+ secsItems = rootSECS.GetItemByName("NAME");
+ foreach (SECSItem item in secsItems)
+ {
+ if (!string.IsNullOrEmpty(standardData.ModuleID)) standardData.HostPanelID += " ";
+ standardData.ModuleID += item.Value;
+ }
+
this.SendStandardData.Add(standardData.SystemByte, standardData);
}
diff --git a/DDUtilityApp/MESDOWNLOADER/FrmServerLog.cs b/DDUtilityApp/MESDOWNLOADER/FrmServerLog.cs
index 1258bc5..122e7c3 100644
--- a/DDUtilityApp/MESDOWNLOADER/FrmServerLog.cs
+++ b/DDUtilityApp/MESDOWNLOADER/FrmServerLog.cs
@@ -7,6 +7,7 @@ using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -163,32 +164,40 @@ namespace DDUtilityApp.MESDOWNLOADER
DataRow[] rows = this.DSSetting.Tables["Item"].Select($"Server_Id='{server_Id}' AND name='{nameap}'");
foreach (DataRow row in rows)
{
- string url = row["url"] as string;
- string dir = row["dir"] as string;
- string conkey = row["conkey"] as string;
-
- string userId = this.GetUserIdFromConkey(conkey);
- string password = this.GetPasswordFromConkey(conkey);
- string currentPath = string.IsNullOrEmpty(subPath) ? dir : System.IO.Path.Combine(dir, subPath);
-
- FtpsClient.Initialize(url, userId, password);
- var files = FtpsClient.GetFtpsList(currentPath);
-
- foreach (var file in files)
+ try
{
- DataRow rowFile = this.DTFileInfo.NewRow();
- rowFile["nameap"] = nameap;
- rowFile["Name"] = file.Name;
- rowFile["FileName"] = file.Name;
- rowFile["Size"] = this.GetFileSize(file.Size, FileSizeType.MB);
- rowFile["Modified"] = file.Modified.ToLocalTime();
- rowFile["Type"] = file.Type;
- rowFile["url"] = url;
- rowFile["dir"] = dir;
- rowFile["subpath"] = subPath;
- rowFile["userId"] = userId;
- rowFile["password"] = password;
- this.DTFileInfo.Rows.Add(rowFile);
+ string url = row["url"] as string;
+ string dir = row["dir"] as string;
+ string conkey = row["conkey"] as string;
+
+ string userId = this.GetUserIdFromConkey(conkey);
+ string password = this.GetPasswordFromConkey(conkey);
+ string currentPath = string.IsNullOrEmpty(subPath) ? dir : System.IO.Path.Combine(dir, subPath);
+
+ FtpsClient.Initialize(url, userId, password);
+ var files = FtpsClient.GetFtpsList(currentPath);
+
+ foreach (var file in files)
+ {
+ DataRow rowFile = this.DTFileInfo.NewRow();
+ rowFile["nameap"] = nameap;
+ rowFile["Name"] = file.Name;
+ rowFile["FileName"] = file.Name;
+ rowFile["Size"] = this.GetFileSize(file.Size, FileSizeType.MB);
+ rowFile["Modified"] = file.Modified.ToLocalTime();
+ rowFile["Type"] = file.Type;
+ rowFile["url"] = url;
+ rowFile["dir"] = dir;
+ rowFile["subpath"] = subPath;
+ rowFile["userId"] = userId;
+ rowFile["password"] = password;
+ this.DTFileInfo.Rows.Add(rowFile);
+ }
+ }
+ catch
+ {
+ chk.Checked = false;
+ chk.Enabled = false;
}
}
}
@@ -484,15 +493,22 @@ namespace DDUtilityApp.MESDOWNLOADER
}
}
- ///
- /// XML 설정파일 로딩 및 CboxServer 셋팅
- ///
+ ///
+ /// XML 설정파일 로딩 및 CboxServer 셋팅
+ ///
private void SetCboxServer()
{
try
{
- string path = ConfigurationManager.AppSettings["BULK_VIEWER"];
- this.DSSetting = XmlToDsConverter.ConvertXmlToDataSet(path);
+ string srcFileName = ConfigurationManager.AppSettings["BULK_VIEWER"];
+ string myFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "DDUtility", "ViewList.xml");
+ if (!File.Exists(myFileName))
+ {
+ if (!File.Exists(srcFileName)) throw new FileNotFoundException($"Source file not found: {srcFileName}");
+ File.Copy(srcFileName, myFileName);
+ }
+
+ this.DSSetting = XmlToDsConverter.ConvertXmlToDataSet(myFileName);
if (this.DSSetting == null || this.DSSetting.Tables.Count < 1 || this.DSSetting.Tables.Contains("Server") == false)
{
MessageBox.Show("XML 데이터를 불러올 수 없습니다.", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
diff --git a/DDUtilityApp/Properties/AssemblyInfo.cs b/DDUtilityApp/Properties/AssemblyInfo.cs
index 729c747..48b5f94 100644
--- a/DDUtilityApp/Properties/AssemblyInfo.cs
+++ b/DDUtilityApp/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2025.04.09.1")]
-[assembly: AssemblyFileVersion("2025.04.09.1")]
+[assembly: AssemblyVersion("2025.04.24.1")]
+[assembly: AssemblyFileVersion("2025.04.24.1")]
diff --git a/JWH/EXTENSIONS/ExtensionReflection.cs b/JWH/EXTENSIONS/ExtensionReflection.cs
index 320ac91..1c629b4 100644
--- a/JWH/EXTENSIONS/ExtensionReflection.cs
+++ b/JWH/EXTENSIONS/ExtensionReflection.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
@@ -17,50 +19,74 @@ namespace JWH
public static bool IsDesignMode = LicenseManager.UsageMode == LicenseUsageMode.Designtime;
+ ///
+ /// 속성 정보를 캐싱하기 위한 사전입니다.
+ ///
+ private static readonly ConcurrentDictionary> PropertyCache =
+ new ConcurrentDictionary>();
+
+ ///
+ /// 주어진 타입의 속성 정보를 캐싱하여 반환합니다.
+ ///
+ /// 대상 타입
+ /// 속성 정보 사전
+ private static Dictionary GetCachedProperties(Type type)
+ {
+ return PropertyCache.GetOrAdd(type, t =>
+ t.GetProperties().ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase));
+ }
#region [ PropertiesCopy ] --------------------------------------------
///
- /// 현재객체의 속성값을 대상객체의 속성에 복사합니다
+ /// 현재 객체의 속성 값을 대상 객체의 속성에 복사합니다.
///
- ///
- /// 대상객체
+ /// 원본 객체
+ /// 대상 객체
+ /// 기존 값을 덮어쓸지 여부
public static void PropertiesCopy(this object sender, object dest, bool overwrite = true)
{
- try
+ if (sender == null) throw new ArgumentNullException(nameof(sender));
+ if (dest == null) throw new ArgumentNullException(nameof(dest));
+
+ var sourceProperties = GetCachedProperties(sender.GetType());
+ var destProperties = GetCachedProperties(dest.GetType());
+
+ foreach (var sourceProp in sourceProperties)
{
- foreach (PropertyInfo property in sender.GetType().GetProperties())
+ if (!destProperties.TryGetValue(sourceProp.Key, out var destProp)) continue;
+ if (!destProp.CanWrite) continue;
+
+ if (typeof(IList).IsAssignableFrom(sourceProp.Value.PropertyType))
{
- try
- {
- PropertyInfo destProp = dest.GetType().GetProperty(property.Name, property.PropertyType);
- if (destProp == null || property.GetType() != destProp.GetType()) continue;
- //if (!property.CanWrite) continue;
- if (!destProp.CanWrite) continue;
+ var sourceList = sourceProp.Value.GetValue(sender) as IList;
+ if (sourceList == null) continue;
- var destValue = destProp.GetValue(dest);
- if (overwrite == false && destValue != null) continue;
+ var destList = destProp.GetValue(dest) as IList ?? (IList)Activator.CreateInstance(sourceProp.Value.PropertyType);
+ if (overwrite) destList.Clear();
- destProp.SetValue(dest, property.GetValue(sender));
- }
- catch (Exception ex)
+ foreach (var item in sourceList)
{
- XLogger.Instance.Fatal(ex);
+ destList.Add(item);
}
+
+ destProp.SetValue(dest, destList);
+ }
+ else
+ {
+ var sourceValue = sourceProp.Value.GetValue(sender);
+ if (!overwrite && destProp.GetValue(dest) != null) continue;
+
+ destProp.SetValue(dest, sourceValue);
}
- }
- catch (Exception ex)
- {
- XLogger.Instance.Fatal(ex);
- throw ex;
}
}
///
- /// 현재객체의 속성값을 대상객체의 속성에 복사합니다
+ /// DataTable의 데이터를 대상 객체의 속성에 복사합니다.
///
- ///
- /// 대상객체
+ /// 원본 DataTable
+ /// 대상 객체
public static void PropertiesCopy(this DataTable sender, object dest)
{
try
@@ -83,7 +109,6 @@ namespace JWH
catch
{
// Object of type 'System.DBNull' cannot be converted to type 'System.String'.
- // XLogger.Instance.Warn(ex);
}
}
catch (Exception ex)
@@ -100,10 +125,10 @@ namespace JWH
}
///
- /// Dictionary의 값을 대상객체의 속성에 복사합니다.
+ /// Dictionary의 데이터를 대상 객체의 속성에 복사합니다.
///
- ///
- ///
+ /// 원본 Dictionary
+ /// 대상 객체
public static void PropertiesCopy(this Dictionary sender, object dest)
{
try
@@ -134,74 +159,150 @@ namespace JWH
#endregion
+ #region [ Property Set/Get ] ------------------------------------------
+
///
- /// value 값을 현재객체의 속성에 복사합니다.
+ /// 주어진 값을 현재 객체의 속성에 설정합니다.
///
- ///
- ///
- ///
+ /// 대상 객체
+ /// 속성 이름
+ /// 설정할 값
public static void PropertySet(this object sender, string name, object value)
{
- try
- {
- PropertyInfo property = sender.GetType().GetProperty(name);
- if (property == null)
- foreach (PropertyInfo item in sender.GetType().GetProperties())
- if (string.Compare(item.Name, name, true) == 0)
- {
- property = item;
- break;
- }
- if (property == null) return;
- if (property.PropertyType != value.GetType())
- {
- try
- { value = Convert.ChangeType(value, property.PropertyType); }
- catch
- { return; }
- }
+ PropertyInfo property;
+ GetCachedProperties(sender.GetType()).TryGetValue(name, out property);
+ if (property == null || !property.CanWrite) return;
- property.SetValue(sender, value);
- }
- catch (Exception ex)
+ if (value != null && property.PropertyType != value.GetType())
{
- XLogger.Instance.Fatal(ex);
- throw ex;
+ value = Convert.ChangeType(value, property.PropertyType);
}
+
+ property.SetValue(sender, value);
}
///
- /// 객체의 속성값을 반환합니다.
+ /// 객체의 특정 속성 값을 반환합니다.
///
- ///
- ///
- ///
- public static string PropertyGet(this object sender, string name)
+ /// 대상 객체
+ /// 속성 이름
+ /// 속성 값
+ public static object PropertyGet(this object sender, string name)
+ {
+ PropertyInfo property;
+ GetCachedProperties(sender.GetType()).TryGetValue(name, out property);
+ return property?.GetValue(sender);
+ }
+
+ #endregion
+
+ #region [ ToClass() ] -------------------------------------------------
+
+ ///
+ /// DataTable을 제네릭 객체 리스트로 변환합니다.
+ ///
+ /// 제네릭 객체 타입
+ /// 원본 DataTable
+ /// 제네릭 객체 배열
+ public static T[] ToClass(this DataTable dataTable) where T : class, new()
+ {
+ var properties = GetCachedProperties(typeof(T));
+ var list = new List();
+
+ foreach (DataRow row in dataTable.Rows)
+ {
+ var obj = new T();
+ foreach (var prop in properties)
+ {
+ if (!dataTable.Columns.Contains(prop.Key) || row[prop.Key] is DBNull) continue;
+
+ var value = Convert.ChangeType(row[prop.Key], prop.Value.PropertyType);
+ prop.Value.SetValue(obj, value);
+ }
+ list.Add(obj);
+ }
+
+ return list.ToArray();
+ }
+
+ /// 원본 객체 배열
+ /// 제네릭 객체 배열
+ public static T[] ToClass(this object[] srcArray) where T : class, new()
{
try
{
- PropertyInfo property = sender.GetType().GetProperty(name);
- if (property == null)
+ List list = new List();
+ var desProperties = GetCachedProperties(typeof(T));
+
+ foreach (object src in srcArray)
{
- foreach (PropertyInfo item in sender.GetType().GetProperties())
+ T des = new T();
+ list.Add(des);
+ var srcProperties = GetCachedProperties(src.GetType());
+
+ foreach (var srcProperty in srcProperties)
{
- if (string.Compare(item.Name, name, true) == 0)
+ try
{
- property = item;
- break;
+ if (!desProperties.TryGetValue(srcProperty.Key, out var desProperty)) continue;
+
+ var srcValue = srcProperty.Value.GetValue(src);
+ if (srcProperty.Value.PropertyType != desProperty.PropertyType)
+ {
+ srcValue = Convert.ChangeType(srcValue, desProperty.PropertyType);
+ }
+
+ desProperty.SetValue(des, srcValue);
+ }
+ catch (Exception ex)
+ {
+ XLogger.Instance.Warn(ex);
}
}
}
- if (property == null) return string.Empty;
- return property.GetValue(sender)?.ToString();
- }
- catch (Exception ex)
- {
- XLogger.Instance.Fatal(ex);
- return string.Empty;
+
+ return list.ToArray();
}
+ catch { throw; }
}
+ /// DataTable
+ /// List with generic objects
+ public static T ToClass(this object src) where T : class, new()
+ {
+ try
+ {
+ T des = new T();
+ var desProperties = GetCachedProperties(typeof(T));
+ var srcProperties = GetCachedProperties(src.GetType());
+
+ foreach (var srcProperty in srcProperties)
+ {
+ try
+ {
+ if (!desProperties.TryGetValue(srcProperty.Key, out var desProperty)) continue;
+
+ var srcValue = srcProperty.Value.GetValue(src);
+ if (srcProperty.Value.PropertyType != desProperty.PropertyType)
+ {
+ srcValue = Convert.ChangeType(srcValue, desProperty.PropertyType);
+ }
+
+ desProperty.SetValue(des, srcValue);
+ }
+ catch (Exception ex)
+ {
+ XLogger.Instance.Warn(ex);
+ }
+ }
+
+ return des;
+ }
+ catch { throw; }
+ }
+
+ #endregion
+
///
/// 객체의 메소드를 호출합니다.
///
@@ -352,141 +453,6 @@ namespace JWH
return null;
}
- #region [ ToClass() ] -------------------------------------------------
-
- ///
- /// Converts a DataTable to a list with generic objects
- /// dataTable.ToClass();
- ///
- /// Generic object
- /// DataTable
- /// List with generic objects
- public static T[] ToClass(this DataTable dataTable) where T : class, new()
- {
- try
- {
- List list = new List();
- foreach (var row in dataTable.AsEnumerable())
- {
- T obj = new T();
-
- foreach (PropertyInfo property in obj.GetType().GetProperties())
- {
- try
- {
- if (dataTable.Columns.Contains(property.Name) == false) continue;
- if (row[property.Name] is System.DBNull) continue;
-
- var val = row[property.Name];
- //if (property.PropertyType == typeof(DateTime) && val.GetType() == typeof(string))
- // DateTime.TryParse(val.ToString(), out val);
-
- property.SetValue(obj, Convert.ChangeType(val, property.PropertyType, CultureInfo.CurrentCulture), null);
- }
- catch
- {
- continue;
- }
- }
-
- list.Add(obj);
- }
-
- return list.ToArray();
- }
- catch { throw; }
- }
-
- ///
- /// Converts a object to a list with generic objects
- /// dataTable.ToClass();
- ///
- /// Generic object
- /// DataTable
- /// List with generic objects
- public static T ToClass(this object src) where T : class, new()
- {
- try
- {
- T des = new T();
- Type desType = des.GetType();
- Type srcType = src.GetType();
- foreach (PropertyInfo srcProperty in srcType.GetProperties())
- {
- try
- {
- PropertyInfo desProperty = desType.GetProperty(srcProperty.Name);
- if (desProperty == null) continue;
-
- var srcValue = srcProperty.GetValue(src);
- if (srcProperty.PropertyType != desProperty.PropertyType)
- {
- srcValue = Convert.ChangeType(srcValue, desProperty.PropertyType);
- }
-
- desProperty.SetValue(des, srcValue);
- }
- catch (Exception ex)
- {
- XLogger.Instance.Warn(ex);
- }
- }
-
- return des;
- }
- catch { throw; }
- }
-
- ///
- /// Converts a object to a list with generic objects
- /// dataTable.ToClass();
- ///
- /// Generic object
- /// DataTable
- /// List with generic objects
- public static T[] ToClass(this object[] srcArray) where T : class, new()
- {
- try
- {
- List list = new List();
-
- foreach (object src in srcArray)
- {
- T des = new T();
- list.Add(des);
- Type desType = des.GetType();
-
- Type srcType = src.GetType();
- foreach (PropertyInfo srcProperty in srcType.GetProperties())
- {
- try
- {
- PropertyInfo desProperty = desType.GetProperty(srcProperty.Name);
- if (desProperty == null) continue;
-
- var srcValue = srcProperty.GetValue(src);
- if (srcProperty.PropertyType != desProperty.PropertyType)
- {
- srcValue = Convert.ChangeType(srcValue, desProperty.PropertyType);
- }
-
- desProperty.SetValue(des, srcValue);
- }
- catch (Exception ex)
- {
- XLogger.Instance.Warn(ex);
- }
- }
-
- }
-
- return list.ToArray();
- }
- catch { throw; }
- }
-
- #endregion
-
public static CultureInfo CultureInfo { get; set; }
public static string ToTitleCase(this string sender)