아모센스 마킹 gui
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

387 lines
17 KiB

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using marking_gui.Models;
namespace marking_gui.Services
{
public class EzdMarkingService : IMarkingService
{
private readonly object _handleLock = new object();
private bool _isInitialized = false;
private IntPtr _markingHandle = IntPtr.Zero; // 마킹 장치 기기 핸들 포인터
private string _ezdFolderPath = string.Empty;
private MarkingConfigService _config;
private string _lastInitErrorMessage = "초기화가 진행되지 않았습니다.";
public string LastInitErrorMessage
{
get
{
lock (_handleLock) { return _lastInitErrorMessage; }
}
}
// ==========================================
// MarkEzdWrapper.dll P/Invoke 선언부
// ==========================================
[DllImport("MarkEzdWrapper.dll", EntryPoint = "InitMarkEzd", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr InitMarkEzd();
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Init", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int Init(IntPtr hHandle, string strEzCadPath, IntPtr hOwenWnd);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "LoadEzdFile", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int LoadEzdFile(IntPtr hHandle, string strEzCadFileName);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "ChangeTextByName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int ChangeTextByNameW(IntPtr hHandle, string strTextName, string strTextNew);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "GetTextByName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int GetTextByNameW(IntPtr hHandle, string strTextName, System.Text.StringBuilder strText);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Mark", CallingConvention = CallingConvention.Cdecl)]
private static extern int Mark(IntPtr hHandle);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "ReadPort", CallingConvention = CallingConvention.Cdecl)]
private static extern int ReadPort(IntPtr hHandle, ref ushort Data);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "WritePort", CallingConvention = CallingConvention.Cdecl)]
private static extern int WritePort(IntPtr hHandle, ushort Data);
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Close", CallingConvention = CallingConvention.Cdecl)]
private static extern int Close(IntPtr hHandle);
private IntPtr _lastWindowHandle = IntPtr.Zero;
private string _lastConfigPath = string.Empty;
private string _lastLoadedEzdPath = string.Empty;
public bool Initialize(string configPath, IntPtr windowHandle)
{
lock (_handleLock)
{
try
{
_lastConfigPath = configPath;
if (windowHandle != IntPtr.Zero) _lastWindowHandle = windowHandle;
_lastInitErrorMessage = string.Empty;
_config = new MarkingConfigService();
_ezdFolderPath = _config.EzdFolderPath;
if (string.IsNullOrEmpty(_ezdFolderPath))
{
_lastInitErrorMessage = "Setting.ini 내 EzdFolderPath 경로가 비어 있습니다.";
_isInitialized = false;
return false;
}
// EZCAD.CFG 파일 유무 검증 및 상위/하위 경로 자동 탐색
string cfgFile = Path.Combine(_ezdFolderPath, "EZCAD.CFG");
if (!File.Exists(cfgFile))
{
if (File.Exists(@"c:\EzCad\EZCAD.CFG"))
{
_ezdFolderPath = @"c:\EzCad";
}
else if (File.Exists(@"c:\EzCad\EasyCfg\EZCAD.CFG"))
{
_ezdFolderPath = @"c:\EzCad\EasyCfg";
}
}
if (!Directory.Exists(_ezdFolderPath))
{
_lastInitErrorMessage = string.Format("마킹 라이브러리 폴더가 존재하지 않습니다: {0}", _ezdFolderPath);
_isInitialized = false;
return false;
}
if (_markingHandle == IntPtr.Zero)
{
_markingHandle = InitMarkEzd();
}
if (_markingHandle == IntPtr.Zero)
{
_lastInitErrorMessage = "InitMarkEzd() 생성 실패 (IntPtr.Zero)";
_isInitialized = false;
return false;
}
int result = Init(_markingHandle, _ezdFolderPath, windowHandle);
if (result == 0)
{
_isInitialized = true;
_lastLoadedEzdPath = string.Empty;
System.Diagnostics.Debug.WriteLine("[EzdMarking] 마킹기 연동 성공");
return true;
}
else
{
_lastInitErrorMessage = string.Format("Init() 실패 코드: {0} (경로: {1})", result, _ezdFolderPath);
try { Close(_markingHandle); } catch { }
_markingHandle = IntPtr.Zero;
_isInitialized = false;
return false;
}
}
catch (Exception ex)
{
_lastInitErrorMessage = "초기화 도중 예외: " + ex.Message;
_isInitialized = false;
return false;
}
}
}
[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
[System.Security.SecurityCritical]
public MarkingResult RequestMarking(MarkingRequest request)
{
lock (_handleLock)
{
if (!_isInitialized || _markingHandle == IntPtr.Zero)
{
System.Diagnostics.Debug.WriteLine("[EzdMarking] 디바이스 미초기화 상태 감지. 재연결 시도...");
Initialize(_lastConfigPath, _lastWindowHandle);
}
if (!_isInitialized || _markingHandle == IntPtr.Zero)
{
return new MarkingResult
{
Success = false,
ErrorCode = -10,
ErrorMessage = "LMC 마킹 디바이스가 연결 및 초기화되지 않았습니다. 상세 원인: " + _lastInitErrorMessage,
MarkedAt = DateTime.Now
};
}
try
{
string ezdFile = request.EzdFileName;
string ezdPath = ezdFile;
if (!File.Exists(ezdPath)) ezdPath = Path.Combine(_ezdFolderPath, ezdFile);
if (!File.Exists(ezdPath)) ezdPath = Path.Combine(_ezdFolderPath, "EasyCfg", ezdFile);
if (!File.Exists(ezdPath))
{
return new MarkingResult
{
Success = false,
ErrorCode = -11,
ErrorMessage = string.Format("도안 파일(.ezd)이 존재하지 않습니다: {0}", ezdFile),
MarkedAt = DateTime.Now
};
}
string absoluteEzdPath = Path.GetFullPath(ezdPath);
if (!string.Equals(_lastLoadedEzdPath, absoluteEzdPath, StringComparison.OrdinalIgnoreCase))
{
System.Diagnostics.Debug.WriteLine("[EzdMarking] 도안 파일 신규 로드: " + absoluteEzdPath);
int loadResult = LoadEzdFile(_markingHandle, absoluteEzdPath);
if (loadResult != 0)
{
_lastLoadedEzdPath = string.Empty;
return new MarkingResult
{
Success = false,
ErrorCode = loadResult,
ErrorMessage = string.Format("도안 파일(.ezd) 로드 실패. (경로: {0}, LoadEzdFile 에러코드: {1})", absoluteEzdPath, loadResult),
MarkedAt = DateTime.Now
};
}
_lastLoadedEzdPath = absoluteEzdPath;
}
string ezdDrawingNo = GetTextFromEzd(_config.DrawingNoTag, absoluteEzdPath);
string ezdHkmcNo = GetTextFromEzd(_config.HkmcNoTag, absoluteEzdPath);
if (string.IsNullOrWhiteSpace(ezdDrawingNo) && _config != null)
ezdDrawingNo = _config.GetDrawingNoForEzd(absoluteEzdPath);
if (string.IsNullOrWhiteSpace(ezdHkmcNo) && _config != null)
ezdHkmcNo = _config.GetHkmcNoForEzd(absoluteEzdPath);
if (!string.IsNullOrWhiteSpace(ezdDrawingNo)) request.DrawingNo = ezdDrawingNo;
if (!string.IsNullOrWhiteSpace(ezdHkmcNo)) request.HkmcNo = ezdHkmcNo;
string icSerial = string.IsNullOrWhiteSpace(request.IcSerial) ? request.Serial : request.IcSerial;
request.QrString = string.Format("{0};{1};{2};{3};", icSerial, request.DrawingNo, request.HkmcNo, request.Serial);
string seqOnly = (!string.IsNullOrEmpty(request.Serial) && request.Serial.Length >= 4)
? request.Serial.Substring(request.Serial.Length - 4)
: request.Serial;
ChangeTextInEzd(_config.SerialTag, seqOnly);
ChangeTextInEzd(_config.LotNoTag, request.LotNo);
ChangeTextInEzd(_config.QrCodeTag, request.QrString);
if (!string.IsNullOrWhiteSpace(request.DrawingNo)) ChangeTextInEzd(_config.DrawingNoTag, request.DrawingNo);
if (!string.IsNullOrWhiteSpace(request.HkmcNo)) ChangeTextInEzd(_config.HkmcNoTag, request.HkmcNo);
System.Diagnostics.Debug.WriteLine("[EzdMarking] 레이저 마킹 기계 동작 시작 (30초 타임아웃 제한)...");
IntPtr handleToMark = _markingHandle;
var markingTask = Task.Run(() => Mark(handleToMark));
var timeoutTask = Task.Delay(30000);
var completedTask = Task.WhenAny(markingTask, timeoutTask).Result;
if (completedTask == timeoutTask)
{
_isInitialized = false;
_markingHandle = IntPtr.Zero;
_lastLoadedEzdPath = string.Empty;
return new MarkingResult { Success = false, ErrorCode = -98, ErrorMessage = "레이저 각인 하드웨어 응답 타임아웃 (30초)", MarkedAt = DateTime.Now };
}
int markResult = markingTask.Result;
if (markResult == 0)
{
return new MarkingResult
{
Success = true,
ErrorCode = 0,
ErrorMessage = "마킹 완료",
MarkedAt = DateTime.Now,
DrawingNo = request.DrawingNo,
HkmcNo = request.HkmcNo,
QrString = request.QrString
};
}
else
{
_isInitialized = false;
_markingHandle = IntPtr.Zero;
_lastLoadedEzdPath = string.Empty;
return new MarkingResult { Success = false, ErrorCode = markResult, ErrorMessage = string.Format("레이저 각인 하드웨어 동작 에러 (에러코드: {0})", markResult), MarkedAt = DateTime.Now };
}
}
catch (Exception ex)
{
_isInitialized = false;
_markingHandle = IntPtr.Zero;
_lastLoadedEzdPath = string.Empty;
return new MarkingResult { Success = false, ErrorCode = -99, ErrorMessage = "마킹 처리 중 예외 발생: " + ex.Message, MarkedAt = DateTime.Now };
}
}
}
private bool _disposed = false;
public string GetTextFromEzd(string tagName, string ezdFilePath = null)
{
if (string.IsNullOrWhiteSpace(tagName)) return string.Empty;
// 1단계: P/Invoke GetTextByNameW 호출 (DLL 지원 시 도안 텍스트 읽기)
if (_markingHandle != IntPtr.Zero)
{
try
{
var sbW = new System.Text.StringBuilder(512);
int resW = GetTextByNameW(_markingHandle, tagName, sbW);
if (resW == 0 && sbW.Length > 0)
{
string val = sbW.ToString().Trim();
if (!string.IsNullOrWhiteSpace(val)) return val;
}
}
catch (EntryPointNotFoundException)
{
System.Diagnostics.Debug.WriteLine($"[EzdMarking] GetTextByName({tagName}) DLL 내 엔트리포인트 없음.");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"[EzdMarking] GetTextByName({tagName}) 읽기 예외: {ex.Message}");
}
}
// 2단계: Setting.ini / MarkingConfigService 사용자 명시 설정값 참조
if (_config != null)
{
if (tagName.Equals(_config.DrawingNoTag, StringComparison.OrdinalIgnoreCase))
{
return _config.GetDrawingNoForEzd(ezdFilePath);
}
if (tagName.Equals(_config.HkmcNoTag, StringComparison.OrdinalIgnoreCase))
{
return _config.GetHkmcNoForEzd(ezdFilePath);
}
}
return string.Empty;
}
private void ChangeTextInEzd(string tagName, string textNew)
{
if (string.IsNullOrWhiteSpace(tagName) || _markingHandle == IntPtr.Zero) return;
try
{
ChangeTextByNameW(_markingHandle, tagName, textNew);
}
catch
{
// Fallback
}
}
public void StopMarking()
{
try
{
if (_markingHandle != IntPtr.Zero)
{
System.Diagnostics.Debug.WriteLine("[EzdMarking] StopMarking 요청 처리 완료");
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("[EzdMarking] StopMarking 중 예외 발생: " + ex.Message);
}
}
public void Shutdown()
{
lock (_handleLock)
{
try
{
if (_isInitialized && _markingHandle != IntPtr.Zero)
{
Close(_markingHandle);
_markingHandle = IntPtr.Zero;
_isInitialized = false;
System.Diagnostics.Debug.WriteLine("[EzdMarking] 마킹 컨트롤 디바이스 정상 종료 완료.");
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("[EzdMarking] 디바이스 종료 중 예외: " + ex.Message);
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
Shutdown();
_disposed = true;
}
}
~EzdMarkingService()
{
Dispose(false);
}
}
}