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