97 changed files with 10548 additions and 2720 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,361 @@ |
|||
# Performance Inspect & Laser Marking System - 개발자 메뉴얼 |
|||
|
|||
본 문서는 **양산형 테스트 기기 모니터링 시스템**의 유지보수, 릴리즈, 시스템 통합 및 디버깅을 위한 개발자용 상세 기술 사양서입니다. 시스템 설계 정보, 하드웨어 연동 규격, 그리고 제어 시퀀스를 포함하고 있습니다. |
|||
|
|||
--- |
|||
|
|||
## 1. 시스템 아키텍처 및 요구사항 |
|||
|
|||
### 1.1 기술 스택 |
|||
- **프레임워크**: .NET Framework 4.7.2 (WPF) |
|||
- **UI 패턴**: MVVM (MainWindow, SettingsWindow, StartupLoginWindow 등) |
|||
- **데이터베이스**: Microsoft SQL Server 2012 이상 (ADO.NET 연동) |
|||
- **장비 연동**: |
|||
- LMC1 레이저 각인 컨트롤러 (C++ Wrapped DLL `MarkEzdWrapper.dll` 로드) |
|||
- Keysight DMM & PSU (TCP/IP 기반 SCPI 통신) |
|||
- 4251 센서 판독 보드 (시리얼 RS-232 기반 고유 프로토콜) |
|||
|
|||
### 1.2 개발 환경 구동 요구사항 |
|||
- Visual Studio 2022 이상 |
|||
- MSBuild 엔진 (XAML 컴파일 지원) |
|||
- MS-SQL Server Express 또는 로컬 DB 인프라 |
|||
- EZCAD 2 소프트웨어 및 LMC USB 각인 카드 드라이버 |
|||
|
|||
--- |
|||
|
|||
## 2. 설정 파일 (INI) 상세 사양 |
|||
|
|||
실행 파일 경로에 위치하는 INI 설정 파일들의 각 항목별 역할 및 타입 정의입니다. |
|||
|
|||
### 2.1 Setting.ini |
|||
계측 장비 접속 주소, SCPI 제어 명령어 매개변수 및 레이저 각인 도안 태그 매핑(`[Tags]`) 설정을 포함합니다. |
|||
|
|||
```ini |
|||
; ================================================================= |
|||
; 성능 검사 모니터링 시스템 - 레이저 마킹기 연동 설정 파일 |
|||
; ================================================================= |
|||
|
|||
[Settings] |
|||
; 마킹 제어 라이브러리 및 드라이버(EzCad) 폴더 경로 |
|||
EzdFolderPath=c:\EzCad |
|||
|
|||
; 테스트 모드 여부 (true 시 하단 테스트 마킹, 강제 검사 버튼 노출) |
|||
test=false |
|||
|
|||
|
|||
[Tags] |
|||
; 도안(.ezd) 파일 내의 텍스트 오브젝트 치환용 태그명 매핑 리스트 |
|||
; (도안에 정의된 오브젝트명과 동일하게 설정해야 정상 작동합니다) |
|||
|
|||
; 일련번호 (Serial Number) 치환 태그 |
|||
SerialTag=SERIAL |
|||
|
|||
; 작업 년월일 (Lot No) 치환 태그 |
|||
LotNoTag=YYMMDD |
|||
|
|||
; 제품 모델명 (Product Name) 치환 태그 |
|||
ProductTag=PRODUCT |
|||
|
|||
; 2D QR 코드 데이터 치환 태그 |
|||
QrCodeTag=QRCODETAG |
|||
|
|||
; 검사 라인 코드 치환 태그 |
|||
LineTag=LCODE |
|||
|
|||
; 작업 조 (Shift) 치환 태그 |
|||
ShiftTag=BAN |
|||
|
|||
|
|||
; ================================================================= |
|||
; 계측기 연동 설정 (SCPI / LAN) |
|||
; ================================================================= |
|||
|
|||
[Equipment] |
|||
; 계측기 통신 타임아웃 (ms) |
|||
Timeout=5000 |
|||
|
|||
; 측정 안정화 대기 시간 (ms) — Power Supply ON 후 이 시간만큼 대기 후 읽음 |
|||
SettleMilliseconds=2000 |
|||
|
|||
; 검사 전 보드 전원 공급 커맨드 (세미콜론으로 구분) |
|||
PreBoardCommand=VOLT 5, (@2);OUTP ON, (@2) |
|||
PreBoardDelayMilliseconds=2000 |
|||
|
|||
; 로그아웃 시 전원 차단 커맨드 |
|||
LogoutCommand=OUTP OFF, (@1) |
|||
|
|||
|
|||
[DMM] |
|||
; Digital Multimeter — 전압 및 저항 측정 전용 (예시 IP: 192.168.1.100) |
|||
VoltageConnection=LAN |
|||
VoltageHost=192.168.1.100 |
|||
VoltagePort=5025 |
|||
VoltageIdnMatch=34465A |
|||
VoltageBaudRate=115200 |
|||
VoltageTerminator=LF |
|||
VoltageSetupCommand= |
|||
VoltageReadCommand=MEAS:VOLT:DC? |
|||
ResistanceReadCommand=MEAS:RES? |
|||
|
|||
|
|||
[CurrentDMM] |
|||
; Digital Multimeter — 전류 측정 전용 (예시 IP: 192.168.1.102 - 현재 제어 시퀀스에서 미사용) |
|||
CurrentDMMConnection=LAN |
|||
CurrentDMMHost=192.168.1.102 |
|||
CurrentDMMPort=5025 |
|||
CurrentDMMIdnMatch=34465A |
|||
CurrentDMMBaudRate=115200 |
|||
CurrentDMMTerminator=LF |
|||
CurrentDMMReadCommand=MEAS:CURR:DC? |
|||
|
|||
|
|||
[PowerSupply] |
|||
; Power Supply — 출력 제어 및 전류 측정 (예시 IP: 192.168.1.101) |
|||
CurrentConnection=LAN |
|||
CurrentHost=192.168.1.101 |
|||
CurrentPort=5025 |
|||
CurrentIdnMatch=E36233A |
|||
CurrentBaudRate=9600 |
|||
CurrentTerminator=LF |
|||
CurrentSetupCommand=OUTP ON, (@1) |
|||
CurrentCleanupCommand=OUTP OFF, (@1) |
|||
CurrentReadCommand=MEAS:CURR? (@1) |
|||
|
|||
|
|||
[Limits] |
|||
; 최종 계측 합/불 판정 규격 임계치 (Min: 하한치, Max: 상한치) |
|||
; UI [시험 설정] 메뉴에서 변경 시 자동 저장 및 갱신됩니다. |
|||
MinVoltage=4.0 |
|||
MaxVoltage=6.0 |
|||
|
|||
MinCurrent=8.0 |
|||
MaxCurrent=10.0 |
|||
|
|||
MinResistance=0.4 |
|||
MaxResistance=0.8 |
|||
``` |
|||
|
|||
### 2.2 Database.ini |
|||
생산 이력 조회 및 적재 목적의 DB 연결 설정입니다. |
|||
|
|||
```ini |
|||
[Database] |
|||
# SQL 데이터베이스 접속 주소 및 계정 정보 (예시 주소) |
|||
Db_Server=192.168.1.200 |
|||
Db_Name=MarkingDb |
|||
Db_User=db_user |
|||
Db_Password=db_password |
|||
|
|||
# 로컬 테스트 및 DB 점검 시 우회용 플래그 |
|||
OfflineMode=False |
|||
|
|||
|
|||
[Login] |
|||
# 작업자 로그인 검증 시 호출할 저장 프로시저명 |
|||
Procedure=dbo.CheckOperator |
|||
|
|||
# 작업 공정 식별 이름 (저장 프로시저 매개변수 바인딩용) |
|||
ProcessName=Marking |
|||
|
|||
# 오프라인 로그인 미리보기 활성화 여부 |
|||
OfflinePreview=false |
|||
``` |
|||
|
|||
### 2.3 Sensor.ini |
|||
4251 센서 통신 보드 시리얼 통신을 위한 포트 매핑 파일입니다. |
|||
|
|||
```ini |
|||
[Sensor] |
|||
# 시리얼 COM 포트 번호 |
|||
Port=COM3 |
|||
|
|||
# 통신 속도 |
|||
BaudRate=115200 |
|||
|
|||
# 보드 내부 멀티 채널 스위칭 인덱스 (1 또는 2) |
|||
Channel=1 |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 3. 데이터베이스 스키마 및 연동 규격 |
|||
|
|||
### 3.1 테이블 구성 정보 |
|||
- **`[dbo].[Users]` (작업자 계정 정보 테이블)** |
|||
- `OperatorId` (VARCHAR(50), UNIQUE): 작업자 로그인 ID |
|||
- `Password` (VARCHAR(50)): 비밀번호 |
|||
- `Name` (VARCHAR(50)): 작업자 성명 |
|||
- `IsActive` (BIT): 활성 상태 여부 |
|||
|
|||
- **`[dbo].[Marking]` (최종 성능 계측값 및 마킹 결과 저장 테이블)** |
|||
- `IC_SN` (VARCHAR(50), PRIMARY KEY): 센서 일련번호 |
|||
- `Marking_QR` (VARCHAR(100), UNIQUE): 고유 QR 코드 문자열 (yyMMdd + 일련번호) |
|||
- `Maker` (VARCHAR(50)), `Model` (VARCHAR(50)): 제품 사양 정보 |
|||
- `Variant_1`, `Variant_2` (VARCHAR(50)) |
|||
- `Operator` (VARCHAR(50)): 담당 작업자 ID |
|||
- `Production_Date` (DATETIME): 생산 일자 및 계측 시간 |
|||
- `Line` (VARCHAR(10)): 생산 라인 (최대 10자 제한, 초과 시 코드 내에서 절삭) |
|||
- `Lot_No` (VARCHAR(8)): 로트 번호 (최대 8자 제한, 초과 시 코드 내에서 절삭) |
|||
- `Jig_No` (VARCHAR(10)): 지그 번호 |
|||
- `PT_Vol_1` (DECIMAL(18,2)), `PT_Current_1` (DECIMAL(18,2)), `PT_Resistance_1` (DECIMAL(18,3)): 실측 전압, 전류, 저항값 |
|||
- `Result` (VARCHAR(10)): 최종 종합 판정 (`PASS` 또는 `FAIL`) |
|||
- `MarkedSerial` (VARCHAR(50)): 최종 마킹된 시퀀스 코드 |
|||
|
|||
### 3.2 이전 공정 결과 교차 검증 (Subquery) |
|||
검사 개시 시점, 제품의 S/N(`IC_SN`)을 기반으로 선행 공정이 완료되었는지 조회합니다. |
|||
```sql |
|||
SELECT |
|||
(SELECT Result FROM Housing_Assembly WHERE IC_SN = @IC_SN) AS HousingResult, |
|||
(SELECT Final_Result FROM Cal_EOL_Result WHERE IC_SN = @IC_SN) AS CalResult, |
|||
(SELECT Result FROM EOL WHERE IC_SN = @IC_SN) AS EolResult |
|||
``` |
|||
- **판정 조건**: 조회 결과 3개 항목이 모두 `PASS` 또는 `OK` 상태이어야 최종 검사 기동이 허용됩니다. |
|||
|
|||
### 3.3 로그인 저장 프로시저 (`[dbo].[CheckOperator]`) |
|||
- **프로시저 스펙**: |
|||
```sql |
|||
CREATE PROCEDURE [dbo].[CheckOperator] |
|||
@Operator VARCHAR(50), |
|||
@Password VARCHAR(50), |
|||
@ProcessName VARCHAR(50) = NULL |
|||
AS |
|||
BEGIN |
|||
SELECT COUNT(*) |
|||
FROM Users |
|||
WHERE OperatorId = @Operator |
|||
AND Password = @Password |
|||
AND IsActive = 1 |
|||
END |
|||
``` |
|||
- **호출 매핑 코드**: |
|||
ADO.NET `SqlCommand` 객체를 사용하여 `CommandType.StoredProcedure` 형식으로 호출하며 리턴값이 `1`일 경우 검증 처리합니다. |
|||
|
|||
--- |
|||
|
|||
## 4. 하드웨어 제어 프로토콜 및 SCPI 사양 |
|||
|
|||
### 4.1 4251 센서 통신 보드 시리얼 패킷 규격 |
|||
센서 일련번호를 추출하고 보드를 제어하기 위해 RS-232 시리얼(115200bps)을 통해 다음 패킷 명령을 전송합니다. |
|||
|
|||
1. **보드 대기 및 리셋 명령**: `"x00o"` |
|||
2. **보드 채널 결속 명령**: `"x00c_00{channel}101:owt28006727ea97c7801"` |
|||
- `{channel}`은 `Sensor.ini`에서 파싱한 값 (예: `1` 또는 `2`) |
|||
3. **고유 ID(IC_SN) 읽기 명령**: `"x00c_00{channel}101:ow2800326003e"` |
|||
- 송신 후 보드 응답 버퍼에서 16진수 일련번호 데이터(16자)를 추출합니다. |
|||
4. **보정 기본값 전송**: `"x00c_00{channel}001:owt28006727ea97c7801"` |
|||
|
|||
### 4.2 계측 장비 제어 SCPI 명령어 구성 및 시퀀스 |
|||
모든 TCP/IP 계측기는 포트 **5025**를 통해 SCPI 표준 명령으로 조작됩니다. |
|||
|
|||
1. **장비 연결 및 아이덴티티 검증 (Handshake)**: |
|||
- 각 계측기 접속 후 `*IDN?` 명령을 전송하여 응답 텍스트에 `Setting.ini`에 지정된 장비 모델명(예: `34465A`, `E36233A`)이 수록되어 있는지 확인합니다. |
|||
2. **테스트 주전원(CH1) 인가**: |
|||
- `OUTP ON, (@1)` |
|||
- 전원 공급 후 신호 안정을 위해 `SettleMilliseconds`(기본 2000ms, 즉 2초)만큼 대기합니다. |
|||
3. **측정 데이터 수집**: |
|||
- **전압(V)**: 전압 DMM(예: 192.168.1.100)에 `MEAS:VOLT:DC?`를 질의하여 획득. |
|||
- **저항(Ω)**: 저항 DMM(예: 192.168.1.100)에 `MEAS:RES?`를 질의하여 획득. (획득값은 kΩ 단위 조정을 위해 1000으로 나눔) |
|||
- **전류(A)**: 파워서플라이(예: 192.168.1.101)의 CH1에 `MEAS:CURR? (@1)`을 질의하여 획득. (획득값은 mA 단위 조정을 위해 1000을 곱함) |
|||
- *주의: 전류 측정 전용 DMM(예: 192.168.1.102) 장비는 설정 파일에 로드되나 실제 측정 시퀀스 상에서는 사용되지 않습니다.* |
|||
4. **주전원(CH1) 차단**: |
|||
- `OUTP OFF, (@1)` |
|||
- 계측 도중 예외가 발생하더라도 `finally` 구문 내에서 차단 명령을 전송합니다. |
|||
|
|||
--- |
|||
|
|||
## 5. 레이저 마킹기 연동 사양 (LMC1 API) |
|||
|
|||
C++로 개발된 레이저 각인기 드라이버 DLL인 `MarkEzdWrapper.dll`을 P/Invoke를 통해 호출합니다. |
|||
|
|||
### 5.1 연동 시 핵심 규칙 |
|||
1. **세션 핸들 (`hHandle`) 관리**: |
|||
- 프로그램 시작 시 `InitMarkEzd()` 함수를 호출하여 세션 포인터(`IntPtr`)를 받아 전역 변수로 관리합니다. |
|||
- 각인 관련 API 함수 호출 시 이 `IntPtr` 핸들을 첫 번째 매개변수로 전달해야 합니다. |
|||
2. **유니코드 마샬링 (`CharSet.Unicode`)**: |
|||
- C++ DLL 단의 모든 문자열 인자가 `const wchar_t*` (유니코드)를 사용하므로, DllImport 선언의 문자셋 속성은 `CharSet = CharSet.Unicode`로 설정해야 정상 작동합니다. |
|||
3. **HWND 부모 창 핸들 지연 초기화**: |
|||
- `Init` 함수는 부모 WPF 윈도우의 핸들(`IntPtr`)을 요구합니다. |
|||
- Window 생성자 시점에는 핸들이 미생성 상태이므로, 반드시 **`Dispatcher.BeginInvoke(..., DispatcherPriority.Loaded)`**를 활용하여 메인 윈도우 로드가 완료된 후에 핸들을 추출해 초기화해야 합니다. |
|||
|
|||
### 5.2 DLL 가져오기 (P/Invoke) 선언 명세 |
|||
```csharp |
|||
[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 ChangeTextByName(IntPtr hHandle, string strTextName, string strTextNew); |
|||
|
|||
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Mark", CallingConvention = CallingConvention.Cdecl)] |
|||
private static extern int Mark(IntPtr hHandle); |
|||
|
|||
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Close", CallingConvention = CallingConvention.Cdecl)] |
|||
private static extern int Close(IntPtr hHandle); |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 6. 데모용 시뮬레이션 격리 및 릴리즈 배포 가이드 |
|||
|
|||
### 6.1 데모 모드 격리 코드 해제 방법 |
|||
상용 빌드 릴리즈 시, 데이터베이스에 실제 로그인하지 않고 통과하는 데모 우회 로직을 소스 코드 단에서 제거해야 합니다. |
|||
|
|||
1. **[LoginServicesStub.cs](file:///C:/Users/COMPUTER1/Desktop/mobi/marking_gui/marking_gui/Services/LoginServicesStub.cs)** 파일을 엽니다. |
|||
2. `ExistsAsync` 메서드 안의 `catch (Exception ex)` 구문 내부에 위치한 아래의 **DEMO MODE 주석 배너** 영역 코드를 삭제하거나 주석 처리하여 릴리즈 빌드를 만드십시오. |
|||
|
|||
```csharp |
|||
// ==================== [DEMO MODE START] ==================== |
|||
// 데모 시뮬레이션용 프로시저 성공 연출 코드 |
|||
// 상용 릴리즈 시 이 블록은 완전히 제거(삭제)할 수 있습니다. |
|||
if (!string.IsNullOrWhiteSpace(_loginSettings.Procedure)) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine(string.Format("[데모 시뮬레이션] 프로시저 '{0}' 호출 모사 (ID: {1}, PW: {2}, Process: {3})", |
|||
_loginSettings.Procedure, operatorId, password, _loginSettings.ProcessName)); |
|||
return IsDefaultAccount(operatorId, password); |
|||
} |
|||
// ==================== [DEMO MODE END] ==================== |
|||
``` |
|||
|
|||
### 6.2 릴리즈 게시 및 단일 설치 파일(MarkingSetup.exe) 자동 생성 가이드 |
|||
|
|||
본 프로젝트는 Visual Studio 게시 프로필 및 WiX Toolset 커스텀 타깃이 적용되어 있어, CLI 게시 명령 한 번으로 단일 실행 설치 파일(`MarkingSetup.exe`)을 자동으로 컴파일 및 생성합니다. |
|||
|
|||
- **권장 CLI 게시 명령어 (Terminal)**: |
|||
```powershell |
|||
dotnet publish marking_gui/marking_gui.csproj -c Release -r win-x86 --self-contained |
|||
``` |
|||
- **자동 빌드 및 패키징 동작 순서**: |
|||
1. 프로젝트 릴리즈 바이너리 및 의존 라이브러리 일체 자동 수집 |
|||
2. `C:\marking\libs\` 경로로 모든 런타임 DLL 격리 구성 |
|||
3. WiX Toolset(`wix build`)이 가동하여 MSI 패키지 및 단일 EXE 부트스트랩 번들 컴파일 |
|||
4. 최종 설치 파일 `MarkingSetup.exe`가 `C:\marking\` 및 `bin\Release\net9.0-windows\win-x86\publish\` 폴더로 자동 생성 이관 |
|||
- **배포 및 전달 대상 파일**: |
|||
- `MarkingSetup.exe` (단일 파일만 현장에 전달하여 1-Click 설치 진행) |
|||
|
|||
### 6.3 배포 설치 디렉터리(`C:\marking\`) 파일 구조 및 런타임 생성 폴더 사양 |
|||
|
|||
`MarkingSetup.exe`로 인스톨된 후 `C:\marking\` 아래에 배치되는 파일 및 런타임 가동 중 생성되는 디렉터리 명세입니다. |
|||
|
|||
``` |
|||
C:\marking\ |
|||
├── marking_gui.exe # 메인 WPF 실행 바이너리 |
|||
├── marking_gui.dll # 핵심 애플리케이션 어셈블리 |
|||
├── marking_gui.deps.json # 종속성 매니페스트 |
|||
├── marking_gui.runtimeconfig.json # .NET 9.0 런타임 환경 구성 |
|||
├── Setting.ini # 마킹기 경로, 태그 매핑, 계측기 IP, SCPI 전원, [Limits] 판정 임계치 종합 설정 |
|||
├── Database.ini # MS-SQL 접속 계정 및 오프라인 모드(OfflineMode) 설정 |
|||
├── Sensor.ini # 4251 센서 통신 보드 시리얼 포트(COM), BaudRate, 채널 설정 |
|||
├── libs\ # C++ LMC 드라이버 라이브러리 격리 폴더 |
|||
│ ├── MarkEzdWrapper.dll # C# - C++ LMC P/Invoke 래퍼 |
|||
│ ├── DataMgr.dll # EZCAD 데이터 매니저 |
|||
│ ├── MarkEzd.dll # EZCAD 커널 마킹 라이브러리 |
|||
│ └── haspms32.dll # 동글/라이선스 보안 라이브러리 일체 |
|||
├── logs\ # 런타임 가동 중 일별 자동 생성되는 시스템/통신/마킹 이력 로그 |
|||
│ └── 2026-07-23.log # 텍스트 형태의 일자별 로그 파일 |
|||
└── publish_backup\ # 게시 및 버전 업데이트 시 기존 파일 자동 백업 보관 폴더 |
|||
``` |
|||
@ -0,0 +1,13 @@ |
|||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal"> |
|||
<Bundle Name="Marking System" Version="1.0.0" Manufacturer="MobiDigm" UpgradeCode="51A2E3B4-F5C6-4A7B-8C9D-0E1F2A3B4C5D" IconSourceFile="C:\marking\Marking.ico"> |
|||
|
|||
<BootstrapperApplication> |
|||
<bal:WixStandardBootstrapperApplication LicenseUrl="https://www.mobidigm.co.kr" Theme="hyperlinkLicense" SuppressOptionsUI="yes" /> |
|||
</BootstrapperApplication> |
|||
|
|||
<Chain> |
|||
<!-- 빌드 프로세스 하위에 생성된 MSI 패키지를 래핑 --> |
|||
<MsiPackage SourceFile="C:\marking\MarkingSetup.msi" Compressed="yes" Vital="yes" /> |
|||
</Chain> |
|||
</Bundle> |
|||
</Wix> |
|||
@ -0,0 +1,147 @@ |
|||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> |
|||
<Package Name="Marking System" Language="1042" Version="1.0.0" Manufacturer="MobiDigm" UpgradeCode="62B3F4C5-0D1E-5B8C-9D0A-1F2E3A4B5C6D" Scope="perMachine"> |
|||
|
|||
<MajorUpgrade DowngradeErrorMessage="이미 최신 버전의 프로그램이 설치되어 있습니다." /> |
|||
|
|||
<MediaTemplate EmbedCab="yes" /> |
|||
|
|||
<!-- 제어판 프로그램 및 바로가기용 아이콘 정의 --> |
|||
<Icon Id="ProductIcon.ico" SourceFile="C:\marking\Marking.ico" /> |
|||
<Property Id="ARPPRODUCTICON" Value="ProductIcon.ico" /> |
|||
|
|||
<!-- 바탕화면 바로가기용 표준 디렉토리 지정 --> |
|||
<StandardDirectory Id="DesktopFolder" /> |
|||
|
|||
<!-- C 드라이브 루트 하위에 marking 폴더 생성 강제 고정 --> |
|||
<StandardDirectory Id="TARGETDIR" /> |
|||
<SetDirectory Id="MarkingFolder" Value="C:\marking" /> |
|||
|
|||
<Directory Id="MarkingFolder"> |
|||
<!-- 하위 폴더 구조 정의 --> |
|||
<Directory Id="libsFolder" Name="libs" /> |
|||
</Directory> |
|||
|
|||
<!-- 1. C:\marking 루트 파일 구성 --> |
|||
<ComponentGroup Id="RootComponents" Directory="MarkingFolder"> |
|||
<Component Id="MainExecutable" Guid="73C4A5D6-1E2F-6C9D-0A1B-2C3D4E5F6A7B"> |
|||
<File Id="marking_gui.exe" Source="C:\marking\marking_gui.exe" KeyPath="yes"> |
|||
<Shortcut Id="DesktopShortcut" Directory="DesktopFolder" Name="Marking System" WorkingDirectory="MarkingFolder" Advertise="no" Icon="ProductIcon.ico" /> |
|||
</File> |
|||
</Component> |
|||
|
|||
<Component Id="ConfigFile" Guid="84D5B6E7-2F3A-7D0A-1B2C-3D4E5F6A7B8C"> |
|||
<File Id="marking_gui.dll.config" Source="C:\marking\marking_gui.dll.config" KeyPath="yes" /> |
|||
</Component> |
|||
|
|||
<Component Id="DatabaseIni" Guid="95E6C7F8-3A4B-8E1B-2C3D-4E5F6A7B8C9D"> |
|||
<File Id="Database.ini" Source="C:\marking\Database.ini" KeyPath="yes" /> |
|||
</Component> |
|||
|
|||
<Component Id="SettingIni" Guid="06F7D8A9-4B5C-9F2B-3C4D-5E6F7A8B9C0D"> |
|||
<File Id="Setting.ini" Source="C:\marking\Setting.ini" KeyPath="yes" /> |
|||
</Component> |
|||
|
|||
<Component Id="LoginOptionsJson" Guid="17A8B9C0-D1E2-3F4A-5B6C-7D8E9F0A1B2C"> |
|||
<File Id="LoginOptions.json" Source="C:\marking\LoginOptions.json" KeyPath="yes" /> |
|||
</Component> |
|||
|
|||
<Component Id="MarkingIcoFile" Guid="28B9C0D1-E2F3-4A5B-6C7D-8E9F0A1B2C3D"> |
|||
<File Id="Marking.ico" Source="C:\marking\Marking.ico" KeyPath="yes" /> |
|||
</Component> |
|||
</ComponentGroup> |
|||
|
|||
<!-- 2. C:\marking\libs 하위 DLL 구성 --> |
|||
<ComponentGroup Id="LibComponents" Directory="libsFolder"> |
|||
<Component Id="libs_DataMgr" Guid="11111111-1111-1111-1111-111111111111"> |
|||
<File Id="libs_DataMgr.dll" Source="C:\marking\libs\DataMgr.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_haspms32" Guid="22222222-2222-2222-2222-222222222222"> |
|||
<File Id="libs_haspms32.dll" Source="C:\marking\libs\haspms32.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_HVAPI" Guid="33333333-3333-3333-3333-333333333333"> |
|||
<File Id="libs_HVAPI.dll" Source="C:\marking\libs\HVAPI.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_HVDAILT" Guid="44444444-4444-4444-4444-444444444444"> |
|||
<File Id="libs_HVDAILT.dll" Source="C:\marking\libs\HVDAILT.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_JczDog" Guid="55555555-5555-5555-5555-555555555555"> |
|||
<File Id="libs_JczDog.dll" Source="C:\marking\libs\JczDog.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_Lmc1" Guid="66666666-6666-6666-6666-666666666666"> |
|||
<File Id="libs_Lmc1.dll" Source="C:\marking\libs\Lmc1.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_LMCMIO" Guid="77777777-7777-7777-7777-777777777777"> |
|||
<File Id="libs_LMCMIO.dll" Source="C:\marking\libs\LMCMIO.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MarkEzd" Guid="88888888-8888-8888-8888-888888888888"> |
|||
<File Id="libs_MarkEzd.dll" Source="C:\marking\libs\MarkEzd.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MarkEzdWrapper_Copy" Guid="99999999-9999-9999-9999-999999999999"> |
|||
<File Id="libs_MarkEzdWrapper_Copy.dll" Source="C:\marking\libs\MarkEzdWrapper - 복사본.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MarkEzdWrapper" Guid="00000000-0000-0000-0000-000000000000"> |
|||
<File Id="libs_MarkEzdWrapper.dll" Source="C:\marking\libs\MarkEzdWrapper.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_mathlib" Guid="12121212-1212-1212-1212-121212121212"> |
|||
<File Id="libs_mathlib.dll" Source="C:\marking\libs\mathlib.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_mfc42u" Guid="23232323-2323-2323-2323-232323232323"> |
|||
<File Id="libs_mfc42u.dll" Source="C:\marking\libs\mfc42u.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MFC71" Guid="34343434-3434-3434-3434-343434343434"> |
|||
<File Id="libs_MFC71.dll" Source="C:\marking\libs\MFC71.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MilProcess" Guid="45454545-4545-4545-4545-454545454545"> |
|||
<File Id="libs_MilProcess.dll" Source="C:\marking\libs\MilProcess.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_Msvcp71" Guid="56565656-5656-5656-5656-565656565656"> |
|||
<File Id="libs_Msvcp71.dll" Source="C:\marking\libs\Msvcp71.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_Msvcr71" Guid="67676767-6767-6767-6767-676767676767"> |
|||
<File Id="libs_Msvcr71.dll" Source="C:\marking\libs\Msvcr71.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_msvcrt" Guid="78787878-7878-7878-7878-787878787878"> |
|||
<File Id="libs_msvcrt.dll" Source="C:\marking\libs\msvcrt.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MVAPI" Guid="89898989-8989-8989-8989-898989898989"> |
|||
<File Id="libs_MVAPI.dll" Source="C:\marking\libs\MVAPI.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MVBayerDec" Guid="90909090-9090-9090-9090-909090909090"> |
|||
<File Id="libs_MVBayerDec.dll" Source="C:\marking\libs\MVBayerDec.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MVCAPI" Guid="01010101-0101-0101-0101-010101010101"> |
|||
<File Id="libs_MVCAPI.dll" Source="C:\marking\libs\MVCAPI.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_MVParm" Guid="13131313-1313-1313-1313-131313131313"> |
|||
<File Id="libs_MVParm.dll" Source="C:\marking\libs\MVParm.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_NcPath" Guid="24242424-2424-2424-2424-242424242424"> |
|||
<File Id="libs_NcPath.dll" Source="C:\marking\libs\NcPath.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_QDib" Guid="35353535-3535-3535-3535-353535353535"> |
|||
<File Id="libs_QDib.dll" Source="C:\marking\libs\QDib.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_QLib" Guid="46464646-4646-4646-4646-464646464646"> |
|||
<File Id="libs_QLib.dll" Source="C:\marking\libs\QLib.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_Sense3" Guid="57575757-5757-5757-5757-575757575757"> |
|||
<File Id="libs_Sense3.dll" Source="C:\marking\libs\Sense3.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_SQLite_Interop" Guid="68686868-6868-6868-6868-686868686868"> |
|||
<File Id="libs_SQLite.Interop.dll" Source="C:\marking\libs\SQLite.Interop.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_System_Data_SQLite" Guid="79797979-7979-7979-7979-797979797979"> |
|||
<File Id="libs_System.Data.SQLite.dll" Source="C:\marking\libs\System.Data.SQLite.dll" KeyPath="yes" /> |
|||
</Component> |
|||
<Component Id="libs_UseSapera" Guid="91919191-9191-9191-9191-919191919191"> |
|||
<File Id="libs_UseSapera.dll" Source="C:\marking\libs\UseSapera.dll" KeyPath="yes" /> |
|||
</Component> |
|||
</ComponentGroup> |
|||
|
|||
<!-- 설치 대상 패키지 Feature 지정 --> |
|||
<Feature Id="ProductFeature" Title="Marking System Setup" Level="1"> |
|||
<ComponentGroupRef Id="RootComponents" /> |
|||
<ComponentGroupRef Id="LibComponents" /> |
|||
</Feature> |
|||
</Package> |
|||
</Wix> |
|||
@ -0,0 +1,87 @@ |
|||
--- |
|||
name: laser_marking_integration |
|||
description: Guidelines and P/Invoke signatures for integrating the LMC laser marking machine via MarkEzdWrapper.dll without crashes. |
|||
--- |
|||
|
|||
# LMC 레이저 각인기 연동 규격 및 에이전트 행동 규칙 |
|||
|
|||
이 규칙은 `MarkEzdWrapper.dll` 파일과 WPF 모니터링 시스템 간의 레이저 각인(마킹) 장치 연동 설계 사양을 고정합니다. **이 사양은 어떠한 경우에도 임의로 단순 값 형식의 int 핸들이나 Ansi 마샬링으로 되돌려서는 안 되며, 반드시 이 명세를 유지해야 합니다.** |
|||
|
|||
--- |
|||
|
|||
## 1. 연동 핵심 원칙 (Core Rules) |
|||
|
|||
1. **IntPtr 기반의 기기 세션 핸들 관리**: |
|||
- `InitMarkEzd()` 함수를 최초 실행하여 생성되는 장치 관리 메모리 세션 포인터(`IntPtr`)를 받아 전역 변수에 저장합니다. |
|||
- 이후 모든 연동 API(`Init`, `LoadEzdFile`, `ChangeTextByName`, `Mark`, `Close`)의 첫 번째 매개변수로 이 `IntPtr` 핸들을 인계하여 호출해야 합니다. 임의의 정수 값(`0` 등)이나 `ref int` 를 대입하여 호출하면 메모리 위반 크래시(`AccessViolationException`)가 발생합니다. |
|||
|
|||
2. **유니코드(`CharSet.Unicode`) 마샬링 준수**: |
|||
- C++ DLL 단의 모든 문자열 인자는 `const wchar_t*` (유니코드)를 사용합니다. |
|||
- 따라서 모든 DllImport 선언의 문자셋 속성은 반드시 **`CharSet = CharSet.Unicode`** 여야 합니다. `Ansi`로 지정할 시 경로명 및 파일명이 한자 깨진 글자로 읽혀 `EZCAD.CFG failed` 에러를 냅니다. |
|||
|
|||
3. **WPF 윈도우 핸들(HWND) 지연 초기화**: |
|||
- `Init` API 호출 시 실제 유효한 부모 윈도우 핸들(`IntPtr windowHandle`)이 필요합니다. |
|||
- MainWindow의 생성자 시점에는 핸들이 미생성 상태(`IntPtr.Zero`)이므로 즉시 초기화하면 안 됩니다. |
|||
- 반드시 WPF **`Dispatcher.BeginInvoke(..., DispatcherPriority.Loaded)`** 지연 큐를 활용하여 메인 윈도우 로드가 완료된 후에 유효한 창 핸들을 추출해 이니셜라이즈 해야 합니다. |
|||
|
|||
--- |
|||
|
|||
## 2. P/Invoke 표준 선언부 (Standard C# Declarations) |
|||
|
|||
```csharp |
|||
[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 ChangeTextByName(IntPtr hHandle, string strTextName, string strTextNew); |
|||
|
|||
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Mark", CallingConvention = CallingConvention.Cdecl)] |
|||
private static extern int Mark(IntPtr hHandle); |
|||
|
|||
[DllImport("MarkEzdWrapper.dll", EntryPoint = "Close", CallingConvention = CallingConvention.Cdecl)] |
|||
private static extern int Close(IntPtr hHandle); |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 3. 핵심 비즈니스 흐름 코드 (Core Implementation Patterns) |
|||
|
|||
### 3.1. 장치 초기화 흐름 |
|||
```csharp |
|||
// 1. 선행 엔진 초기화 및 포인터 획득 |
|||
IntPtr markingHandle = InitMarkEzd(); |
|||
if (markingHandle == IntPtr.Zero) |
|||
{ |
|||
// 보드 또는 동글 락키 인식 실패 예외 처리 |
|||
return false; |
|||
} |
|||
|
|||
// 2. WPF 메인 윈도우 실제 창 핸들 획득 (Loaded 시점) |
|||
IntPtr windowHandle = new System.Windows.Interop.WindowInteropHelper(this).Handle; |
|||
|
|||
// 3. 컨트롤러 장비 초기화 수행 |
|||
int initResult = Init(markingHandle, ezcadFolderPath, windowHandle); |
|||
if (initResult == 0) |
|||
{ |
|||
// 연결 완료 상태 전환 |
|||
} |
|||
``` |
|||
|
|||
### 3.2. 공정 각인 요청 흐름 |
|||
```csharp |
|||
// 1. 도안 로드 |
|||
int loadResult = LoadEzdFile(markingHandle, absoluteEzdPath); |
|||
|
|||
// 2. 도안 내 변수 태그 치환 (Marking.ini 매핑 기준) |
|||
ChangeTextByName(markingHandle, "SERIAL", request.Serial); |
|||
ChangeTextByName(markingHandle, "YYMMDD", request.LotNo); |
|||
|
|||
// 3. 각인 기계 동작 기동 |
|||
int markResult = Mark(markingHandle); |
|||
``` |
|||
@ -0,0 +1,23 @@ |
|||
{ |
|||
"loginAccounts": [ |
|||
{ |
|||
"id": "su", |
|||
"password": "su" |
|||
} |
|||
], |
|||
"makers": [ |
|||
"AMO", |
|||
"ABC" |
|||
], |
|||
"models": [ |
|||
"MODEL-1" |
|||
], |
|||
"variant1Values": [], |
|||
"variant2Values": [], |
|||
"lineValues": [ |
|||
"LINE-1" |
|||
], |
|||
"jigNoValues": [ |
|||
"JIG-1" |
|||
] |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,3 @@ |
|||
{ |
|||
"spellcheck": false |
|||
} |
|||
@ -0,0 +1 @@ |
|||
{} |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"file-explorer": true, |
|||
"global-search": true, |
|||
"switcher": true, |
|||
"graph": true, |
|||
"backlink": true, |
|||
"canvas": true, |
|||
"outgoing-link": true, |
|||
"tag-pane": true, |
|||
"footnotes": false, |
|||
"properties": true, |
|||
"page-preview": true, |
|||
"daily-notes": true, |
|||
"templates": true, |
|||
"note-composer": true, |
|||
"command-palette": true, |
|||
"slash-command": false, |
|||
"editor-status": true, |
|||
"bookmarks": true, |
|||
"markdown-importer": false, |
|||
"zk-prefixer": false, |
|||
"random-note": false, |
|||
"outline": true, |
|||
"word-count": true, |
|||
"slides": false, |
|||
"audio-recorder": false, |
|||
"workspaces": false, |
|||
"file-recovery": true, |
|||
"publish": false, |
|||
"sync": true, |
|||
"bases": true, |
|||
"webviewer": false |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
{ |
|||
"main": { |
|||
"id": "e986c9dffdb55d9e", |
|||
"type": "split", |
|||
"children": [ |
|||
{ |
|||
"id": "e5576011528e6b5c", |
|||
"type": "tabs", |
|||
"children": [ |
|||
{ |
|||
"id": "b98d55f22f4d8058", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "markdown", |
|||
"state": { |
|||
"file": "02_초기_설정.md", |
|||
"mode": "source", |
|||
"source": false |
|||
}, |
|||
"icon": "lucide-file", |
|||
"title": "02_초기_설정" |
|||
} |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"direction": "vertical" |
|||
}, |
|||
"left": { |
|||
"id": "c57355fcc7fdff6f", |
|||
"type": "split", |
|||
"children": [ |
|||
{ |
|||
"id": "0dd5370634e2a0cb", |
|||
"type": "tabs", |
|||
"children": [ |
|||
{ |
|||
"id": "34581207ae14950d", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "file-explorer", |
|||
"state": { |
|||
"sortOrder": "alphabetical", |
|||
"autoReveal": false |
|||
}, |
|||
"icon": "lucide-folder-closed", |
|||
"title": "파일 탐색기" |
|||
} |
|||
}, |
|||
{ |
|||
"id": "9392a937e5fa675d", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "search", |
|||
"state": { |
|||
"query": "", |
|||
"matchingCase": false, |
|||
"explainSearch": false, |
|||
"collapseAll": false, |
|||
"extraContext": false, |
|||
"sortOrder": "alphabetical" |
|||
}, |
|||
"icon": "lucide-search", |
|||
"title": "검색" |
|||
} |
|||
}, |
|||
{ |
|||
"id": "885558dab49fcbe9", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "bookmarks", |
|||
"state": {}, |
|||
"icon": "lucide-bookmark", |
|||
"title": "북마크" |
|||
} |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"direction": "horizontal", |
|||
"width": 300 |
|||
}, |
|||
"right": { |
|||
"id": "99e0f4ec73247bac", |
|||
"type": "split", |
|||
"children": [ |
|||
{ |
|||
"id": "e73c85dfbcab7caf", |
|||
"type": "tabs", |
|||
"children": [ |
|||
{ |
|||
"id": "563edc0360ae71a5", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "backlink", |
|||
"state": { |
|||
"file": "06_데이터_조회.md", |
|||
"collapseAll": false, |
|||
"extraContext": false, |
|||
"sortOrder": "alphabetical", |
|||
"showSearch": false, |
|||
"searchQuery": "", |
|||
"backlinkCollapsed": false, |
|||
"unlinkedCollapsed": true |
|||
}, |
|||
"icon": "links-coming-in", |
|||
"title": "06_데이터_조회 의 백링크" |
|||
} |
|||
}, |
|||
{ |
|||
"id": "5a190c7cdaac43a6", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "outgoing-link", |
|||
"state": { |
|||
"file": "06_데이터_조회.md", |
|||
"linksCollapsed": false, |
|||
"unlinkedCollapsed": true |
|||
}, |
|||
"icon": "links-going-out", |
|||
"title": "06_데이터_조회 의 나가는 링크" |
|||
} |
|||
}, |
|||
{ |
|||
"id": "b2a637895408e226", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "tag", |
|||
"state": { |
|||
"sortOrder": "frequency", |
|||
"useHierarchy": true, |
|||
"showSearch": false, |
|||
"searchQuery": "" |
|||
}, |
|||
"icon": "lucide-tags", |
|||
"title": "태그" |
|||
} |
|||
}, |
|||
{ |
|||
"id": "c2aa104400708a18", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "all-properties", |
|||
"state": { |
|||
"sortOrder": "frequency", |
|||
"showSearch": false, |
|||
"searchQuery": "" |
|||
}, |
|||
"icon": "lucide-archive", |
|||
"title": "모든 속성" |
|||
} |
|||
}, |
|||
{ |
|||
"id": "210708f9a623a5be", |
|||
"type": "leaf", |
|||
"state": { |
|||
"type": "outline", |
|||
"state": { |
|||
"file": "06_데이터_조회.md", |
|||
"followCursor": false, |
|||
"showSearch": false, |
|||
"searchQuery": "" |
|||
}, |
|||
"icon": "lucide-list", |
|||
"title": "06_데이터_조회 의 개요" |
|||
} |
|||
} |
|||
] |
|||
} |
|||
], |
|||
"direction": "horizontal", |
|||
"width": 300, |
|||
"collapsed": true |
|||
}, |
|||
"left-ribbon": { |
|||
"hiddenItems": { |
|||
"switcher:빠른 전환기 열기": false, |
|||
"graph:그래프 뷰 열기": false, |
|||
"canvas:새 캔버스 만들기": false, |
|||
"daily-notes:오늘의 일일 노트 열기": false, |
|||
"templates:템플릿 삽입": false, |
|||
"command-palette:명령어 팔레트 열기": false, |
|||
"bases:새 베이스 생성하기": false |
|||
} |
|||
}, |
|||
"active": "b98d55f22f4d8058", |
|||
"lastOpenFiles": [ |
|||
"Manual_for_pdf.html", |
|||
"05_시험_설정.md", |
|||
"04_통신_설정.md", |
|||
"03_메인_화면.md", |
|||
"02_초기_설정.md", |
|||
"01_시스템_개요.md", |
|||
"06_데이터_조회.md" |
|||
] |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
# 1. 시스템 개요 및 요구사항 |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 1.1 시스템 개요 |
|||
|
|||
**Performance Inspect & Laser Marking System**은 온압센서 완제품의 최종 성능 검사를 수행하고, 이전 공정 단계들의 합격(PASS) 이력을 조회하여 최종 적합 제품에 한해 제품 표면에 레이저 마킹을 수행하는 시스템 제어 프로그램입니다. |
|||
|
|||
본 프로그램은 측정 계측기와 센서 판독기, 레이저 각인 장치 및 공장 생산 데이터베이스와 연동되어 작동합니다. |
|||
|
|||
### 주요 기능 요약 |
|||
|
|||
| 기능 | 설명 | |
|||
|------|------| |
|||
| **일련번호(S/N) 자동 추출** | 센서 판독 보드를 통해 제품 안착 시 제품 내부 메모리로부터 일련번호를 추출합니다. | |
|||
| **선행 공정 검사 교차 조회** | 이전 단계(하우징 조립, 센서 보정, 1차 EOL 성능 검사)가 모두 합격 판정되었는지 생산 데이터베이스에서 조회합니다. | |
|||
| **자동 계측 시퀀스** | 전원 공급 장치와 전압/저항 측정 장비들과 연동하여 제품에 테스트 전원을 투입하고 전압, 저항, 전류 값을 차례대로 계측합니다. | |
|||
| **실제 저항값 측정** | 전압/저항 DMM 측정기를 통해 센서의 실제 저항값(Ω)을 측정합니다. | |
|||
| **전류 측정** | 전원 공급 장치(Power Supply)의 출력 채널 1을 통해 제품의 소모 전류를 계측합니다. | |
|||
| **레이저 각인 연동** | 성능 검사가 모두 통과된 합격품에 대해 제품 표면에 2D QR 코드 및 단축 일련번호(생산일자 + 순번)를 마킹합니다. | |
|||
| **결과 기록** | 계측 판정 규격(전압, 전류, 저항)과 마킹 성공 여부를 최종 판정하여 생산 데이터베이스에 저장합니다. | |
|||
|
|||
--- |
|||
|
|||
## 1.2 소프트웨어 요구사항 |
|||
|
|||
| 항목 | 요구사항 | 비고 | |
|||
|------|----------|------| |
|||
| **통합 설치 프로그램** | `MarkingSetup.exe` (WiX 번들) | 1-Click 자동 설치 및 실행 환경, 드라이버, 설정 일체 셋업 | |
|||
| **운영체제** | Windows 10 이상 | 프로그램 구동 및 장비 드라이버 운용용 | |
|||
| **데이터베이스** | Microsoft SQL Server (MS-SQL) | 생산 공정 데이터 및 계측 결과 연동용 | |
|||
| **레이저 제어 프로그램** | EZCAD 각인 제어 프로그램 및 드라이버 | 레이저 마킹기 구동 및 전용 도면(.ezd) 운용용 | |
|||
| **네트워크 환경** | LAN (TCP/IP) 통신 | 제어 PC와 측정 기기 간의 연결 | |
|||
| **센서 보드 통신** | COM 포트 (RS-232 시리얼) | 4251 센서 통신 보드 연동 | |
|||
|
|||
--- |
|||
|
|||
## 1.3 하드웨어 구성 |
|||
|
|||
| 장비 | 역할 | 통신 방식 | |
|||
|------|------|-----------| |
|||
| **센서 판독 보드 (4251 보드)** | 제품 내부 칩의 일련번호(IC_SN)를 인식합니다. | RS-232 시리얼 통신 | |
|||
| **전압 및 저항 측정 장비 (DMM)** | 제품의 전압(V) 및 전기적 저항(Ω)을 측정합니다. (예: 192.168.1.100) | TCP/IP 네트워크 통신 | |
|||
| **전류 측정 및 전원 공급 장비 (PSU)** | 제품 구동을 위한 전원 공급 및 소모 전류(A)를 측정합니다. (예: 192.168.1.101) | TCP/IP 네트워크 통신 | |
|||
| **레이저 마킹기** | 2D QR 코드 및 텍스트 일련번호를 제품 표면에 인쇄합니다. | 마킹 제어 보드 연동 | |
|||
| *(전류 측정 DMM)* | *설정 파일(예: 192.168.1.102)에 존재하나 현재 제어 시퀀스에서는 사용하지 않습니다.* | *(미사용)* | |
|||
|
|||
## 1.4 설치 경로(`C:\marking\`) 구조 및 생성 파일 역할 |
|||
|
|||
단일 통합 설치 마법사(`MarkingSetup.exe`)를 통해 시스템을 설치하면 기본 설치 디렉터리(`C:\marking\`) 아래에 다음과 같은 실행 바이너리, 설정 파일, 드라이버 라이브러리 및 런타임 로그 폴더가 배치·생성됩니다. |
|||
|
|||
| 구분 | 파일 / 폴더명 | 상세 역할 및 기능 설명 | |
|||
|------|----------------|------------------------| |
|||
| **실행 프로그램** | `marking_gui.exe` | 메인 성능 검사 및 레이저 마킹 GUI 제어 실행 파일 | |
|||
| **종속 라이브러리** | `marking_gui.dll`, `*.deps.json`, `*.runtimeconfig.json` | .NET 9.0 (WPF) 자립형 런타임 및 종속 구성 바이너리 | |
|||
| **통합 설정 파일** | `Setting.ini` | 마킹기 폴더 경로, 테스트 모드, 도안 태그 매핑, 계측기 LAN IP, SCPI 전원 커맨드, 계측 판정 규격 임계치(`[Limits]`) 종합 설정 파일 | |
|||
| **DB 설정 파일** | `Database.ini` | MS-SQL 데이터베이스 접속 주소, DB명, 사용자 계정/PW, 오프라인 모드(`OfflineMode=true`) 설정 파일 | |
|||
| **센서 설정 파일** | `Sensor.ini` | 4251 센서 통신 보드 시리얼 포트(`Port=COM3`), 통신 속도(`BaudRate=115200`), 통신 채널(`Channel=1`) 설정 파일 | |
|||
| **드라이버 폴더** | `libs/` | C++ LMC 각인 드라이버 격리 디렉터리 (`MarkEzdWrapper.dll`, `DataMgr.dll`, `MarkEzd.dll`, `haspms32.dll` 등) | |
|||
| **로그 저장 폴더** | `logs/` *(자동 생성)* | 시스템 운용 중 발생하는 일별 이벤트 로그, 통신 이력, 각인 성공/실패 기록 텍스트 저장 디렉터리 (예: `logs/2026-07-23.log`) | |
|||
| **백업 보관 폴더** | `publish_backup/` | 프로그램 업데이트 및 빌드 배포 시 이전 릴리즈 바이너리/설정 자동 백업 폴더 | |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,117 @@ |
|||
# 2. 초기 설정 가이드 |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 2.1 프로그램 설정 구성 개요 |
|||
|
|||
본 프로그램은 정상적인 계측기 통신 및 데이터베이스 연동을 위해 몇 가지 설정 파일을 사용합니다. 이 설정 파일들은 프로그램 설치 및 라인 도입 시 최초 1회 셋업을 원칙으로 하며, 일반 운영자가 직접 설정 파일을 열어 수정할 필요는 없습니다. |
|||
|
|||
*참고: 대부분의 검사 기준 및 통신 정보는 프로그램 내의 **'통신 설정'** 및 **'시험 설정'** 화면을 통해 수정할 수 있습니다.* |
|||
|
|||
### 2.1.1 주요 설정 정보 구분 |
|||
|
|||
1. **장비 및 계측 설정** |
|||
- 계측기들과의 네트워크 연결 주소와 대기 시간 등을 정의합니다. |
|||
- 제품 합격 여부를 판정하는 전압, 전류, 저항의 기본 합격 규격 범위가 이 파일에 저장되며, 화면 내의 **'시험 설정'** 창에서 수정한 사항이 이 파일에 동적으로 반영됩니다. |
|||
- 프로그램은 전압/저항 측정 장치와 전원/전류 공급 장치를 제어하여 계측을 진행합니다. |
|||
|
|||
2. **생산 데이터베이스 연동 설정** |
|||
- 공장 생산 관리 시스템 데이터베이스와의 통신 경로가 기록되어 있습니다. |
|||
- 전산망이나 DB 서버 점검 등으로 인해 통신이 어려울 경우, 설정 파일을 통해 **'오프라인 모드'**로 전환하여 단독으로 장비 작동 테스트를 해볼 수 있습니다. |
|||
- **오프라인 로그인 지원**: 데이터베이스 확인 단계 없이 로그인하여 프로그램을 기동합니다. |
|||
- **오프라인 검사 지원**: 제품 이력 조회 및 검사 결과 저장을 건너뛰고 단독으로 계측 및 마킹을 실행합니다. |
|||
|
|||
3. **센서 판독기 설정** |
|||
- 제품 일련번호를 로드하기 위한 통신 채널 및 연결 포트 주소가 정의됩니다. |
|||
- 화면 내의 **'통신 설정'** 창에서 수정한 사항이 이 파일에 자동으로 저장됩니다. |
|||
|
|||
### 2.1.2 설치 경로(`C:\marking\`) 내 파일 배치 구조 |
|||
|
|||
프로그램 설치 완료 후 `C:\marking\` 경로에는 다음과 같이 구동 파일, 설정 파일, 드라이버 라이브러리 및 런타임 자동 생성 디렉터리가 배치됩니다. |
|||
|
|||
* **`C:\marking\marking_gui.exe`**: GUI 제어 메인 실행 파일 |
|||
* **`C:\marking\Setting.ini`**: 장비 통신 IP, 마킹 태그, 규격 임계치(`[Limits]`) 종합 설정 파일 |
|||
* **`C:\marking\Database.ini`**: MS-SQL DB 접속 정보 및 오프라인 모드 설정 파일 |
|||
* **`C:\marking\Sensor.ini`**: 4251 센서 통신 보드 포트/속도/채널 설정 파일 |
|||
* **`C:\marking\libs\`**: C++ LMC 레이저 각인 드라이버 라이브러리 격리 폴더 (`MarkEzdWrapper.dll` 등) |
|||
* **`C:\marking\logs\`**: 런타임 가동 중 자동 생성되는 일별 이력 로그 폴더 (`yyyy-MM-dd.log`) |
|||
* **`C:\marking\publish_backup\`**: 업데이트/배포 시 이전 버전 바이너리 및 설정 자동 백업 폴더 |
|||
|
|||
### 2.1.3 기본적인 설정 파일 편집 방법 |
|||
|
|||
> [!IMPORTANT] |
|||
> **[권장 조치 안내]** |
|||
> 현장 라인 검사자 및 일반 작업자는 프로그램 UI의 **[통신 설정]** 및 **[시험 설정]** 메뉴를 통해 안전하게 파라미터를 변경하십시오. |
|||
> 아래의 `.ini` 파일 직접 수정은 라인 엔지니어 또는 설비 관리자 전용 권한 작업이며, 잘못된 파일 수정 시 장비 통신 오류가 발생할 수 있습니다. |
|||
|
|||
설비 이동이나 네트워크 환경 변경 시, 프로그램 폴더 내의 각 `.ini` 파일을 텍스트 편집기(메모장 등)로 열어 아래의 전체 설정 레이아웃 항목을 참조하여 수정할 수 있습니다. |
|||
|
|||
#### 1) Setting.ini (주요 변경 가능 설정) |
|||
현장 네트워크 IP, 도안 파일 경로 및 검사 규격(임계치) 변경 시 수정하는 주요 설정 항목입니다. |
|||
```ini |
|||
[Settings] |
|||
EzdFolderPath=c:\EzCad\EasyCfg ; EZD 도안 파일 기본 탐색/저장 폴더 경로 |
|||
test=false ; 테스트 마킹 버튼 및 개발 모드 노출 여부 (true/false) |
|||
|
|||
[DMM] |
|||
VoltageHost=192.168.1.100 ; 전압/저항 측정용 계측기(DMM) IP 주소 |
|||
|
|||
[CurrentDMM] |
|||
CurrentDMMHost=192.168.1.102 ; 전류 측정용 계측기(DMM) IP 주소 |
|||
|
|||
[PowerSupply] |
|||
CurrentHost=192.168.1.101 ; 전원 공급기(Power Supply) IP 주소 |
|||
|
|||
[Limits] |
|||
MinVoltage=4.0 ; 전압 하한 판정 기준값 (V) |
|||
MaxVoltage=6.0 ; 전압 상한 판정 기준값 (V) |
|||
MinCurrent=8.0 ; 전류 하한 판정 기준값 (mA) |
|||
MaxCurrent=10.0 ; 전류 상한 판정 기준값 (mA) |
|||
MinResistance=0.4 ; 저항 하한 판정 기준값 (kΩ) |
|||
MaxResistance=0.8 ; 저항 상한 판정 기준값 (kΩ) |
|||
``` |
|||
|
|||
#### 2) Database.ini (주요 변경 가능 설정) |
|||
DB 서버 접속 주소 및 점검용 오프라인 모드 변경 시 수정하는 항목입니다. |
|||
```ini |
|||
[Database] |
|||
Db_Server=192.168.1.200 ; MSSQL 데이터베이스 서버 IP 주소 |
|||
Db_Name=MarkingDb ; 연결할 데이터베이스 이름 |
|||
Db_User=db_user ; DB 접속 사용자 계정 |
|||
Db_Password=db_password ; DB 접속 비밀번호 |
|||
OfflineMode=False ; DB 미연결 점검 모드 (True: DB 저장 생략, False: 정상 검증/적재) |
|||
|
|||
[Login] |
|||
OfflinePreview=False ; 로그인 DB 검증 우회 여부 (True: 로그인 생략, False: 정상 검증) |
|||
``` |
|||
|
|||
#### 3) Sensor.ini (주요 변경 가능 설정) |
|||
바코드 스캐너 시리얼 포트 및 채널 설정 항목입니다. |
|||
```ini |
|||
[Sensor] |
|||
Port=COM3 ; 바코드 스캐너 시리얼 포트 (장치 관리자 COM 포트 번호) |
|||
Channel=1 ; 통신 채널 번호 (1 또는 2) |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 2.2 최초 실행 및 장비 점검 순서 |
|||
|
|||
라인 가동 전 최초 실행할 때는 아래 단계를 순서대로 이행하여 정상 작동 여부를 점검하십시오. |
|||
|
|||
1. **프로그램 단일 설치 (MarkingSetup.exe)** |
|||
- 배포받은 단일 설치 마법사 `MarkingSetup.exe`를 실행하여 1-Click으로 `C:\marking\` 설치 및 바탕화면 바로가기를 자동 생성합니다. |
|||
2. **데이터베이스 연결 상태 확인** |
|||
- 데이터베이스가 점검 중인 경우 설정 파일을 통해 오프라인 모드로 설정하면 로그인 창을 통과하여 단독 테스트를 진행할 수 있습니다. |
|||
3. **장비 네트워크 통신 점검** |
|||
- 제어 PC와 계측 장비들(전압/저항 측정 장비, 전원 공급 장치) 간의 LAN 케이블 연결을 확인합니다. |
|||
- 제어 PC의 네트워크 IP 환경이 장비들의 대역과 동일한지 확인하고, 통신 신호가 정상적으로 송수신되는지 점검합니다. |
|||
4. **상시전원 자동 인가 확인** |
|||
- 프로그램 실행 후 작업자 계정으로 로그인을 시도합니다. |
|||
- 로그인이 완료되면 전원 공급 장치의 상시전원 채널 전원 램프가 자동으로 켜지는지 확인합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,63 @@ |
|||
# 3. 메인 화면 (Home View) |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 3.1 메인 화면 레이아웃 구성 |
|||
|
|||
본 프로그램은 작업자가 화면 구성 및 각 항목 상태를 파악할 수 있도록 4개의 카드 레이아웃으로 화면을 구성했습니다. |
|||
|
|||
### 3.1.1 상단 헤더 영역 (Header Bar) |
|||
|
|||
프로그램 최상단 영역에는 시스템 정보 배지와 제어 버튼이 배치되어 있습니다. |
|||
* **실시간 시계**: 좌측 상단에 날짜와 시간이 표시됩니다. |
|||
* **작업 정보 배지**: |
|||
* **공정 라인**: 로그인 단계에서 지정한 생산 라인 코드 (`Line No`) |
|||
* **로트 번호**: 로그인 단계에서 지정한 생산 로트 번호 (`Lot No`) |
|||
* **모델명**: 현재 가동 중인 제품의 사양 모델 (`Model`) |
|||
* **작업자**: 로그인한 작업자의 이름 (`Operator`) |
|||
* **제어 버튼**: 우측 상단에 `로그아웃` 버튼이 위치하며 최하단 바에 설정 관련 버튼이 배치됩니다. |
|||
|
|||
--- |
|||
|
|||
## 3.2 상태 및 제어 카드 영역 |
|||
|
|||
화면 중앙에는 역할을 구분한 4개의 상태 카드가 배치되어 있어, 제품 상태와 계측 단계를 모니터링할 수 있습니다. |
|||
|
|||
### 3.2.1 [카드 1] 제품 정보 및 이전 결과 (좌측 상단) |
|||
제품의 일련번호와 이전 생산 공정에서의 합격 이력을 대조하는 영역입니다. |
|||
* **작업 모델 설정**: |
|||
- `파일 선택` 버튼을 사용하여 각인용 도면 파일을 불러옵니다. |
|||
- 도면 파일 선택이 완료되면 상단 헤더 영역의 모델명(Model) 배지 텍스트가 선택한 도면명으로 자동 변경됩니다. |
|||
* **일련번호 (IC_SN)**: 제품이 안착되면 센서 판독기를 통해 자동으로 인식되어 표시됩니다. (읽기 전용) |
|||
* **이전 공정 이력 배지**: |
|||
* **Housing**: 하우징 조립 공정 판정 상태 (`PASS` / `FAIL` / `대기`) |
|||
* **Calibration**: 압력 보정 공정 판정 상태 (`PASS` / `FAIL` / `대기`) |
|||
* **EOL**: EOL 1차 성능 평가 판정 상태 (`PASS` / `FAIL` / `대기`) |
|||
* *주의: 이전 공정 이력 배지 중 하나라도 `FAIL` 상태인 경우 성능 검사를 시작할 수 없습니다.* |
|||
|
|||
### 3.2.2 [카드 2] 측정 결과 (우측 상단) |
|||
현재 장비에서 실제 계측한 3대 전기 파라미터(전압, 전류, 저항) 수치와 설정된 기준 규격 범위를 표시하는 영역입니다. |
|||
* **측정 전압 (Voltage)**: 전압 측정 장치가 측정한 전압 수치 (**V** 단위) |
|||
* **측정 전류 (Current)**: 전원 공급 장치가 측정한 소모 전류 수치 (**mA** 단위) |
|||
* **측정 저항 (Resistance)**: 저항 측정 장치가 측정한 전기적 저항 수치 (**kΩ** 단위) |
|||
* *알림: 각 물리량의 하단에는 현재 적용 중인 기준 규격 범위가 문구(`기준범위: X ~ Y`)로 표출되며, 실측값이 규격 범위 내에 도달하면 카드 테두리가 **초록색(PASS)**으로 표시되고, 범위를 벗어나면 테두리가 **빨간색(FAIL)**으로 바뀝니다.* |
|||
|
|||
### 3.2.3 [카드 3] 진행상황 (좌측 하단) |
|||
현재 설비가 수행하고 있는 단계별 자동 제어 시퀀스를 보여주는 안내 창입니다. |
|||
* "대기 상태", "제품 정보 수집 중...", "이전 공정 검사 결과 조회 중...", "측정 계측기 데이터 수집 중...", "제품 합격 - 레이저 각인 중..." 등 작동 상태를 실시간 텍스트로 표출합니다. |
|||
|
|||
### 3.2.4 [카드 4] 판정결과 (우측 하단) |
|||
제품의 최종 합격(PASS) 및 불합격(FAIL) 상태를 표시합니다. |
|||
* 계측 검사와 데이터 저장, 레이저 각인이 완료되었을 때 최종 합격인 경우 카드 배경이 **초록색(PASS)**으로 전환되며, 불합격인 경우 카드 배경이 **빨간색(FAIL)**으로 변경됩니다. |
|||
|
|||
### 3.2.5 최하단 제어 영역 (Control Box) |
|||
* **검사 시작 (START)**: 전체 검사 시퀀스를 기동하는 메인 버튼입니다. 이 버튼을 누르면 이전 계측 수치들이 초기화되고 새로운 측정 프로세스가 개시됩니다. |
|||
* **강제 검사 (스킵)**: 이전 가공 공정의 합격 이력이 없더라도 검증 단계를 건너뛰고 성능 계측 및 각인 시퀀스를 기동하는 버튼입니다. |
|||
* **테스트 마킹**: 성능 계측 없이 즉시 각인기에 테스트 마킹 신호를 전송하는 버튼입니다. |
|||
* *참고: `강제 검사 (스킵)` 및 `테스트 마킹` 버튼은 환경 설정에서 테스트 모드가 활성화된 상태에서만 화면 하단에 노출됩니다.* |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,37 @@ |
|||
# 4. 통신 설정 (Comm. Settings) |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 4.1 포트 설정 화면 사용법 |
|||
|
|||
프로그램 상단의 `통신 설정` 버튼을 클릭하면 포트 설정 대화 상자가 나타납니다. 이 대화 상자에서 센서 판독 장치(4251 보드)의 연결 포트 및 채널을 설정할 수 있습니다. |
|||
|
|||
### 주요 설정 항목 및 설명 |
|||
|
|||
1. **통신 포트 (Port)**: |
|||
- 센서 판독기가 연결되어 있는 PC의 연결 포트를 선택합니다. (예: `COM1`, `COM3`, `COM4` 등) |
|||
- 현재 PC에 인식되어 있는 포트 목록이 자동으로 표시됩니다. |
|||
|
|||
2. **통신 속도 (BaudRate)**: |
|||
- 센서 판독 장치와의 데이터 송수신 속도를 설정합니다. |
|||
- 기본 설정값은 **`115200`** 이며, 특수한 경우가 아니면 변경하지 않는 것을 권장합니다. |
|||
|
|||
3. **통신 채널 (Channel)**: |
|||
- 센서 판독기 내부의 연결 채널을 결정합니다. |
|||
- 드롭다운 메뉴를 통해 **`CH1`** 또는 **`CH2`**를 선택할 수 있습니다. |
|||
- 선택된 채널에 따라 센서 인식 모드가 변경됩니다. |
|||
|
|||
--- |
|||
|
|||
## 4.2 설정 저장 |
|||
|
|||
* **설정 저장**: |
|||
- 통신 포트와 채널을 선택한 후 `저장` 버튼을 누르면 설정 정보가 저장됩니다. |
|||
- 저장 시 기존 센서 연결을 해제하고 새로운 설정값으로 센서 인식 서비스를 다시 시작합니다. 프로그램을 재시작할 필요 없이 변경 사항이 즉시 적용됩니다. |
|||
- 저장하지 않고 창을 닫으려면 `취소` 버튼을 누릅니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,44 @@ |
|||
# 5. 시험 설정 (Parameters) |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 5.1 판정 기준 설정 |
|||
|
|||
프로그램 상단 우측의 `시험 설정` 버튼을 클릭하면 판정 기준을 구성하는 대화 상자가 나타납니다. 이 화면에서 제품 합불 판정에 사용되는 전압, 전류, 저항의 기준값을 입력할 수 있습니다. |
|||
|
|||
### 5.1.1 각 항목별 한계치 입력 가이드 |
|||
|
|||
* **전압 판정 범위**: |
|||
* **하한값**: 합격 전압 하한 규격 (V 단위) |
|||
* **상한값**: 합격 전압 상한 규격 (V 단위) |
|||
* **전류 판정 범위**: |
|||
* **하한값**: 합격 전류 하한 규격 (설정창 표기 단위 참조, 기본 mA/A) |
|||
* **상한값**: 합격 전류 상한 규격 (설정창 표기 단위 참조, 기본 mA/A) |
|||
* **저항 판정 범위**: |
|||
* **하한값**: 합격 저항 하한 규격 (설정창 표기 단위 참조, 기본 Ω/kΩ) |
|||
* **상한값**: 합격 저항 상한 규격 (설정창 표기 단위 참조, 기본 Ω/kΩ) |
|||
|
|||
*참고: 저장 버튼을 클릭하면 메인 화면의 하단 가이드 문구(`기준범위: X ~ Y`)가 즉시 갱신되어 새로 입력한 한계치가 다음 검사 시퀀스부터 반영됩니다.* |
|||
|
|||
--- |
|||
|
|||
## 5.2 레이저 각인 도면 지정 |
|||
|
|||
* **각인 파일 설정 경로**: |
|||
* 레이저 마킹기에서 사용할 작업 도면 파일 선택은 설정 대화 상자가 아닌, **메인 화면 좌측 상단의 '작업 모델 설정' 영역에 있는 '파일 선택' 버튼**을 클릭하여 수행합니다. |
|||
* 도면이 선택되면 상단 헤더 배지의 모델명 정보도 해당 도면 파일명으로 자동으로 변경됩니다. |
|||
* **유의 사항**: |
|||
* 지정해 놓은 도면 파일이 실제 경로에 존재하지 않는 경우, 계측 성능 검사가 합격하더라도 각인 단계에서 에러가 납니다. 검사 전 파일 경로 상태를 확인하십시오. |
|||
|
|||
--- |
|||
|
|||
## 5.3 설정 저장 및 적용 |
|||
|
|||
* 설정 창의 `저장` 버튼을 클릭하면 변경된 파라미터가 시스템 설정에 저장됩니다. |
|||
* 저장 완료 즉시 **메인 화면 하단에 표시되는 판정 기준 가이드 텍스트**가 업데이트되며, 이후에 새로 시작하는 성능 검사 시퀀스부터 새로운 규격치가 적용됩니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,53 @@ |
|||
# 6. 측정 데이터 조회 및 데이터베이스 연동 |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 6.1 선행 공정 결과 조회 (이력 확인) |
|||
|
|||
본 프로그램은 검사 시작 시 입력된 제품 일련번호를 기반으로 생산 데이터베이스에 접속하여 이전 제조 공정의 합격 여부를 조회합니다. |
|||
|
|||
### 6.1.1 이력 검토 대상 공정 |
|||
|
|||
시스템은 다음 3개의 선행 공정 검사 결과를 확인합니다. |
|||
1. **하우징 조립 공정** |
|||
2. **센서 오차 보정 공정** |
|||
3. **1차 EOL 성능 검사** |
|||
|
|||
### 6.1.2 이전 단계 규격 교차 확인 동작 |
|||
* 이전 3개 선행 단계의 이력이 **모두 합격(PASS 또는 OK)**된 제품인 경우에만 최종 성능검사(EOL2)를 진행할 수 있습니다. |
|||
* 선행 이력이 존재하지 않거나, 단 한 곳이라도 불합격(FAIL 또는 NG) 판정을 받은 경우 화면 진행 상황 표시창에 경고가 표시되며 최종 성능검사 시작이 제한됩니다. |
|||
|
|||
--- |
|||
|
|||
## 6.2 검사 결과 자동 적재 및 최종 판정 기록 |
|||
|
|||
자동 계측 프로세스가 종료되면 다음 정보가 생산 데이터베이스에 저장됩니다. |
|||
|
|||
* **저장 정보**: |
|||
- 제품 일련번호 |
|||
- 생산 라인, 로트 번호, 작업자 정보 |
|||
- 실측 전압, 전류, 저항값 |
|||
- 실측값은 데이터베이스 저장 규격에 맞춰 시스템 내부에서 소수점 이하 자리로 정밀 정리되어 저장됩니다. |
|||
- 최종 판정 결과 (`PASS` / `FAIL`) |
|||
- 마킹 시퀀스 번호 및 성공 기록 |
|||
* **비동기 데이터 처리**: |
|||
- 데이터베이스 통신 대기로 인한 화면 멈춤 현상을 방지하기 위해 데이터 조회 및 저장 작업은 프로그램 화면 동작과 별개로 백그라운드에서 비동기식으로 안전하게 처리됩니다. |
|||
|
|||
--- |
|||
|
|||
## 6.3 오프라인 모드 운용 |
|||
|
|||
데이터베이스 서버 접속이 불가능한 환경에서도 단독으로 설비를 가동할 수 있도록 **오프라인 모드**를 지원합니다. |
|||
|
|||
* **활성화 목적**: |
|||
- 네트워크 연결이 끊긴 상태에서 프로그램의 단독 동작 및 장비 제어 상태를 확인하기 위함입니다. |
|||
* **오프라인 작동 패턴**: |
|||
- **공정 조회 우회**: 입력된 일련번호에 대해 생산 데이터베이스 서버 접속 없이 이전 공정을 합격한 것으로 우회 처리합니다. |
|||
- **임시 일련번호 생성**: 일련번호가 비어 있는 상태에서 테스트를 개시하는 경우 현재 시간 기반의 임시 일련번호가 자동으로 부여되어 진행합니다. |
|||
- **각인 모사**: 실제 각인기에 데이터를 전송하는 단계를 가상 성공 처리하여 전체 흐름을 테스트합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,75 @@ |
|||
# 7. 자동 시험 프로세스 및 15단계 시퀀스 |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 7.1 자동 시험 및 마킹 프로세스 개요 |
|||
|
|||
본 프로그램은 사용자가 메인 화면 하단의 `검사 시작 (START)` 버튼을 누르면 데이터 저장까지의 과정이 자동 계측 시퀀스에 따라 순차적으로 동작하도록 구성되어 있습니다. |
|||
|
|||
```mermaid |
|||
graph TD |
|||
A[START 버튼 클릭] --> B[UI 화면 수치 초기화] |
|||
B --> C[4~8단계: 센서 S/N 읽기 및 보정] |
|||
C --> D{선행 공정 이력 확인} |
|||
D -- 불합격/미진행 --> E[검사 중단 & 경고 팝업] |
|||
E --> F{강제 검사 스킵?} |
|||
F -- 취소 --> Z[대기 복구] |
|||
F -- 스킵 실행 --> G[9~15단계: 계측 시퀀스 기동] |
|||
D -- 3개 공정 모두 PASS --> G |
|||
G --> H[10단계: 테스트 주전원 ON] |
|||
H --> I[12~14단계: 전압 / 저항 / 전류 실측] |
|||
I --> J[15단계: 테스트 주전원 안전 차단] |
|||
J --> K{최종 규격 비교 판정} |
|||
K -- 1개 이상 이탈 FAIL --> L[대형 FAIL 표시 & 마킹 제외 & DB 불합격 적재] |
|||
K -- 모두 통과 PASS --> M[대형 PASS 표시 & DB 합격 적재 & LMC1 레이저 QR 각인] |
|||
L --> Z |
|||
M --> Z |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 7.2 상세 15단계 자동 제어 시퀀스 |
|||
|
|||
최종 검사가 시작되면 장비와 계측기들은 다음 15가지 단계에 따라 동작을 차례대로 수행합니다. |
|||
|
|||
### [1단계] 사전 전원 인가 단계 (최초 가동/로그인 시 1회 진행) |
|||
* **1단계 [장비 확인]**: 전원 공급 장치와의 통신 연결 상태를 점검합니다. |
|||
* **2단계 [센서 구동 전압 설정]**: 센서 보드를 구동하는 데 필요한 전압을 전원 장치에 설정합니다. |
|||
* **3단계 [센서 구동 전원 출력]**: 설정된 전원을 출력하여 보드를 부팅합니다. |
|||
* *(참고: 이 단계는 로그인 성공 시 1회만 실행되며, 이후의 반복 검사 과정에서는 이미 투입된 전원을 재사용하여 4단계부터 즉각 검사가 수행됩니다)* |
|||
|
|||
### [2단계] 제품 일련번호 수집 및 센서 통신 대기 단계 |
|||
* **4단계 [판독 장치 대기]**: 센서 판독 장치를 초기 대기 상태로 설정합니다. |
|||
* **5단계 [보드 통신 연결]**: 통신 설정에 명시된 채널을 선택하여 센서 보드와 연결합니다. |
|||
* **6단계 [일련번호 읽기]**: 제품 메모리로부터 스캔한 고유 일련번호를 로드합니다. |
|||
* **7단계 [보드 통신 해제]**: 센서 데이터 전송을 중지하고 대기 상태로 되돌립니다. |
|||
* **8단계 [보정 기준 전송]**: 센서 장치에 보정 기준값을 인계하고 동작을 종료합니다. |
|||
|
|||
### [3단계] 계측기 연동 성능 평가 및 전원 차단 단계 |
|||
* **9단계 [전원 장비 확인]**: 주 테스트 전원을 공급할 전원 장치의 통신 상태를 확인합니다. |
|||
* **10단계 [테스트 전원 인가]**: 테스트 전원 출력을 ON시키고, 전원 인가 후 신호 안정을 위해 잠시 대기합니다. |
|||
* **11단계 [측정 장비 확인]**: 측정 장치의 통신 상태를 확인합니다. |
|||
* **12단계 [전압 측정]**: 제품의 현재 작동 전압을 측정합니다. |
|||
* **13단계 [저항 측정]**: 제품의 전기적 저항값을 직접 실측합니다. |
|||
* **14단계 [전류 측정]**: 전원 공급 장치의 출력 채널을 통해 제품의 작동 소모 전류를 측정합니다. |
|||
* **15단계 [테스트 전원 차단]**: 수집 완료 후 테스트 전원 출력을 자동으로 차단하여 제품을 안전하게 보호합니다. (계측 도중 오류가 발생하더라도 강제로 전원이 차단되도록 안전 장치가 적용되어 있습니다.) |
|||
|
|||
--- |
|||
|
|||
## 7.3 최종 판정 및 마킹 실행 조건 |
|||
|
|||
계측이 완료되면 측정된 전압(V), 저항(kΩ), 전류(mA) 값을 설정한 기준 규격값(SPEC)과 비교하여 최종 판정을 내립니다. |
|||
|
|||
1. **기준 규격을 벗어난 경우 (FAIL)**: |
|||
* 전압, 전류, 저항 중 하나라도 기준을 벗어나면 최종 불합격(FAIL) 판정이 내려집니다. |
|||
* 이 경우 레이저 마킹 장비 구동은 자동으로 제외(Skip)되며, 불합격 내역으로 DB에 기록됩니다. |
|||
2. **모든 항목이 합격인 경우 (PASS)**: |
|||
* 모든 수치가 기준치 내에 들어오면 최종 합격(PASS) 판정이 내려집니다. |
|||
* 합격 판정과 동시에 레이저 마킹기에 각인 데이터가 전달되어 2D QR 코드 및 제품 일련번호 각인이 자동으로 실행됩니다. |
|||
* 마킹 완료 기록과 계측 수치는 최종 PASS 상태로 데이터베이스에 저장됩니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,39 @@ |
|||
# 8. 로그 및 데이터 관리 |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 8.1 시스템 로그 수집 및 관리 |
|||
|
|||
본 제어 프로그램은 설비 가동 중에 발생하는 계측기와의 통신 상태, 측정값 정보 및 각종 예외 오류 상황을 로그 파일로 기록합니다. |
|||
|
|||
### 8.1.1 로그 파일 보관 방법 |
|||
|
|||
* **보관 폴더**: 프로그램 실행 파일 경로의 하위 **`Logs`** 폴더에 저장됩니다. |
|||
* **파일명 규칙**: 날짜별로 파일이 자동으로 생성되어 보관됩니다. |
|||
* **로그 중요도 분류**: |
|||
* **정보 (INFO)**: 정상적인 검사 프로세스 시작, 계측기 연결 성공, 레이저 인쇄 성공 및 데이터베이스 저장 완료 기록. |
|||
* **경고 (WARN)**: 센서 판독기 인식 지연, 제품 한계 기준치를 벗어난 불합격(FAIL) 발생 기록 등 설비 동작은 유지되나 품질 확인이 필요한 정보. |
|||
* **오류 (ERROR)**: 데이터베이스 네트워크 접속 끊김, 마킹 장치 연결 실패 등 조치가 필요한 장비 오류 정보. |
|||
|
|||
--- |
|||
|
|||
## 8.2 장비 교체 및 프로그램 백업 방법 |
|||
|
|||
장비를 교환하거나 PC 복구 상황에 대비하여, 정상 작동 상태에서의 설정 파일들을 정기적으로 백업해 둘 것을 권장합니다. |
|||
|
|||
### 8.2.1 백업 대상 리스트 |
|||
|
|||
1. **계측기 설정 및 검사 기준값 백업**: |
|||
* 계측기들의 연결 설정 정보와 합격 판정 기준 범위가 저장됩니다. |
|||
2. **데이터베이스 서버 정보 백업**: |
|||
* 생산 정보 데이터베이스 서버 주소와 로그인 정보가 저장됩니다. |
|||
3. **센서 채널 정보 백업**: |
|||
* 일련번호 판독 통신 포트 번호와 설정 채널 정보가 저장됩니다. |
|||
4. **레이저 마킹 도면 파일 백업**: |
|||
* 제품 표면에 각인할 마킹 도면 파일입니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,59 @@ |
|||
# 9. 오류 대응 및 프로그램 종료 |
|||
|
|||
[← 메뉴얼 목차로 돌아가기](사용자_메뉴얼.md) |
|||
|
|||
--- |
|||
|
|||
## 9.1 현장 장애 유형별 점검 및 예외 조치 요령 |
|||
|
|||
공정 가동 중 장비 상태나 전산망에 이상이 생길 경우 발생할 수 있는 주요 화면 경고창 및 조치 요령입니다. |
|||
|
|||
### 9.1.1 [오류 1] "제품 ID(IC_SN)를 읽어오지 못했습니다" |
|||
* **현상**: 검사 시작 시 제품 일련번호 읽기 단계에서 경고창이 발생하고 검사가 취소됨. |
|||
* **원인 및 해결**: |
|||
1. **접촉 상태 점검**: 제품이 안착 지그에 완벽하게 안착되었는지 확인하고, 프레스 실린더 또는 핀 단자의 밀착 상태를 확인하십시오. |
|||
2. **통신 설정 점검**: 프로그램 상단의 `통신 설정` 창을 열어 현재 설정된 포트 번호 및 물리 채널 번호가 실제 케이블 연결 상태와 일치하는지 확인하십시오. |
|||
|
|||
### 9.1.2 [오류 2] "이전 공정 이력이 조회되지 않는 제품입니다" |
|||
* **현상**: 검사 시작 시 이전 단계 결과가 조회되지 않아 검사가 진행되지 않음. |
|||
* **원인 및 해결**: |
|||
- 해당 제품이 하우징 조립, 센서 보정, EOL 1차 성능 검사 등 이전 가공 공정을 진행하지 않았거나, 이전 설비에서 생산 DB에 데이터를 올바르게 전송하지 않은 상태입니다. 제품 바코드를 재확인하고 이전 설비의 데이터 전송 유무를 검토하십시오. |
|||
* **비상 조치 (강제 검사)**: |
|||
- 이전 이력 등록 상태와 무관하게 **제품 성능 계측 및 마킹을 실행하고 결과를 저장해야 하는 특수 테스트 상황**인 경우, 화면 최하단의 **`강제 검사 (스킵)`** 버튼을 누르면 DB 검증을 건너뛰고 성능 검사를 강제로 실행할 수 있습니다. |
|||
|
|||
### 9.1.3 [오류 3] "이전 공정 단계가 불합격 상태이므로 최종 성능 검사를 시작할 수 없습니다" |
|||
* **현상**: DB 조회 결과 이전 공정 중 불합격(FAIL 또는 NG) 판정을 받은 내역이 발견되어 검사가 중단됨. |
|||
* **원인 및 해결**: |
|||
- 이전 공정에서 불합격 판정을 받은 제품은 최종 평가 및 레이저 마킹을 가동할 수 없습니다. 불량 제품 격리 기준에 따라 해당 제품을 생산 라인에서 제외 조치하십시오. |
|||
* **비상 조치 (강제 검사)**: |
|||
- 설비 작동 확인이나 품질 분석 등을 위해 반드시 검사를 진행해야 하는 경우, 하단바의 **`강제 검사 (스킵)`** 버튼을 클릭하면 경고 상태를 건너뛰고 계측과 마킹을 실행할 수 있습니다. |
|||
|
|||
### 9.1.4 [오류 4] "레이저 각인 작업 전송 실패" |
|||
* **현상**: 성능 검사는 합격(PASS)했으나, 레이저 장비로의 데이터 전송 단계에서 경고 에러가 발생함. |
|||
* **원인 및 해결**: |
|||
1. **도면 파일 점검**: `시험 설정` 화면에서 세팅해 놓은 작업 도면 파일이 실제 해당 경로에 존재하는지 점검하십시오. |
|||
2. **마킹기 전원/연결 점검**: 레이저 마킹기의 전원이 켜져 있는지 확인하고, 제어 PC와 마킹기 간의 연결 케이블 상태를 확인하십시오. |
|||
|
|||
### 9.1.5 [오류 5] "각인 순번이 9999를 초과했습니다. 다음 Lot No로 변경하십시오." |
|||
* **현상**: |
|||
- 프로그램 실행 또는 로그인 완료 후, 메인 화면 상태 알림창에 빨간색 경고 배너로 문구가 표시됩니다. |
|||
- `검사 시작 (START)` 또는 `강제 검사 (스킵)` 버튼을 누르면 작동 차단 경고창이 나타나며 설비 검사가 시작되지 않습니다. |
|||
* **원인 및 해결**: |
|||
- **순번 범위 초과**: 현재 로트 번호(`Lot No`)에서 최종 합격을 받아 각인이 완료된 누적 수량이 9999개를 초과하여 더 이상 순차 번호를 인쇄할 수 없습니다. |
|||
- **해결 방법**: 새로운 생산 조 또는 로트 번호(`Lot No`)를 수정하여 **프로그램에 재로그인**하십시오. 로트 번호가 변경되면 순번 카운트가 다시 초기화됩니다. |
|||
|
|||
--- |
|||
|
|||
## 9.2 프로그램 정상 종료 및 전원 자동 차단 규칙 |
|||
|
|||
본 설비는 고전력 계측 및 전원 제어를 함께 수행하므로 대기 전력 소모 방지와 안전을 위해 아래 절차에 따라 정상 종료 프로세스를 밟아야 합니다. |
|||
|
|||
* **로그아웃 (Logout)**: |
|||
- 상단 메뉴의 `로그아웃` 버튼을 클릭하면 현재 작업자 정보가 해제되고 초기 로그인 창으로 전환됩니다. |
|||
- **이와 동시에 연동된 전원 공급 장치로 차단 신호가 자동으로 전송되어 주전원 및 보드 부팅용 상시전원 출력이 OFF 상태로 차단됩니다.** |
|||
* **프로그램 완전 종료**: |
|||
- 화면 우측 상단의 `닫기(X)` 버튼을 눌러 프로그램을 최종 종료할 때도, 자동으로 상시전원 차단 명령을 장비에 인계한 뒤 레이저 각인 드라이버 리소스를 닫고 메모리를 환원합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
@ -0,0 +1,844 @@ |
|||
<style> |
|||
/* |
|||
* A4 용지 기준 PDF 출력을 위한 스타일시트 (pdf_style.css) |
|||
*/ |
|||
|
|||
@page { |
|||
size: A4; |
|||
margin: 20mm 15mm 20mm 15mm; |
|||
@top-left { content: none !important; } |
|||
@top-right { content: none !important; } |
|||
@bottom-left { content: none !important; } |
|||
@bottom-right { content: none !important; } |
|||
@bottom-center { |
|||
content: counter(page) !important; |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans KR", sans-serif; |
|||
font-size: 8.5pt; |
|||
color: #7f8c8d; |
|||
} |
|||
} |
|||
|
|||
body { |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans KR", sans-serif; |
|||
font-size: 10pt; |
|||
line-height: 1.6; |
|||
color: #333333; |
|||
background-color: #ffffff; |
|||
-webkit-print-color-adjust: exact !important; |
|||
print-color-adjust: exact !important; |
|||
} |
|||
|
|||
/* 제목 스타일 */ |
|||
h1, h2, h3, h4, h5, h6 { |
|||
color: #111111; |
|||
font-weight: bold; |
|||
page-break-after: avoid; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
h1 { |
|||
font-size: 18pt; |
|||
border-bottom: 2px solid #007acc; |
|||
padding-bottom: 4px; |
|||
margin-top: 20px; |
|||
margin-bottom: 12px; |
|||
} |
|||
|
|||
h2 { |
|||
font-size: 13pt; |
|||
border-bottom: 1px solid #e1e4e8; |
|||
padding-bottom: 3px; |
|||
margin-top: 16px; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
h3 { |
|||
font-size: 11pt; |
|||
margin-top: 12px; |
|||
margin-bottom: 6px; |
|||
} |
|||
|
|||
h4 { |
|||
font-size: 10pt; |
|||
margin-top: 10px; |
|||
margin-bottom: 6px; |
|||
} |
|||
|
|||
/* 문단 및 리스트 */ |
|||
p { |
|||
margin-top: 0; |
|||
margin-bottom: 8px; |
|||
text-align: justify; |
|||
} |
|||
|
|||
ul, ol { |
|||
margin-top: 0; |
|||
margin-bottom: 8px; |
|||
padding-left: 20px; |
|||
} |
|||
|
|||
li { |
|||
margin-bottom: 3px; |
|||
} |
|||
|
|||
/* 구분선 */ |
|||
hr { |
|||
height: 1px; |
|||
padding: 0; |
|||
margin: 15px 0; |
|||
background-color: #e1e4e8; |
|||
border: 0; |
|||
} |
|||
|
|||
/* 테이블 스타일 */ |
|||
table { |
|||
width: 100%; |
|||
border-collapse: collapse; |
|||
margin-top: 0; |
|||
margin-bottom: 10px; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
table th, table td { |
|||
padding: 4px 8px; |
|||
border: 1px solid #dfe2e5; |
|||
font-size: 8.5pt; |
|||
word-break: keep-all; |
|||
} |
|||
|
|||
table th { |
|||
font-weight: 600; |
|||
background-color: #f6f8fa; |
|||
text-align: left; |
|||
} |
|||
|
|||
table tr:nth-child(even) { |
|||
background-color: #f9fbfd; |
|||
} |
|||
|
|||
table tr { |
|||
page-break-inside: avoid; /* 표의 중간 행이 반으로 쪼개지는 것만 방지 */ |
|||
} |
|||
|
|||
/* 인용구 스타일 */ |
|||
blockquote { |
|||
padding: 6px 12px; |
|||
color: #6a737d; |
|||
border-left: 0.25em solid #007acc; |
|||
background-color: #f6f8fa; |
|||
margin: 0 0 10px 0; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
blockquote p { |
|||
margin: 0; |
|||
} |
|||
|
|||
/* 코드 블록 (아스크 아트 등 포함) */ |
|||
pre, code { |
|||
font-family: "Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", monospace; |
|||
font-size: 8.5pt; |
|||
background-color: #f6f8fa; |
|||
border-radius: 3px; |
|||
} |
|||
|
|||
code { |
|||
padding: 0.2em 0.4em; |
|||
margin: 0; |
|||
border: 1px solid #eaecef; |
|||
} |
|||
|
|||
pre { |
|||
padding: 12px; |
|||
overflow: auto; |
|||
line-height: 1.45; |
|||
border: 1px solid #e1e4e8; |
|||
word-wrap: normal; |
|||
white-space: pre; /* 아스키 아트 정렬 유지를 위해 강제 줄바꿈 해제 */ |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
pre code { |
|||
padding: 0; |
|||
margin: 0; |
|||
background-color: transparent; |
|||
border: none; |
|||
font-size: inherit; |
|||
white-space: inherit; |
|||
} |
|||
|
|||
/* 이미지 스타일 */ |
|||
img { |
|||
max-width: 100%; |
|||
max-height: 100mm; /* A4 높이의 약 절반 이하로 제한 */ |
|||
display: block; |
|||
margin: 15px auto; |
|||
object-fit: contain; |
|||
page-break-inside: avoid; |
|||
border: 1px solid #e1e4e8; |
|||
box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
|||
} |
|||
|
|||
/* 페이지 나누기 요소 */ |
|||
.page-break { |
|||
page-break-before: always !important; |
|||
} |
|||
|
|||
/* 내비게이션 숨김 (인쇄 시) */ |
|||
.nav-link, .nav-links, .back-to-toc, .manual-nav, |
|||
a[href$=".md"] { |
|||
display: none !important; |
|||
} |
|||
|
|||
/* 링크 스타일 */ |
|||
a { |
|||
color: #007acc; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
a:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
/* 특별 배지 스타일 */ |
|||
.badge { |
|||
display: inline-block; |
|||
padding: 2px 6px; |
|||
font-size: 8pt; |
|||
font-weight: 600; |
|||
line-height: 1; |
|||
border-radius: 2px; |
|||
background-color: #e1e4e8; |
|||
color: #24292e; |
|||
margin-right: 4px; |
|||
} |
|||
|
|||
</style> |
|||
|
|||
# Performance Inspect & Laser Marking System - 사용자 메뉴얼 |
|||
|
|||
> **버전**: 1.0.0 | **최종 수정**: 2026-07-14 |
|||
|
|||
--- |
|||
|
|||
## 메뉴얼 목차 |
|||
|
|||
본 메뉴얼은 각 주제별로 별도 문서로 구성되어 있습니다. 아래 링크를 클릭하여 해당 문서로 이동하세요. |
|||
|
|||
| 번호 | 문서 | 설명 | |
|||
|------|------|------| |
|||
| 1 | [시스템 개요 및 요구사항](#1-시스템-개요-및-요구사항) | 프로그램 소개, 주요 기능, 하드웨어/소프트웨어 요구사항, 장비 구성 | |
|||
| 2 | [초기 설정 가이드](#2-초기-설정-가이드) | 설정 파일의 구성 요소 안내 및 최초 장비 가동 시 점검 순서 | |
|||
| 3 | [메인 화면 (Home View)](#3-메인-화면-home-view) | 상단 정보 표시, 제품 정보 카드, 검사 결과 화면, 진행 상황 확인 및 버튼 제어 가이드 | |
|||
| 4 | [통신 설정 (Comm. Settings)](#4-통신-설정-comm-settings) | 4251 센서 통신 채널 설정 및 PC 통신 포트 연동 방법 | |
|||
| 5 | [시험 설정 (Parameters)](#5-시험-설정-parameters) | 제품 규격치(전압, 전류, 저항 범위) 및 레이저 마킹 도면 파일 연동 | |
|||
| 6 | [측정 데이터 조회 (Data View)](#6-측정-데이터-조회-및-데이터베이스-연동) | 생산 데이터베이스를 통한 이전 공정 이력 자동 조회 및 최종 결과 저장 원리 | |
|||
| 7 | [자동 시험 프로세스](#7-자동-시험-프로세스-및-14단계-시퀀스) | 자동 계측 시퀀스 기동, 마킹 수행 및 최종 합격 판정 흐름 | |
|||
| 8 | [로그 및 데이터 관리](#8-로그-및-데이터-관리) | 시스템 로그 파일 확인 방법 및 장비 설정 파일 백업 방법 | |
|||
| 9 | [오류 대응 및 프로그램 종료](#9-오류-대응-및-프로그램-종료) | 센서 통신 오류, DB 조회 에러, 마킹 불량 등 현장 장애 대응 및 안전한 프로그램 종료 방법 | |
|||
|
|||
--- |
|||
|
|||
## 빠른 시작 가이드 (Quick Start) |
|||
|
|||
처음 시스템을 가동하여 검사를 진행하는 경우 다음 순서에 따라 작업을 수행해 주십시오. |
|||
|
|||
1. **프로그램 설치 (최초 1회)** |
|||
- 배포받은 단일 설치 프로그램 `MarkingSetup.exe`를 실행하여 클릭 한 번으로 `C:\marking` 경로 및 바탕화면 바로가기를 자동 생성합니다. |
|||
2. **하드웨어 연결 상태 확인** |
|||
- 계측 장비들과 제어용 PC 간의 네트워크(LAN)선 및 센서 리더용 시리얼 포트 케이블 연결을 확인합니다. |
|||
3. **프로그램 실행 및 로그인** |
|||
- 바탕화면의 `Marking System` (`marking_gui`) 프로그램을 실행한 뒤, 작업자 계정 정보를 입력하여 로그인합니다. (데이터베이스 점검 중인 경우 설정 파일을 통해 오프라인 모드로의 진입이 가능합니다.) |
|||
3. **통신 상태 확인 및 채널 설정** |
|||
- 우측 상단의 `통신 설정` 메뉴에서 센서가 올바른 포트와 채널에 연결되었는지 확인합니다. |
|||
4. **검사 규격값 검증** |
|||
- 우측 상단의 `시험 설정` 메뉴를 열고, 전압/전류/저항 검사 기준치와 각인 템플릿 도면 파일의 경로가 올바른지 점검합니다. |
|||
5. **성능 검사 및 마킹 시작** |
|||
- 안착 지그에 제품을 바르게 장착한 뒤 메인 화면 하단의 `검사 시작 (START)` 버튼을 눌러 계측 및 마킹을 수행합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 1. 시스템 개요 및 요구사항 |
|||
|
|||
|
|||
--- |
|||
|
|||
## 1.1 시스템 개요 |
|||
|
|||
**Performance Inspect & Laser Marking System**은 온압센서 완제품의 최종 성능 검사를 수행하고, 이전 공정 단계들의 합격(PASS) 이력을 조회하여 최종 적합 제품에 한해 제품 표면에 레이저 마킹을 수행하는 시스템 제어 프로그램입니다. |
|||
|
|||
본 프로그램은 측정 계측기와 센서 판독기, 레이저 각인 장치 및 공장 생산 데이터베이스와 연동되어 작동합니다. |
|||
|
|||
### 주요 기능 요약 |
|||
|
|||
| 기능 | 설명 | |
|||
|------|------| |
|||
| **일련번호(S/N) 자동 추출** | 센서 판독 보드를 통해 제품 안착 시 제품 내부 메모리로부터 일련번호를 추출합니다. | |
|||
| **선행 공정 검사 교차 조회** | 이전 단계(하우징 조립, 센서 보정, 1차 EOL 성능 검사)가 모두 합격 판정되었는지 생산 데이터베이스에서 조회합니다. | |
|||
| **자동 계측 시퀀스** | 전원 공급 장치와 전압/저항 측정 장비들과 연동하여 제품에 테스트 전원을 투입하고 전압, 저항, 전류 값을 차례대로 계측합니다. | |
|||
| **실제 저항값 측정** | 전압/저항 DMM 측정기를 통해 센서의 실제 저항값(Ω)을 측정합니다. | |
|||
| **전류 측정** | 전원 공급 장치(Power Supply)의 출력 채널 1을 통해 제품의 소모 전류를 계측합니다. | |
|||
| **레이저 각인 연동** | 성능 검사가 모두 통과된 합격품에 대해 제품 표면에 2D QR 코드 및 단축 일련번호(생산일자 + 순번)를 마킹합니다. | |
|||
| **결과 기록** | 계측 판정 규격(전압, 전류, 저항)과 마킹 성공 여부를 최종 판정하여 생산 데이터베이스에 저장합니다. | |
|||
|
|||
--- |
|||
|
|||
## 1.2 소프트웨어 요구사항 |
|||
|
|||
| 항목 | 요구사항 | 비고 | |
|||
|------|----------|------| |
|||
| **통합 설치 프로그램** | `MarkingSetup.exe` (WiX 번들) | 1-Click 자동 설치 및 실행 환경, 드라이버, 설정 일체 셋업 | |
|||
| **운영체제** | Windows 10 이상 | 프로그램 구동 및 장비 드라이버 운용용 | |
|||
| **데이터베이스** | Microsoft SQL Server (MS-SQL) | 생산 공정 데이터 및 계측 결과 연동용 | |
|||
| **레이저 제어 프로그램** | EZCAD 각인 제어 프로그램 및 드라이버 | 레이저 마킹기 구동 및 전용 도면(.ezd) 운용용 | |
|||
| **네트워크 환경** | LAN (TCP/IP) 통신 | 제어 PC와 측정 기기 간의 연결 | |
|||
| **센서 보드 통신** | COM 포트 (RS-232 시리얼) | 4251 센서 통신 보드 연동 | |
|||
|
|||
--- |
|||
|
|||
## 1.3 하드웨어 구성 |
|||
|
|||
| 장비 | 역할 | 통신 방식 | |
|||
|------|------|-----------| |
|||
| **센서 판독 보드 (4251 보드)** | 제품 내부 칩의 일련번호(IC_SN)를 인식합니다. | RS-232 시리얼 통신 | |
|||
| **전압 및 저항 측정 장비 (DMM)** | 제품의 전압(V) 및 전기적 저항(Ω)을 측정합니다. (예: 192.168.1.100) | TCP/IP 네트워크 통신 | |
|||
| **전류 측정 및 전원 공급 장비 (PSU)** | 제품 구동을 위한 전원 공급 및 소모 전류(A)를 측정합니다. (예: 192.168.1.101) | TCP/IP 네트워크 통신 | |
|||
| **레이저 마킹기** | 2D QR 코드 및 텍스트 일련번호를 제품 표면에 인쇄합니다. | 마킹 제어 보드 연동 | |
|||
| *(전류 측정 DMM)* | *설정 파일(예: 192.168.1.102)에 존재하나 현재 제어 시퀀스에서는 사용하지 않습니다.* | *(미사용)* | |
|||
|
|||
## 1.4 설치 경로(`C:\marking\`) 구조 및 생성 파일 역할 |
|||
|
|||
단일 통합 설치 마법사(`MarkingSetup.exe`)를 통해 시스템을 설치하면 기본 설치 디렉터리(`C:\marking\`) 아래에 다음과 같은 실행 바이너리, 설정 파일, 드라이버 라이브러리 및 런타임 로그 폴더가 배치·생성됩니다. |
|||
|
|||
| 구분 | 파일 / 폴더명 | 상세 역할 및 기능 설명 | |
|||
|------|----------------|------------------------| |
|||
| **실행 프로그램** | `marking_gui.exe` | 메인 성능 검사 및 레이저 마킹 GUI 제어 실행 파일 | |
|||
| **종속 라이브러리** | `marking_gui.dll`, `*.deps.json`, `*.runtimeconfig.json` | .NET 9.0 (WPF) 자립형 런타임 및 종속 구성 바이너리 | |
|||
| **통합 설정 파일** | `Setting.ini` | 마킹기 폴더 경로, 테스트 모드, 도안 태그 매핑, 계측기 LAN IP, SCPI 전원 커맨드, 계측 판정 규격 임계치(`[Limits]`) 종합 설정 파일 | |
|||
| **DB 설정 파일** | `Database.ini` | MS-SQL 데이터베이스 접속 주소, DB명, 사용자 계정/PW, 오프라인 모드(`OfflineMode=true`) 설정 파일 | |
|||
| **센서 설정 파일** | `Sensor.ini` | 4251 센서 통신 보드 시리얼 포트(`Port=COM3`), 통신 속도(`BaudRate=115200`), 통신 채널(`Channel=1`) 설정 파일 | |
|||
| **드라이버 폴더** | `libs/` | C++ LMC 각인 드라이버 격리 디렉터리 (`MarkEzdWrapper.dll`, `DataMgr.dll`, `MarkEzd.dll`, `haspms32.dll` 등) | |
|||
| **로그 저장 폴더** | `logs/` *(자동 생성)* | 시스템 운용 중 발생하는 일별 이벤트 로그, 통신 이력, 각인 성공/실패 기록 텍스트 저장 디렉터리 (예: `logs/2026-07-23.log`) | |
|||
| **백업 보관 폴더** | `publish_backup/` | 프로그램 업데이트 및 빌드 배포 시 이전 릴리즈 바이너리/설정 자동 백업 폴더 | |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 2. 초기 설정 가이드 |
|||
|
|||
|
|||
--- |
|||
|
|||
## 2.1 프로그램 설정 구성 개요 |
|||
|
|||
본 프로그램은 정상적인 계측기 통신 및 데이터베이스 연동을 위해 몇 가지 설정 파일을 사용합니다. 이 설정 파일들은 프로그램 설치 및 라인 도입 시 최초 1회 셋업을 원칙으로 하며, 일반 운영자가 직접 설정 파일을 열어 수정할 필요는 없습니다. |
|||
|
|||
*참고: 대부분의 검사 기준 및 통신 정보는 프로그램 내의 **'통신 설정'** 및 **'시험 설정'** 화면을 통해 수정할 수 있습니다.* |
|||
|
|||
### 2.1.1 주요 설정 정보 구분 |
|||
|
|||
1. **장비 및 계측 설정** |
|||
- 계측기들과의 네트워크 연결 주소와 대기 시간 등을 정의합니다. |
|||
- 제품 합격 여부를 판정하는 전압, 전류, 저항의 기본 합격 규격 범위가 이 파일에 저장되며, 화면 내의 **'시험 설정'** 창에서 수정한 사항이 이 파일에 동적으로 반영됩니다. |
|||
- 프로그램은 전압/저항 측정 장치와 전원/전류 공급 장치를 제어하여 계측을 진행합니다. |
|||
|
|||
2. **생산 데이터베이스 연동 설정** |
|||
- 공장 생산 관리 시스템 데이터베이스와의 통신 경로가 기록되어 있습니다. |
|||
- 전산망이나 DB 서버 점검 등으로 인해 통신이 어려울 경우, 설정 파일을 통해 **'오프라인 모드'**로 전환하여 단독으로 장비 작동 테스트를 해볼 수 있습니다. |
|||
- **오프라인 로그인 지원**: 데이터베이스 확인 단계 없이 로그인하여 프로그램을 기동합니다. |
|||
- **오프라인 검사 지원**: 제품 이력 조회 및 검사 결과 저장을 건너뛰고 단독으로 계측 및 마킹을 실행합니다. |
|||
|
|||
3. **센서 판독기 설정** |
|||
- 제품 일련번호를 로드하기 위한 통신 채널 및 연결 포트 주소가 정의됩니다. |
|||
- 화면 내의 **'통신 설정'** 창에서 수정한 사항이 이 파일에 자동으로 저장됩니다. |
|||
|
|||
### 2.1.2 설치 경로(`C:\marking\`) 내 파일 배치 구조 |
|||
|
|||
프로그램 설치 완료 후 `C:\marking\` 경로에는 다음과 같이 구동 파일, 설정 파일, 드라이버 라이브러리 및 런타임 자동 생성 디렉터리가 배치됩니다. |
|||
|
|||
* **`C:\marking\marking_gui.exe`**: GUI 제어 메인 실행 파일 |
|||
* **`C:\marking\Setting.ini`**: 장비 통신 IP, 마킹 태그, 규격 임계치(`[Limits]`) 종합 설정 파일 |
|||
* **`C:\marking\Database.ini`**: MS-SQL DB 접속 정보 및 오프라인 모드 설정 파일 |
|||
* **`C:\marking\Sensor.ini`**: 4251 센서 통신 보드 포트/속도/채널 설정 파일 |
|||
* **`C:\marking\libs\`**: C++ LMC 레이저 각인 드라이버 라이브러리 격리 폴더 (`MarkEzdWrapper.dll` 등) |
|||
* **`C:\marking\logs\`**: 런타임 가동 중 자동 생성되는 일별 이력 로그 폴더 (`yyyy-MM-dd.log`) |
|||
* **`C:\marking\publish_backup\`**: 업데이트/배포 시 이전 버전 바이너리 및 설정 자동 백업 폴더 |
|||
|
|||
### 2.1.3 기본적인 설정 파일 편집 방법 |
|||
|
|||
> [!IMPORTANT] |
|||
> **[권장 조치 안내]** |
|||
> 현장 라인 검사자 및 일반 작업자는 프로그램 UI의 **[통신 설정]** 및 **[시험 설정]** 메뉴를 통해 안전하게 파라미터를 변경하십시오. |
|||
> 아래의 `.ini` 파일 직접 수정은 라인 엔지니어 또는 설비 관리자 전용 권한 작업이며, 잘못된 파일 수정 시 장비 통신 오류가 발생할 수 있습니다. |
|||
|
|||
설비 이동이나 네트워크 환경 변경 시, 프로그램 폴더 내의 각 `.ini` 파일을 텍스트 편집기(메모장 등)로 열어 아래의 전체 설정 레이아웃 항목을 참조하여 수정할 수 있습니다. |
|||
|
|||
#### 1) Setting.ini (주요 변경 가능 설정) |
|||
현장 네트워크 IP, 도안 파일 경로 및 검사 규격(임계치) 변경 시 수정하는 주요 설정 항목입니다. |
|||
```ini |
|||
[Settings] |
|||
EzdFolderPath=c:\EzCad\EasyCfg ; EZD 도안 파일 기본 탐색/저장 폴더 경로 |
|||
test=false ; 테스트 마킹 버튼 및 개발 모드 노출 여부 (true/false) |
|||
|
|||
[DMM] |
|||
VoltageHost=192.168.1.100 ; 전압/저항 측정용 계측기(DMM) IP 주소 |
|||
|
|||
[CurrentDMM] |
|||
CurrentDMMHost=192.168.1.102 ; 전류 측정용 계측기(DMM) IP 주소 |
|||
|
|||
[PowerSupply] |
|||
CurrentHost=192.168.1.101 ; 전원 공급기(Power Supply) IP 주소 |
|||
|
|||
[Limits] |
|||
MinVoltage=4.0 ; 전압 하한 판정 기준값 (V) |
|||
MaxVoltage=6.0 ; 전압 상한 판정 기준값 (V) |
|||
MinCurrent=8.0 ; 전류 하한 판정 기준값 (mA) |
|||
MaxCurrent=10.0 ; 전류 상한 판정 기준값 (mA) |
|||
MinResistance=0.4 ; 저항 하한 판정 기준값 (kΩ) |
|||
MaxResistance=0.8 ; 저항 상한 판정 기준값 (kΩ) |
|||
``` |
|||
|
|||
#### 2) Database.ini (주요 변경 가능 설정) |
|||
DB 서버 접속 주소 및 점검용 오프라인 모드 변경 시 수정하는 항목입니다. |
|||
```ini |
|||
[Database] |
|||
Db_Server=192.168.1.200 ; MSSQL 데이터베이스 서버 IP 주소 |
|||
Db_Name=MarkingDb ; 연결할 데이터베이스 이름 |
|||
Db_User=db_user ; DB 접속 사용자 계정 |
|||
Db_Password=db_password ; DB 접속 비밀번호 |
|||
OfflineMode=False ; DB 미연결 점검 모드 (True: DB 저장 생략, False: 정상 검증/적재) |
|||
|
|||
[Login] |
|||
OfflinePreview=False ; 로그인 DB 검증 우회 여부 (True: 로그인 생략, False: 정상 검증) |
|||
``` |
|||
|
|||
#### 3) Sensor.ini (주요 변경 가능 설정) |
|||
바코드 스캐너 시리얼 포트 및 채널 설정 항목입니다. |
|||
```ini |
|||
[Sensor] |
|||
Port=COM3 ; 바코드 스캐너 시리얼 포트 (장치 관리자 COM 포트 번호) |
|||
Channel=1 ; 통신 채널 번호 (1 또는 2) |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 2.2 최초 실행 및 장비 점검 순서 |
|||
|
|||
라인 가동 전 최초 실행할 때는 아래 단계를 순서대로 이행하여 정상 작동 여부를 점검하십시오. |
|||
|
|||
1. **프로그램 단일 설치 (MarkingSetup.exe)** |
|||
- 배포받은 단일 설치 마법사 `MarkingSetup.exe`를 실행하여 1-Click으로 `C:\marking\` 설치 및 바탕화면 바로가기를 자동 생성합니다. |
|||
2. **데이터베이스 연결 상태 확인** |
|||
- 데이터베이스가 점검 중인 경우 설정 파일을 통해 오프라인 모드로 설정하면 로그인 창을 통과하여 단독 테스트를 진행할 수 있습니다. |
|||
3. **장비 네트워크 통신 점검** |
|||
- 제어 PC와 계측 장비들(전압/저항 측정 장비, 전원 공급 장치) 간의 LAN 케이블 연결을 확인합니다. |
|||
- 제어 PC의 네트워크 IP 환경이 장비들의 대역과 동일한지 확인하고, 통신 신호가 정상적으로 송수신되는지 점검합니다. |
|||
4. **상시전원 자동 인가 확인** |
|||
- 프로그램 실행 후 작업자 계정으로 로그인을 시도합니다. |
|||
- 로그인이 완료되면 전원 공급 장치의 상시전원 채널 전원 램프가 자동으로 켜지는지 확인합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 3. 메인 화면 (Home View) |
|||
|
|||
|
|||
--- |
|||
|
|||
## 3.1 메인 화면 레이아웃 구성 |
|||
|
|||
본 프로그램은 작업자가 화면 구성 및 각 항목 상태를 파악할 수 있도록 4개의 카드 레이아웃으로 화면을 구성했습니다. |
|||
|
|||
### 3.1.1 상단 헤더 영역 (Header Bar) |
|||
|
|||
프로그램 최상단 영역에는 시스템 정보 배지와 제어 버튼이 배치되어 있습니다. |
|||
* **실시간 시계**: 좌측 상단에 날짜와 시간이 표시됩니다. |
|||
* **작업 정보 배지**: |
|||
* **공정 라인**: 로그인 단계에서 지정한 생산 라인 코드 (`Line No`) |
|||
* **로트 번호**: 로그인 단계에서 지정한 생산 로트 번호 (`Lot No`) |
|||
* **모델명**: 현재 가동 중인 제품의 사양 모델 (`Model`) |
|||
* **작업자**: 로그인한 작업자의 이름 (`Operator`) |
|||
* **제어 버튼**: 우측 상단에 `로그아웃` 버튼이 위치하며 최하단 바에 설정 관련 버튼이 배치됩니다. |
|||
|
|||
--- |
|||
|
|||
## 3.2 상태 및 제어 카드 영역 |
|||
|
|||
화면 중앙에는 역할을 구분한 4개의 상태 카드가 배치되어 있어, 제품 상태와 계측 단계를 모니터링할 수 있습니다. |
|||
|
|||
### 3.2.1 [카드 1] 제품 정보 및 이전 결과 (좌측 상단) |
|||
제품의 일련번호와 이전 생산 공정에서의 합격 이력을 대조하는 영역입니다. |
|||
* **작업 모델 설정**: |
|||
- `파일 선택` 버튼을 사용하여 각인용 도면 파일을 불러옵니다. |
|||
- 도면 파일 선택이 완료되면 상단 헤더 영역의 모델명(Model) 배지 텍스트가 선택한 도면명으로 자동 변경됩니다. |
|||
* **일련번호 (IC_SN)**: 제품이 안착되면 센서 판독기를 통해 자동으로 인식되어 표시됩니다. (읽기 전용) |
|||
* **이전 공정 이력 배지**: |
|||
* **Housing**: 하우징 조립 공정 판정 상태 (`PASS` / `FAIL` / `대기`) |
|||
* **Calibration**: 압력 보정 공정 판정 상태 (`PASS` / `FAIL` / `대기`) |
|||
* **EOL**: EOL 1차 성능 평가 판정 상태 (`PASS` / `FAIL` / `대기`) |
|||
* *주의: 이전 공정 이력 배지 중 하나라도 `FAIL` 상태인 경우 성능 검사를 시작할 수 없습니다.* |
|||
|
|||
### 3.2.2 [카드 2] 측정 결과 (우측 상단) |
|||
현재 장비에서 실제 계측한 3대 전기 파라미터(전압, 전류, 저항) 수치와 설정된 기준 규격 범위를 표시하는 영역입니다. |
|||
* **측정 전압 (Voltage)**: 전압 측정 장치가 측정한 전압 수치 (**V** 단위) |
|||
* **측정 전류 (Current)**: 전원 공급 장치가 측정한 소모 전류 수치 (**mA** 단위) |
|||
* **측정 저항 (Resistance)**: 저항 측정 장치가 측정한 전기적 저항 수치 (**kΩ** 단위) |
|||
* *알림: 각 물리량의 하단에는 현재 적용 중인 기준 규격 범위가 문구(`기준범위: X ~ Y`)로 표출되며, 실측값이 규격 범위 내에 도달하면 카드 테두리가 **초록색(PASS)**으로 표시되고, 범위를 벗어나면 테두리가 **빨간색(FAIL)**으로 바뀝니다.* |
|||
|
|||
### 3.2.3 [카드 3] 진행상황 (좌측 하단) |
|||
현재 설비가 수행하고 있는 단계별 자동 제어 시퀀스를 보여주는 안내 창입니다. |
|||
* "대기 상태", "제품 정보 수집 중...", "이전 공정 검사 결과 조회 중...", "측정 계측기 데이터 수집 중...", "제품 합격 - 레이저 각인 중..." 등 작동 상태를 실시간 텍스트로 표출합니다. |
|||
|
|||
### 3.2.4 [카드 4] 판정결과 (우측 하단) |
|||
제품의 최종 합격(PASS) 및 불합격(FAIL) 상태를 표시합니다. |
|||
* 계측 검사와 데이터 저장, 레이저 각인이 완료되었을 때 최종 합격인 경우 카드 배경이 **초록색(PASS)**으로 전환되며, 불합격인 경우 카드 배경이 **빨간색(FAIL)**으로 변경됩니다. |
|||
|
|||
### 3.2.5 최하단 제어 영역 (Control Box) |
|||
* **검사 시작 (START)**: 전체 검사 시퀀스를 기동하는 메인 버튼입니다. 이 버튼을 누르면 이전 계측 수치들이 초기화되고 새로운 측정 프로세스가 개시됩니다. |
|||
* **강제 검사 (스킵)**: 이전 가공 공정의 합격 이력이 없더라도 검증 단계를 건너뛰고 성능 계측 및 각인 시퀀스를 기동하는 버튼입니다. |
|||
* **테스트 마킹**: 성능 계측 없이 즉시 각인기에 테스트 마킹 신호를 전송하는 버튼입니다. |
|||
* *참고: `강제 검사 (스킵)` 및 `테스트 마킹` 버튼은 환경 설정에서 테스트 모드가 활성화된 상태에서만 화면 하단에 노출됩니다.* |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 4. 통신 설정 (Comm. Settings) |
|||
|
|||
|
|||
--- |
|||
|
|||
## 4.1 포트 설정 화면 사용법 |
|||
|
|||
프로그램 상단의 `통신 설정` 버튼을 클릭하면 포트 설정 대화 상자가 나타납니다. 이 대화 상자에서 센서 판독 장치(4251 보드)의 연결 포트 및 채널을 설정할 수 있습니다. |
|||
|
|||
### 주요 설정 항목 및 설명 |
|||
|
|||
1. **통신 포트 (Port)**: |
|||
- 센서 판독기가 연결되어 있는 PC의 연결 포트를 선택합니다. (예: `COM1`, `COM3`, `COM4` 등) |
|||
- 현재 PC에 인식되어 있는 포트 목록이 자동으로 표시됩니다. |
|||
|
|||
2. **통신 속도 (BaudRate)**: |
|||
- 센서 판독 장치와의 데이터 송수신 속도를 설정합니다. |
|||
- 기본 설정값은 **`115200`** 이며, 특수한 경우가 아니면 변경하지 않는 것을 권장합니다. |
|||
|
|||
3. **통신 채널 (Channel)**: |
|||
- 센서 판독기 내부의 연결 채널을 결정합니다. |
|||
- 드롭다운 메뉴를 통해 **`CH1`** 또는 **`CH2`**를 선택할 수 있습니다. |
|||
- 선택된 채널에 따라 센서 인식 모드가 변경됩니다. |
|||
|
|||
--- |
|||
|
|||
## 4.2 설정 저장 |
|||
|
|||
* **설정 저장**: |
|||
- 통신 포트와 채널을 선택한 후 `저장` 버튼을 누르면 설정 정보가 저장됩니다. |
|||
- 저장 시 기존 센서 연결을 해제하고 새로운 설정값으로 센서 인식 서비스를 다시 시작합니다. 프로그램을 재시작할 필요 없이 변경 사항이 즉시 적용됩니다. |
|||
- 저장하지 않고 창을 닫으려면 `취소` 버튼을 누릅니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 5. 시험 설정 (Parameters) |
|||
|
|||
|
|||
--- |
|||
|
|||
## 5.1 판정 기준 설정 |
|||
|
|||
프로그램 상단 우측의 `시험 설정` 버튼을 클릭하면 판정 기준을 구성하는 대화 상자가 나타납니다. 이 화면에서 제품 합불 판정에 사용되는 전압, 전류, 저항의 기준값을 입력할 수 있습니다. |
|||
|
|||
### 5.1.1 각 항목별 한계치 입력 가이드 |
|||
|
|||
* **전압 판정 범위**: |
|||
* **하한값**: 합격 전압 하한 규격 (V 단위) |
|||
* **상한값**: 합격 전압 상한 규격 (V 단위) |
|||
* **전류 판정 범위**: |
|||
* **하한값**: 합격 전류 하한 규격 (설정창 표기 단위 참조, 기본 mA/A) |
|||
* **상한값**: 합격 전류 상한 규격 (설정창 표기 단위 참조, 기본 mA/A) |
|||
* **저항 판정 범위**: |
|||
* **하한값**: 합격 저항 하한 규격 (설정창 표기 단위 참조, 기본 Ω/kΩ) |
|||
* **상한값**: 합격 저항 상한 규격 (설정창 표기 단위 참조, 기본 Ω/kΩ) |
|||
|
|||
*참고: 저장 버튼을 클릭하면 메인 화면의 하단 가이드 문구(`기준범위: X ~ Y`)가 즉시 갱신되어 새로 입력한 한계치가 다음 검사 시퀀스부터 반영됩니다.* |
|||
|
|||
--- |
|||
|
|||
## 5.2 레이저 각인 도면 지정 |
|||
|
|||
* **각인 파일 설정 경로**: |
|||
* 레이저 마킹기에서 사용할 작업 도면 파일 선택은 설정 대화 상자가 아닌, **메인 화면 좌측 상단의 '작업 모델 설정' 영역에 있는 '파일 선택' 버튼**을 클릭하여 수행합니다. |
|||
* 도면이 선택되면 상단 헤더 배지의 모델명 정보도 해당 도면 파일명으로 자동으로 변경됩니다. |
|||
* **유의 사항**: |
|||
* 지정해 놓은 도면 파일이 실제 경로에 존재하지 않는 경우, 계측 성능 검사가 합격하더라도 각인 단계에서 에러가 납니다. 검사 전 파일 경로 상태를 확인하십시오. |
|||
|
|||
--- |
|||
|
|||
## 5.3 설정 저장 및 적용 |
|||
|
|||
* 설정 창의 `저장` 버튼을 클릭하면 변경된 파라미터가 시스템 설정에 저장됩니다. |
|||
* 저장 완료 즉시 **메인 화면 하단에 표시되는 판정 기준 가이드 텍스트**가 업데이트되며, 이후에 새로 시작하는 성능 검사 시퀀스부터 새로운 규격치가 적용됩니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 6. 측정 데이터 조회 및 데이터베이스 연동 |
|||
|
|||
|
|||
--- |
|||
|
|||
## 6.1 선행 공정 결과 조회 (이력 확인) |
|||
|
|||
본 프로그램은 검사 시작 시 입력된 제품 일련번호를 기반으로 생산 데이터베이스에 접속하여 이전 제조 공정의 합격 여부를 조회합니다. |
|||
|
|||
### 6.1.1 이력 검토 대상 공정 |
|||
|
|||
시스템은 다음 3개의 선행 공정 검사 결과를 확인합니다. |
|||
1. **하우징 조립 공정** |
|||
2. **센서 오차 보정 공정** |
|||
3. **1차 EOL 성능 검사** |
|||
|
|||
### 6.1.2 이전 단계 규격 교차 확인 동작 |
|||
* 이전 3개 선행 단계의 이력이 **모두 합격(PASS 또는 OK)**된 제품인 경우에만 최종 성능검사(EOL2)를 진행할 수 있습니다. |
|||
* 선행 이력이 존재하지 않거나, 단 한 곳이라도 불합격(FAIL 또는 NG) 판정을 받은 경우 화면 진행 상황 표시창에 경고가 표시되며 최종 성능검사 시작이 제한됩니다. |
|||
|
|||
--- |
|||
|
|||
## 6.2 검사 결과 자동 적재 및 최종 판정 기록 |
|||
|
|||
자동 계측 프로세스가 종료되면 다음 정보가 생산 데이터베이스에 저장됩니다. |
|||
|
|||
* **저장 정보**: |
|||
- 제품 일련번호 |
|||
- 생산 라인, 로트 번호, 작업자 정보 |
|||
- 실측 전압, 전류, 저항값 |
|||
- 실측값은 데이터베이스 저장 규격에 맞춰 시스템 내부에서 소수점 이하 자리로 정밀 정리되어 저장됩니다. |
|||
- 최종 판정 결과 (`PASS` / `FAIL`) |
|||
- 마킹 시퀀스 번호 및 성공 기록 |
|||
* **비동기 데이터 처리**: |
|||
- 데이터베이스 통신 대기로 인한 화면 멈춤 현상을 방지하기 위해 데이터 조회 및 저장 작업은 프로그램 화면 동작과 별개로 백그라운드에서 비동기식으로 안전하게 처리됩니다. |
|||
|
|||
--- |
|||
|
|||
## 6.3 오프라인 모드 운용 |
|||
|
|||
데이터베이스 서버 접속이 불가능한 환경에서도 단독으로 설비를 가동할 수 있도록 **오프라인 모드**를 지원합니다. |
|||
|
|||
* **활성화 목적**: |
|||
- 네트워크 연결이 끊긴 상태에서 프로그램의 단독 동작 및 장비 제어 상태를 확인하기 위함입니다. |
|||
* **오프라인 작동 패턴**: |
|||
- **공정 조회 우회**: 입력된 일련번호에 대해 생산 데이터베이스 서버 접속 없이 이전 공정을 합격한 것으로 우회 처리합니다. |
|||
- **임시 일련번호 생성**: 일련번호가 비어 있는 상태에서 테스트를 개시하는 경우 현재 시간 기반의 임시 일련번호가 자동으로 부여되어 진행합니다. |
|||
- **각인 모사**: 실제 각인기에 데이터를 전송하는 단계를 가상 성공 처리하여 전체 흐름을 테스트합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 7. 자동 시험 프로세스 및 15단계 시퀀스 |
|||
|
|||
|
|||
--- |
|||
|
|||
## 7.1 자동 시험 및 마킹 프로세스 개요 |
|||
|
|||
본 프로그램은 사용자가 메인 화면 하단의 `검사 시작 (START)` 버튼을 누르면 데이터 저장까지의 과정이 자동 계측 시퀀스에 따라 순차적으로 동작하도록 구성되어 있습니다. |
|||
|
|||
```mermaid |
|||
graph TD |
|||
A[START 버튼 클릭] --> B[UI 화면 수치 초기화] |
|||
B --> C[4~8단계: 센서 S/N 읽기 및 보정] |
|||
C --> D{선행 공정 이력 확인} |
|||
D -- 불합격/미진행 --> E[검사 중단 & 경고 팝업] |
|||
E --> F{강제 검사 스킵?} |
|||
F -- 취소 --> Z[대기 복구] |
|||
F -- 스킵 실행 --> G[9~15단계: 계측 시퀀스 기동] |
|||
D -- 3개 공정 모두 PASS --> G |
|||
G --> H[10단계: 테스트 주전원 ON] |
|||
H --> I[12~14단계: 전압 / 저항 / 전류 실측] |
|||
I --> J[15단계: 테스트 주전원 안전 차단] |
|||
J --> K{최종 규격 비교 판정} |
|||
K -- 1개 이상 이탈 FAIL --> L[대형 FAIL 표시 & 마킹 제외 & DB 불합격 적재] |
|||
K -- 모두 통과 PASS --> M[대형 PASS 표시 & DB 합격 적재 & LMC1 레이저 QR 각인] |
|||
L --> Z |
|||
M --> Z |
|||
``` |
|||
|
|||
--- |
|||
|
|||
## 7.2 상세 15단계 자동 제어 시퀀스 |
|||
|
|||
최종 검사가 시작되면 장비와 계측기들은 다음 15가지 단계에 따라 동작을 차례대로 수행합니다. |
|||
|
|||
### [1단계] 사전 전원 인가 단계 (최초 가동/로그인 시 1회 진행) |
|||
* **1단계 [장비 확인]**: 전원 공급 장치와의 통신 연결 상태를 점검합니다. |
|||
* **2단계 [센서 구동 전압 설정]**: 센서 보드를 구동하는 데 필요한 전압을 전원 장치에 설정합니다. |
|||
* **3단계 [센서 구동 전원 출력]**: 설정된 전원을 출력하여 보드를 부팅합니다. |
|||
* *(참고: 이 단계는 로그인 성공 시 1회만 실행되며, 이후의 반복 검사 과정에서는 이미 투입된 전원을 재사용하여 4단계부터 즉각 검사가 수행됩니다)* |
|||
|
|||
### [2단계] 제품 일련번호 수집 및 센서 통신 대기 단계 |
|||
* **4단계 [판독 장치 대기]**: 센서 판독 장치를 초기 대기 상태로 설정합니다. |
|||
* **5단계 [보드 통신 연결]**: 통신 설정에 명시된 채널을 선택하여 센서 보드와 연결합니다. |
|||
* **6단계 [일련번호 읽기]**: 제품 메모리로부터 스캔한 고유 일련번호를 로드합니다. |
|||
* **7단계 [보드 통신 해제]**: 센서 데이터 전송을 중지하고 대기 상태로 되돌립니다. |
|||
* **8단계 [보정 기준 전송]**: 센서 장치에 보정 기준값을 인계하고 동작을 종료합니다. |
|||
|
|||
### [3단계] 계측기 연동 성능 평가 및 전원 차단 단계 |
|||
* **9단계 [전원 장비 확인]**: 주 테스트 전원을 공급할 전원 장치의 통신 상태를 확인합니다. |
|||
* **10단계 [테스트 전원 인가]**: 테스트 전원 출력을 ON시키고, 전원 인가 후 신호 안정을 위해 잠시 대기합니다. |
|||
* **11단계 [측정 장비 확인]**: 측정 장치의 통신 상태를 확인합니다. |
|||
* **12단계 [전압 측정]**: 제품의 현재 작동 전압을 측정합니다. |
|||
* **13단계 [저항 측정]**: 제품의 전기적 저항값을 직접 실측합니다. |
|||
* **14단계 [전류 측정]**: 전원 공급 장치의 출력 채널을 통해 제품의 작동 소모 전류를 측정합니다. |
|||
* **15단계 [테스트 전원 차단]**: 수집 완료 후 테스트 전원 출력을 자동으로 차단하여 제품을 안전하게 보호합니다. (계측 도중 오류가 발생하더라도 강제로 전원이 차단되도록 안전 장치가 적용되어 있습니다.) |
|||
|
|||
--- |
|||
|
|||
## 7.3 최종 판정 및 마킹 실행 조건 |
|||
|
|||
계측이 완료되면 측정된 전압(V), 저항(kΩ), 전류(mA) 값을 설정한 기준 규격값(SPEC)과 비교하여 최종 판정을 내립니다. |
|||
|
|||
1. **기준 규격을 벗어난 경우 (FAIL)**: |
|||
* 전압, 전류, 저항 중 하나라도 기준을 벗어나면 최종 불합격(FAIL) 판정이 내려집니다. |
|||
* 이 경우 레이저 마킹 장비 구동은 자동으로 제외(Skip)되며, 불합격 내역으로 DB에 기록됩니다. |
|||
2. **모든 항목이 합격인 경우 (PASS)**: |
|||
* 모든 수치가 기준치 내에 들어오면 최종 합격(PASS) 판정이 내려집니다. |
|||
* 합격 판정과 동시에 레이저 마킹기에 각인 데이터가 전달되어 2D QR 코드 및 제품 일련번호 각인이 자동으로 실행됩니다. |
|||
* 마킹 완료 기록과 계측 수치는 최종 PASS 상태로 데이터베이스에 저장됩니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 8. 로그 및 데이터 관리 |
|||
|
|||
|
|||
--- |
|||
|
|||
## 8.1 시스템 로그 수집 및 관리 |
|||
|
|||
본 제어 프로그램은 설비 가동 중에 발생하는 계측기와의 통신 상태, 측정값 정보 및 각종 예외 오류 상황을 로그 파일로 기록합니다. |
|||
|
|||
### 8.1.1 로그 파일 보관 방법 |
|||
|
|||
* **보관 폴더**: 프로그램 실행 파일 경로의 하위 **`Logs`** 폴더에 저장됩니다. |
|||
* **파일명 규칙**: 날짜별로 파일이 자동으로 생성되어 보관됩니다. |
|||
* **로그 중요도 분류**: |
|||
* **정보 (INFO)**: 정상적인 검사 프로세스 시작, 계측기 연결 성공, 레이저 인쇄 성공 및 데이터베이스 저장 완료 기록. |
|||
* **경고 (WARN)**: 센서 판독기 인식 지연, 제품 한계 기준치를 벗어난 불합격(FAIL) 발생 기록 등 설비 동작은 유지되나 품질 확인이 필요한 정보. |
|||
* **오류 (ERROR)**: 데이터베이스 네트워크 접속 끊김, 마킹 장치 연결 실패 등 조치가 필요한 장비 오류 정보. |
|||
|
|||
--- |
|||
|
|||
## 8.2 장비 교체 및 프로그램 백업 방법 |
|||
|
|||
장비를 교환하거나 PC 복구 상황에 대비하여, 정상 작동 상태에서의 설정 파일들을 정기적으로 백업해 둘 것을 권장합니다. |
|||
|
|||
### 8.2.1 백업 대상 리스트 |
|||
|
|||
1. **계측기 설정 및 검사 기준값 백업**: |
|||
* 계측기들의 연결 설정 정보와 합격 판정 기준 범위가 저장됩니다. |
|||
2. **데이터베이스 서버 정보 백업**: |
|||
* 생산 정보 데이터베이스 서버 주소와 로그인 정보가 저장됩니다. |
|||
3. **센서 채널 정보 백업**: |
|||
* 일련번호 판독 통신 포트 번호와 설정 채널 정보가 저장됩니다. |
|||
4. **레이저 마킹 도면 파일 백업**: |
|||
* 제품 표면에 각인할 마킹 도면 파일입니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
<div class="page-break"></div> |
|||
|
|||
# 9. 오류 대응 및 프로그램 종료 |
|||
|
|||
|
|||
--- |
|||
|
|||
## 9.1 현장 장애 유형별 점검 및 예외 조치 요령 |
|||
|
|||
공정 가동 중 장비 상태나 전산망에 이상이 생길 경우 발생할 수 있는 주요 화면 경고창 및 조치 요령입니다. |
|||
|
|||
### 9.1.1 [오류 1] "제품 ID(IC_SN)를 읽어오지 못했습니다" |
|||
* **현상**: 검사 시작 시 제품 일련번호 읽기 단계에서 경고창이 발생하고 검사가 취소됨. |
|||
* **원인 및 해결**: |
|||
1. **접촉 상태 점검**: 제품이 안착 지그에 완벽하게 안착되었는지 확인하고, 프레스 실린더 또는 핀 단자의 밀착 상태를 확인하십시오. |
|||
2. **통신 설정 점검**: 프로그램 상단의 `통신 설정` 창을 열어 현재 설정된 포트 번호 및 물리 채널 번호가 실제 케이블 연결 상태와 일치하는지 확인하십시오. |
|||
|
|||
### 9.1.2 [오류 2] "이전 공정 이력이 조회되지 않는 제품입니다" |
|||
* **현상**: 검사 시작 시 이전 단계 결과가 조회되지 않아 검사가 진행되지 않음. |
|||
* **원인 및 해결**: |
|||
- 해당 제품이 하우징 조립, 센서 보정, EOL 1차 성능 검사 등 이전 가공 공정을 진행하지 않았거나, 이전 설비에서 생산 DB에 데이터를 올바르게 전송하지 않은 상태입니다. 제품 바코드를 재확인하고 이전 설비의 데이터 전송 유무를 검토하십시오. |
|||
* **비상 조치 (강제 검사)**: |
|||
- 이전 이력 등록 상태와 무관하게 **제품 성능 계측 및 마킹을 실행하고 결과를 저장해야 하는 특수 테스트 상황**인 경우, 화면 최하단의 **`강제 검사 (스킵)`** 버튼을 누르면 DB 검증을 건너뛰고 성능 검사를 강제로 실행할 수 있습니다. |
|||
|
|||
### 9.1.3 [오류 3] "이전 공정 단계가 불합격 상태이므로 최종 성능 검사를 시작할 수 없습니다" |
|||
* **현상**: DB 조회 결과 이전 공정 중 불합격(FAIL 또는 NG) 판정을 받은 내역이 발견되어 검사가 중단됨. |
|||
* **원인 및 해결**: |
|||
- 이전 공정에서 불합격 판정을 받은 제품은 최종 평가 및 레이저 마킹을 가동할 수 없습니다. 불량 제품 격리 기준에 따라 해당 제품을 생산 라인에서 제외 조치하십시오. |
|||
* **비상 조치 (강제 검사)**: |
|||
- 설비 작동 확인이나 품질 분석 등을 위해 반드시 검사를 진행해야 하는 경우, 하단바의 **`강제 검사 (스킵)`** 버튼을 클릭하면 경고 상태를 건너뛰고 계측과 마킹을 실행할 수 있습니다. |
|||
|
|||
### 9.1.4 [오류 4] "레이저 각인 작업 전송 실패" |
|||
* **현상**: 성능 검사는 합격(PASS)했으나, 레이저 장비로의 데이터 전송 단계에서 경고 에러가 발생함. |
|||
* **원인 및 해결**: |
|||
1. **도면 파일 점검**: `시험 설정` 화면에서 세팅해 놓은 작업 도면 파일이 실제 해당 경로에 존재하는지 점검하십시오. |
|||
2. **마킹기 전원/연결 점검**: 레이저 마킹기의 전원이 켜져 있는지 확인하고, 제어 PC와 마킹기 간의 연결 케이블 상태를 확인하십시오. |
|||
|
|||
### 9.1.5 [오류 5] "각인 순번이 9999를 초과했습니다. 다음 Lot No로 변경하십시오." |
|||
* **현상**: |
|||
- 프로그램 실행 또는 로그인 완료 후, 메인 화면 상태 알림창에 빨간색 경고 배너로 문구가 표시됩니다. |
|||
- `검사 시작 (START)` 또는 `강제 검사 (스킵)` 버튼을 누르면 작동 차단 경고창이 나타나며 설비 검사가 시작되지 않습니다. |
|||
* **원인 및 해결**: |
|||
- **순번 범위 초과**: 현재 로트 번호(`Lot No`)에서 최종 합격을 받아 각인이 완료된 누적 수량이 9999개를 초과하여 더 이상 순차 번호를 인쇄할 수 없습니다. |
|||
- **해결 방법**: 새로운 생산 조 또는 로트 번호(`Lot No`)를 수정하여 **프로그램에 재로그인**하십시오. 로트 번호가 변경되면 순번 카운트가 다시 초기화됩니다. |
|||
|
|||
--- |
|||
|
|||
## 9.2 프로그램 정상 종료 및 전원 자동 차단 규칙 |
|||
|
|||
본 설비는 고전력 계측 및 전원 제어를 함께 수행하므로 대기 전력 소모 방지와 안전을 위해 아래 절차에 따라 정상 종료 프로세스를 밟아야 합니다. |
|||
|
|||
* **로그아웃 (Logout)**: |
|||
- 상단 메뉴의 `로그아웃` 버튼을 클릭하면 현재 작업자 정보가 해제되고 초기 로그인 창으로 전환됩니다. |
|||
- **이와 동시에 연동된 전원 공급 장치로 차단 신호가 자동으로 전송되어 주전원 및 보드 부팅용 상시전원 출력이 OFF 상태로 차단됩니다.** |
|||
* **프로그램 완전 종료**: |
|||
- 화면 우측 상단의 `닫기(X)` 버튼을 눌러 프로그램을 최종 종료할 때도, 자동으로 상시전원 차단 명령을 장비에 인계한 뒤 레이저 각인 드라이버 리소스를 닫고 메모리를 환원합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
|||
|
|||
@ -0,0 +1,974 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title>Performance Inspect & Laser Marking System - 사용자 메뉴얼</title> |
|||
<style> |
|||
/* |
|||
* A4 용지 기준 PDF 출력을 위한 스타일시트 (pdf_style.css) |
|||
*/ |
|||
|
|||
@page { |
|||
size: A4; |
|||
margin: 20mm 15mm 20mm 15mm; |
|||
@top-left { content: none !important; } |
|||
@top-right { content: none !important; } |
|||
@bottom-left { content: none !important; } |
|||
@bottom-right { content: none !important; } |
|||
@bottom-center { |
|||
content: counter(page) !important; |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans KR", sans-serif; |
|||
font-size: 8.5pt; |
|||
color: #7f8c8d; |
|||
} |
|||
} |
|||
|
|||
body { |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans KR", sans-serif; |
|||
font-size: 10pt; |
|||
line-height: 1.6; |
|||
color: #333333; |
|||
background-color: #ffffff; |
|||
-webkit-print-color-adjust: exact !important; |
|||
print-color-adjust: exact !important; |
|||
} |
|||
|
|||
/* 제목 스타일 */ |
|||
h1, h2, h3, h4, h5, h6 { |
|||
color: #111111; |
|||
font-weight: bold; |
|||
page-break-after: avoid; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
h1 { |
|||
font-size: 18pt; |
|||
border-bottom: 2px solid #007acc; |
|||
padding-bottom: 4px; |
|||
margin-top: 20px; |
|||
margin-bottom: 12px; |
|||
} |
|||
|
|||
h2 { |
|||
font-size: 13pt; |
|||
border-bottom: 1px solid #e1e4e8; |
|||
padding-bottom: 3px; |
|||
margin-top: 16px; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
h3 { |
|||
font-size: 11pt; |
|||
margin-top: 12px; |
|||
margin-bottom: 6px; |
|||
} |
|||
|
|||
h4 { |
|||
font-size: 10pt; |
|||
margin-top: 10px; |
|||
margin-bottom: 6px; |
|||
} |
|||
|
|||
/* 문단 및 리스트 */ |
|||
p { |
|||
margin-top: 0; |
|||
margin-bottom: 8px; |
|||
text-align: justify; |
|||
} |
|||
|
|||
ul, ol { |
|||
margin-top: 0; |
|||
margin-bottom: 8px; |
|||
padding-left: 20px; |
|||
} |
|||
|
|||
li { |
|||
margin-bottom: 3px; |
|||
} |
|||
|
|||
/* 구분선 */ |
|||
hr { |
|||
height: 1px; |
|||
padding: 0; |
|||
margin: 15px 0; |
|||
background-color: #e1e4e8; |
|||
border: 0; |
|||
} |
|||
|
|||
/* 테이블 스타일 */ |
|||
table { |
|||
width: 100%; |
|||
border-collapse: collapse; |
|||
margin-top: 0; |
|||
margin-bottom: 10px; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
table th, table td { |
|||
padding: 4px 8px; |
|||
border: 1px solid #dfe2e5; |
|||
font-size: 8.5pt; |
|||
word-break: keep-all; |
|||
} |
|||
|
|||
table th { |
|||
font-weight: 600; |
|||
background-color: #f6f8fa; |
|||
text-align: left; |
|||
} |
|||
|
|||
table tr:nth-child(even) { |
|||
background-color: #f9fbfd; |
|||
} |
|||
|
|||
table tr { |
|||
page-break-inside: avoid; /* 표의 중간 행이 반으로 쪼개지는 것만 방지 */ |
|||
} |
|||
|
|||
/* 인용구 스타일 */ |
|||
blockquote { |
|||
padding: 6px 12px; |
|||
color: #6a737d; |
|||
border-left: 0.25em solid #007acc; |
|||
background-color: #f6f8fa; |
|||
margin: 0 0 10px 0; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
blockquote p { |
|||
margin: 0; |
|||
} |
|||
|
|||
/* 코드 블록 (아스크 아트 등 포함) */ |
|||
pre, code { |
|||
font-family: "Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", monospace; |
|||
font-size: 8.5pt; |
|||
background-color: #f6f8fa; |
|||
border-radius: 3px; |
|||
} |
|||
|
|||
code { |
|||
padding: 0.2em 0.4em; |
|||
margin: 0; |
|||
border: 1px solid #eaecef; |
|||
} |
|||
|
|||
pre { |
|||
padding: 12px; |
|||
overflow: auto; |
|||
line-height: 1.45; |
|||
border: 1px solid #e1e4e8; |
|||
word-wrap: normal; |
|||
white-space: pre; /* 아스키 아트 정렬 유지를 위해 강제 줄바꿈 해제 */ |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
pre code { |
|||
padding: 0; |
|||
margin: 0; |
|||
background-color: transparent; |
|||
border: none; |
|||
font-size: inherit; |
|||
white-space: inherit; |
|||
} |
|||
|
|||
/* 이미지 스타일 */ |
|||
img { |
|||
max-width: 100%; |
|||
max-height: 100mm; /* A4 높이의 약 절반 이하로 제한 */ |
|||
display: block; |
|||
margin: 15px auto; |
|||
object-fit: contain; |
|||
page-break-inside: avoid; |
|||
border: 1px solid #e1e4e8; |
|||
box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
|||
} |
|||
|
|||
/* 페이지 나누기 요소 */ |
|||
.page-break { |
|||
page-break-before: always !important; |
|||
} |
|||
|
|||
/* 내비게이션 숨김 (인쇄 시) */ |
|||
.nav-link, .nav-links, .back-to-toc, .manual-nav, |
|||
a[href$=".md"] { |
|||
display: none !important; |
|||
} |
|||
|
|||
/* 링크 스타일 */ |
|||
a { |
|||
color: #007acc; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
a:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
/* 특별 배지 스타일 */ |
|||
.badge { |
|||
display: inline-block; |
|||
padding: 2px 6px; |
|||
font-size: 8pt; |
|||
font-weight: 600; |
|||
line-height: 1; |
|||
border-radius: 2px; |
|||
background-color: #e1e4e8; |
|||
color: #24292e; |
|||
margin-right: 4px; |
|||
} |
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
<h1>Performance Inspect & Laser Marking System - 사용자 메뉴얼</h1> |
|||
<blockquote> |
|||
<p><strong>버전</strong>: 1.0.0 | <strong>최종 수정</strong>: 2026-07-14</p> |
|||
</blockquote> |
|||
<hr /> |
|||
<h2>메뉴얼 목차</h2> |
|||
<p>본 메뉴얼은 각 주제별로 별도 문서로 구성되어 있습니다. 아래 링크를 클릭하여 해당 문서로 이동하세요.</p> |
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th>번호</th> |
|||
<th>문서</th> |
|||
<th>설명</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td>1</td> |
|||
<td><a href="#1-시스템-개요-및-요구사항">시스템 개요 및 요구사항</a></td> |
|||
<td>프로그램 소개, 주요 기능, 하드웨어/소프트웨어 요구사항, 장비 구성</td> |
|||
</tr> |
|||
<tr> |
|||
<td>2</td> |
|||
<td><a href="#2-초기-설정-가이드">초기 설정 가이드</a></td> |
|||
<td>설정 파일의 구성 요소 안내 및 최초 장비 가동 시 점검 순서</td> |
|||
</tr> |
|||
<tr> |
|||
<td>3</td> |
|||
<td><a href="#3-메인-화면-home-view">메인 화면 (Home View)</a></td> |
|||
<td>상단 정보 표시, 제품 정보 카드, 검사 결과 화면, 진행 상황 확인 및 버튼 제어 가이드</td> |
|||
</tr> |
|||
<tr> |
|||
<td>4</td> |
|||
<td><a href="#4-통신-설정-comm-settings">통신 설정 (Comm. Settings)</a></td> |
|||
<td>4251 센서 통신 채널 설정 및 PC 통신 포트 연동 방법</td> |
|||
</tr> |
|||
<tr> |
|||
<td>5</td> |
|||
<td><a href="#5-시험-설정-parameters">시험 설정 (Parameters)</a></td> |
|||
<td>제품 규격치(전압, 전류, 저항 범위) 및 레이저 마킹 도면 파일 연동</td> |
|||
</tr> |
|||
<tr> |
|||
<td>6</td> |
|||
<td><a href="#6-측정-데이터-조회-및-데이터베이스-연동">측정 데이터 조회 (Data View)</a></td> |
|||
<td>생산 데이터베이스를 통한 이전 공정 이력 자동 조회 및 최종 결과 저장 원리</td> |
|||
</tr> |
|||
<tr> |
|||
<td>7</td> |
|||
<td><a href="#7-자동-시험-프로세스-및-14단계-시퀀스">자동 시험 프로세스</a></td> |
|||
<td>자동 계측 시퀀스 기동, 마킹 수행 및 최종 합격 판정 흐름</td> |
|||
</tr> |
|||
<tr> |
|||
<td>8</td> |
|||
<td><a href="#8-로그-및-데이터-관리">로그 및 데이터 관리</a></td> |
|||
<td>시스템 로그 파일 확인 방법 및 장비 설정 파일 백업 방법</td> |
|||
</tr> |
|||
<tr> |
|||
<td>9</td> |
|||
<td><a href="#9-오류-대응-및-프로그램-종료">오류 대응 및 프로그램 종료</a></td> |
|||
<td>센서 통신 오류, DB 조회 에러, 마킹 불량 등 현장 장애 대응 및 안전한 프로그램 종료 방법</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<hr /> |
|||
<h2>빠른 시작 가이드 (Quick Start)</h2> |
|||
<p>처음 시스템을 가동하여 검사를 진행하는 경우 다음 순서에 따라 작업을 수행해 주십시오.</p> |
|||
<ol> |
|||
<li><strong>프로그램 설치 (최초 1회)</strong></li> |
|||
<li>배포받은 단일 설치 프로그램 <code>MarkingSetup.exe</code>를 실행하여 클릭 한 번으로 <code>C:\marking</code> 경로 및 바탕화면 바로가기를 자동 생성합니다.</li> |
|||
<li><strong>하드웨어 연결 상태 확인</strong></li> |
|||
<li>계측 장비들과 제어용 PC 간의 네트워크(LAN)선 및 센서 리더용 시리얼 포트 케이블 연결을 확인합니다.</li> |
|||
<li><strong>프로그램 실행 및 로그인</strong></li> |
|||
<li>바탕화면의 <code>Marking System</code> (<code>marking_gui</code>) 프로그램을 실행한 뒤, 작업자 계정 정보를 입력하여 로그인합니다. (데이터베이스 점검 중인 경우 설정 파일을 통해 오프라인 모드로의 진입이 가능합니다.)</li> |
|||
<li><strong>통신 상태 확인 및 채널 설정</strong></li> |
|||
<li>우측 상단의 <code>통신 설정</code> 메뉴에서 센서가 올바른 포트와 채널에 연결되었는지 확인합니다.</li> |
|||
<li><strong>검사 규격값 검증</strong></li> |
|||
<li>우측 상단의 <code>시험 설정</code> 메뉴를 열고, 전압/전류/저항 검사 기준치와 각인 템플릿 도면 파일의 경로가 올바른지 점검합니다.</li> |
|||
<li><strong>성능 검사 및 마킹 시작</strong></li> |
|||
<li>안착 지그에 제품을 바르게 장착한 뒤 메인 화면 하단의 <code>검사 시작 (START)</code> 버튼을 눌러 계측 및 마킹을 수행합니다.</li> |
|||
</ol> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>1. 시스템 개요 및 요구사항</h1> |
|||
<hr /> |
|||
<h2>1.1 시스템 개요</h2> |
|||
<p><strong>Performance Inspect & Laser Marking System</strong>은 온압센서 완제품의 최종 성능 검사를 수행하고, 이전 공정 단계들의 합격(PASS) 이력을 조회하여 최종 적합 제품에 한해 제품 표면에 레이저 마킹을 수행하는 시스템 제어 프로그램입니다.</p> |
|||
<p>본 프로그램은 측정 계측기와 센서 판독기, 레이저 각인 장치 및 공장 생산 데이터베이스와 연동되어 작동합니다.</p> |
|||
<h3>주요 기능 요약</h3> |
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th>기능</th> |
|||
<th>설명</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td><strong>일련번호(S/N) 자동 추출</strong></td> |
|||
<td>센서 판독 보드를 통해 제품 안착 시 제품 내부 메모리로부터 일련번호를 추출합니다.</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>선행 공정 검사 교차 조회</strong></td> |
|||
<td>이전 단계(하우징 조립, 센서 보정, 1차 EOL 성능 검사)가 모두 합격 판정되었는지 생산 데이터베이스에서 조회합니다.</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>자동 계측 시퀀스</strong></td> |
|||
<td>전원 공급 장치와 전압/저항 측정 장비들과 연동하여 제품에 테스트 전원을 투입하고 전압, 저항, 전류 값을 차례대로 계측합니다.</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>실제 저항값 측정</strong></td> |
|||
<td>전압/저항 DMM 측정기를 통해 센서의 실제 저항값(Ω)을 측정합니다.</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>전류 측정</strong></td> |
|||
<td>전원 공급 장치(Power Supply)의 출력 채널 1을 통해 제품의 소모 전류를 계측합니다.</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>레이저 각인 연동</strong></td> |
|||
<td>성능 검사가 모두 통과된 합격품에 대해 제품 표면에 2D QR 코드 및 단축 일련번호(생산일자 + 순번)를 마킹합니다.</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>결과 기록</strong></td> |
|||
<td>계측 판정 규격(전압, 전류, 저항)과 마킹 성공 여부를 최종 판정하여 생산 데이터베이스에 저장합니다.</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<hr /> |
|||
<h2>1.2 소프트웨어 요구사항</h2> |
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th>항목</th> |
|||
<th>요구사항</th> |
|||
<th>비고</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td><strong>통합 설치 프로그램</strong></td> |
|||
<td><code>MarkingSetup.exe</code> (WiX 번들)</td> |
|||
<td>1-Click 자동 설치 및 실행 환경, 드라이버, 설정 일체 셋업</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>운영체제</strong></td> |
|||
<td>Windows 10 이상</td> |
|||
<td>프로그램 구동 및 장비 드라이버 운용용</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>데이터베이스</strong></td> |
|||
<td>Microsoft SQL Server (MS-SQL)</td> |
|||
<td>생산 공정 데이터 및 계측 결과 연동용</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>레이저 제어 프로그램</strong></td> |
|||
<td>EZCAD 각인 제어 프로그램 및 드라이버</td> |
|||
<td>레이저 마킹기 구동 및 전용 도면(.ezd) 운용용</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>네트워크 환경</strong></td> |
|||
<td>LAN (TCP/IP) 통신</td> |
|||
<td>제어 PC와 측정 기기 간의 연결</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>센서 보드 통신</strong></td> |
|||
<td>COM 포트 (RS-232 시리얼)</td> |
|||
<td>4251 센서 통신 보드 연동</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<hr /> |
|||
<h2>1.3 하드웨어 구성</h2> |
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th>장비</th> |
|||
<th>역할</th> |
|||
<th>통신 방식</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td><strong>센서 판독 보드 (4251 보드)</strong></td> |
|||
<td>제품 내부 칩의 일련번호(IC_SN)를 인식합니다.</td> |
|||
<td>RS-232 시리얼 통신</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>전압 및 저항 측정 장비 (DMM)</strong></td> |
|||
<td>제품의 전압(V) 및 전기적 저항(Ω)을 측정합니다. (예: 192.168.1.100)</td> |
|||
<td>TCP/IP 네트워크 통신</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>전류 측정 및 전원 공급 장비 (PSU)</strong></td> |
|||
<td>제품 구동을 위한 전원 공급 및 소모 전류(A)를 측정합니다. (예: 192.168.1.101)</td> |
|||
<td>TCP/IP 네트워크 통신</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>레이저 마킹기</strong></td> |
|||
<td>2D QR 코드 및 텍스트 일련번호를 제품 표면에 인쇄합니다.</td> |
|||
<td>마킹 제어 보드 연동</td> |
|||
</tr> |
|||
<tr> |
|||
<td><em>(전류 측정 DMM)</em></td> |
|||
<td><em>설정 파일(예: 192.168.1.102)에 존재하나 현재 제어 시퀀스에서는 사용하지 않습니다.</em></td> |
|||
<td><em>(미사용)</em></td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<h2>1.4 설치 경로(<code>C:\marking\</code>) 구조 및 생성 파일 역할</h2> |
|||
<p>단일 통합 설치 마법사(<code>MarkingSetup.exe</code>)를 통해 시스템을 설치하면 기본 설치 디렉터리(<code>C:\marking\</code>) 아래에 다음과 같은 실행 바이너리, 설정 파일, 드라이버 라이브러리 및 런타임 로그 폴더가 배치·생성됩니다.</p> |
|||
<table> |
|||
<thead> |
|||
<tr> |
|||
<th>구분</th> |
|||
<th>파일 / 폴더명</th> |
|||
<th>상세 역할 및 기능 설명</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td><strong>실행 프로그램</strong></td> |
|||
<td><code>marking_gui.exe</code></td> |
|||
<td>메인 성능 검사 및 레이저 마킹 GUI 제어 실행 파일</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>종속 라이브러리</strong></td> |
|||
<td><code>marking_gui.dll</code>, <code>*.deps.json</code>, <code>*.runtimeconfig.json</code></td> |
|||
<td>.NET 9.0 (WPF) 자립형 런타임 및 종속 구성 바이너리</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>통합 설정 파일</strong></td> |
|||
<td><code>Setting.ini</code></td> |
|||
<td>마킹기 폴더 경로, 테스트 모드, 도안 태그 매핑, 계측기 LAN IP, SCPI 전원 커맨드, 계측 판정 규격 임계치(<code>[Limits]</code>) 종합 설정 파일</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>DB 설정 파일</strong></td> |
|||
<td><code>Database.ini</code></td> |
|||
<td>MS-SQL 데이터베이스 접속 주소, DB명, 사용자 계정/PW, 오프라인 모드(<code>OfflineMode=true</code>) 설정 파일</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>센서 설정 파일</strong></td> |
|||
<td><code>Sensor.ini</code></td> |
|||
<td>4251 센서 통신 보드 시리얼 포트(<code>Port=COM3</code>), 통신 속도(<code>BaudRate=115200</code>), 통신 채널(<code>Channel=1</code>) 설정 파일</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>드라이버 폴더</strong></td> |
|||
<td><code>libs/</code></td> |
|||
<td>C++ LMC 각인 드라이버 격리 디렉터리 (<code>MarkEzdWrapper.dll</code>, <code>DataMgr.dll</code>, <code>MarkEzd.dll</code>, <code>haspms32.dll</code> 등)</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>로그 저장 폴더</strong></td> |
|||
<td><code>logs/</code> <em>(자동 생성)</em></td> |
|||
<td>시스템 운용 중 발생하는 일별 이벤트 로그, 통신 이력, 각인 성공/실패 기록 텍스트 저장 디렉터리 (예: <code>logs/2026-07-23.log</code>)</td> |
|||
</tr> |
|||
<tr> |
|||
<td><strong>백업 보관 폴더</strong></td> |
|||
<td><code>publish_backup/</code></td> |
|||
<td>프로그램 업데이트 및 빌드 배포 시 이전 릴리즈 바이너리/설정 자동 백업 폴더</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>2. 초기 설정 가이드</h1> |
|||
<hr /> |
|||
<h2>2.1 프로그램 설정 구성 개요</h2> |
|||
<p>본 프로그램은 정상적인 계측기 통신 및 데이터베이스 연동을 위해 몇 가지 설정 파일을 사용합니다. 이 설정 파일들은 프로그램 설치 및 라인 도입 시 최초 1회 셋업을 원칙으로 하며, 일반 운영자가 직접 설정 파일을 열어 수정할 필요는 없습니다.</p> |
|||
<p><em>참고: 대부분의 검사 기준 및 통신 정보는 프로그램 내의 </em><em>'통신 설정'</em><em> 및 </em><em>'시험 설정'</em><em> 화면을 통해 수정할 수 있습니다.</em></p> |
|||
<h3>2.1.1 주요 설정 정보 구분</h3> |
|||
<ol> |
|||
<li><strong>장비 및 계측 설정</strong></li> |
|||
<li>계측기들과의 네트워크 연결 주소와 대기 시간 등을 정의합니다.</li> |
|||
<li>제품 합격 여부를 판정하는 전압, 전류, 저항의 기본 합격 규격 범위가 이 파일에 저장되며, 화면 내의 <strong>'시험 설정'</strong> 창에서 수정한 사항이 이 파일에 동적으로 반영됩니다.</li> |
|||
<li> |
|||
<p>프로그램은 전압/저항 측정 장치와 전원/전류 공급 장치를 제어하여 계측을 진행합니다.</p> |
|||
</li> |
|||
<li> |
|||
<p><strong>생산 데이터베이스 연동 설정</strong></p> |
|||
</li> |
|||
<li>공장 생산 관리 시스템 데이터베이스와의 통신 경로가 기록되어 있습니다.</li> |
|||
<li> |
|||
<p>전산망이나 DB 서버 점검 등으로 인해 통신이 어려울 경우, 설정 파일을 통해 <strong>'오프라인 모드'</strong>로 전환하여 단독으로 장비 작동 테스트를 해볼 수 있습니다.</p> |
|||
<ul> |
|||
<li><strong>오프라인 로그인 지원</strong>: 데이터베이스 확인 단계 없이 로그인하여 프로그램을 기동합니다.</li> |
|||
<li><strong>오프라인 검사 지원</strong>: 제품 이력 조회 및 검사 결과 저장을 건너뛰고 단독으로 계측 및 마킹을 실행합니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li> |
|||
<p><strong>센서 판독기 설정</strong></p> |
|||
</li> |
|||
<li>제품 일련번호를 로드하기 위한 통신 채널 및 연결 포트 주소가 정의됩니다.</li> |
|||
<li>화면 내의 <strong>'통신 설정'</strong> 창에서 수정한 사항이 이 파일에 자동으로 저장됩니다.</li> |
|||
</ol> |
|||
<h3>2.1.2 설치 경로(<code>C:\marking\</code>) 내 파일 배치 구조</h3> |
|||
<p>프로그램 설치 완료 후 <code>C:\marking\</code> 경로에는 다음과 같이 구동 파일, 설정 파일, 드라이버 라이브러리 및 런타임 자동 생성 디렉터리가 배치됩니다.</p> |
|||
<ul> |
|||
<li><strong><code>C:\marking\marking_gui.exe</code></strong>: GUI 제어 메인 실행 파일</li> |
|||
<li><strong><code>C:\marking\Setting.ini</code></strong>: 장비 통신 IP, 마킹 태그, 규격 임계치(<code>[Limits]</code>) 종합 설정 파일</li> |
|||
<li><strong><code>C:\marking\Database.ini</code></strong>: MS-SQL DB 접속 정보 및 오프라인 모드 설정 파일</li> |
|||
<li><strong><code>C:\marking\Sensor.ini</code></strong>: 4251 센서 통신 보드 포트/속도/채널 설정 파일</li> |
|||
<li><strong><code>C:\marking\libs\</code></strong>: C++ LMC 레이저 각인 드라이버 라이브러리 격리 폴더 (<code>MarkEzdWrapper.dll</code> 등)</li> |
|||
<li><strong><code>C:\marking\logs\</code></strong>: 런타임 가동 중 자동 생성되는 일별 이력 로그 폴더 (<code>yyyy-MM-dd.log</code>)</li> |
|||
<li><strong><code>C:\marking\publish_backup\</code></strong>: 업데이트/배포 시 이전 버전 바이너리 및 설정 자동 백업 폴더</li> |
|||
</ul> |
|||
<h3>2.1.3 기본적인 설정 파일 편집 방법</h3> |
|||
<blockquote> |
|||
<p>[!IMPORTANT] |
|||
<strong>[권장 조치 안내]</strong> |
|||
현장 라인 검사자 및 일반 작업자는 프로그램 UI의 <strong>[통신 설정]</strong> 및 <strong>[시험 설정]</strong> 메뉴를 통해 안전하게 파라미터를 변경하십시오. |
|||
아래의 <code>.ini</code> 파일 직접 수정은 라인 엔지니어 또는 설비 관리자 전용 권한 작업이며, 잘못된 파일 수정 시 장비 통신 오류가 발생할 수 있습니다.</p> |
|||
</blockquote> |
|||
<p>설비 이동이나 네트워크 환경 변경 시, 프로그램 폴더 내의 각 <code>.ini</code> 파일을 텍스트 편집기(메모장 등)로 열어 아래의 전체 설정 레이아웃 항목을 참조하여 수정할 수 있습니다.</p> |
|||
<h4>1) Setting.ini (주요 변경 가능 설정)</h4> |
|||
<p>현장 네트워크 IP, 도안 파일 경로 및 검사 규격(임계치) 변경 시 수정하는 주요 설정 항목입니다.</p> |
|||
<pre><code class="language-ini">[Settings] |
|||
EzdFolderPath=c:\EzCad\EasyCfg ; EZD 도안 파일 기본 탐색/저장 폴더 경로 |
|||
test=false ; 테스트 마킹 버튼 및 개발 모드 노출 여부 (true/false) |
|||
|
|||
[DMM] |
|||
VoltageHost=192.168.1.100 ; 전압/저항 측정용 계측기(DMM) IP 주소 |
|||
|
|||
[CurrentDMM] |
|||
CurrentDMMHost=192.168.1.102 ; 전류 측정용 계측기(DMM) IP 주소 |
|||
|
|||
[PowerSupply] |
|||
CurrentHost=192.168.1.101 ; 전원 공급기(Power Supply) IP 주소 |
|||
|
|||
[Limits] |
|||
MinVoltage=4.0 ; 전압 하한 판정 기준값 (V) |
|||
MaxVoltage=6.0 ; 전압 상한 판정 기준값 (V) |
|||
MinCurrent=8.0 ; 전류 하한 판정 기준값 (mA) |
|||
MaxCurrent=10.0 ; 전류 상한 판정 기준값 (mA) |
|||
MinResistance=0.4 ; 저항 하한 판정 기준값 (kΩ) |
|||
MaxResistance=0.8 ; 저항 상한 판정 기준값 (kΩ) |
|||
</code></pre> |
|||
<h4>2) Database.ini (주요 변경 가능 설정)</h4> |
|||
<p>DB 서버 접속 주소 및 점검용 오프라인 모드 변경 시 수정하는 항목입니다.</p> |
|||
<pre><code class="language-ini">[Database] |
|||
Db_Server=192.168.1.200 ; MSSQL 데이터베이스 서버 IP 주소 |
|||
Db_Name=MarkingDb ; 연결할 데이터베이스 이름 |
|||
Db_User=db_user ; DB 접속 사용자 계정 |
|||
Db_Password=db_password ; DB 접속 비밀번호 |
|||
OfflineMode=False ; DB 미연결 점검 모드 (True: DB 저장 생략, False: 정상 검증/적재) |
|||
|
|||
[Login] |
|||
OfflinePreview=False ; 로그인 DB 검증 우회 여부 (True: 로그인 생략, False: 정상 검증) |
|||
</code></pre> |
|||
<h4>3) Sensor.ini (주요 변경 가능 설정)</h4> |
|||
<p>바코드 스캐너 시리얼 포트 및 채널 설정 항목입니다.</p> |
|||
<pre><code class="language-ini">[Sensor] |
|||
Port=COM3 ; 바코드 스캐너 시리얼 포트 (장치 관리자 COM 포트 번호) |
|||
Channel=1 ; 통신 채널 번호 (1 또는 2) |
|||
</code></pre> |
|||
<hr /> |
|||
<h2>2.2 최초 실행 및 장비 점검 순서</h2> |
|||
<p>라인 가동 전 최초 실행할 때는 아래 단계를 순서대로 이행하여 정상 작동 여부를 점검하십시오.</p> |
|||
<ol> |
|||
<li><strong>프로그램 단일 설치 (MarkingSetup.exe)</strong></li> |
|||
<li>배포받은 단일 설치 마법사 <code>MarkingSetup.exe</code>를 실행하여 1-Click으로 <code>C:\marking\</code> 설치 및 바탕화면 바로가기를 자동 생성합니다.</li> |
|||
<li><strong>데이터베이스 연결 상태 확인</strong></li> |
|||
<li>데이터베이스가 점검 중인 경우 설정 파일을 통해 오프라인 모드로 설정하면 로그인 창을 통과하여 단독 테스트를 진행할 수 있습니다.</li> |
|||
<li><strong>장비 네트워크 통신 점검</strong></li> |
|||
<li>제어 PC와 계측 장비들(전압/저항 측정 장비, 전원 공급 장치) 간의 LAN 케이블 연결을 확인합니다.</li> |
|||
<li>제어 PC의 네트워크 IP 환경이 장비들의 대역과 동일한지 확인하고, 통신 신호가 정상적으로 송수신되는지 점검합니다.</li> |
|||
<li><strong>상시전원 자동 인가 확인</strong></li> |
|||
<li>프로그램 실행 후 작업자 계정으로 로그인을 시도합니다.</li> |
|||
<li>로그인이 완료되면 전원 공급 장치의 상시전원 채널 전원 램프가 자동으로 켜지는지 확인합니다.</li> |
|||
</ol> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>3. 메인 화면 (Home View)</h1> |
|||
<hr /> |
|||
<h2>3.1 메인 화면 레이아웃 구성</h2> |
|||
<p>본 프로그램은 작업자가 화면 구성 및 각 항목 상태를 파악할 수 있도록 4개의 카드 레이아웃으로 화면을 구성했습니다.</p> |
|||
<h3>3.1.1 상단 헤더 영역 (Header Bar)</h3> |
|||
<p>프로그램 최상단 영역에는 시스템 정보 배지와 제어 버튼이 배치되어 있습니다. |
|||
* <strong>실시간 시계</strong>: 좌측 상단에 날짜와 시간이 표시됩니다. |
|||
* <strong>작업 정보 배지</strong>: |
|||
* <strong>공정 라인</strong>: 로그인 단계에서 지정한 생산 라인 코드 (<code>Line No</code>) |
|||
* <strong>로트 번호</strong>: 로그인 단계에서 지정한 생산 로트 번호 (<code>Lot No</code>) |
|||
* <strong>모델명</strong>: 현재 가동 중인 제품의 사양 모델 (<code>Model</code>) |
|||
* <strong>작업자</strong>: 로그인한 작업자의 이름 (<code>Operator</code>) |
|||
* <strong>제어 버튼</strong>: 우측 상단에 <code>로그아웃</code> 버튼이 위치하며 최하단 바에 설정 관련 버튼이 배치됩니다.</p> |
|||
<hr /> |
|||
<h2>3.2 상태 및 제어 카드 영역</h2> |
|||
<p>화면 중앙에는 역할을 구분한 4개의 상태 카드가 배치되어 있어, 제품 상태와 계측 단계를 모니터링할 수 있습니다.</p> |
|||
<h3>3.2.1 [카드 1] 제품 정보 및 이전 결과 (좌측 상단)</h3> |
|||
<p>제품의 일련번호와 이전 생산 공정에서의 합격 이력을 대조하는 영역입니다. |
|||
* <strong>작업 모델 설정</strong>: |
|||
- <code>파일 선택</code> 버튼을 사용하여 각인용 도면 파일을 불러옵니다. |
|||
- 도면 파일 선택이 완료되면 상단 헤더 영역의 모델명(Model) 배지 텍스트가 선택한 도면명으로 자동 변경됩니다. |
|||
* <strong>일련번호 (IC_SN)</strong>: 제품이 안착되면 센서 판독기를 통해 자동으로 인식되어 표시됩니다. (읽기 전용) |
|||
* <strong>이전 공정 이력 배지</strong>: |
|||
* <strong>Housing</strong>: 하우징 조립 공정 판정 상태 (<code>PASS</code> / <code>FAIL</code> / <code>대기</code>) |
|||
* <strong>Calibration</strong>: 압력 보정 공정 판정 상태 (<code>PASS</code> / <code>FAIL</code> / <code>대기</code>) |
|||
* <strong>EOL</strong>: EOL 1차 성능 평가 판정 상태 (<code>PASS</code> / <code>FAIL</code> / <code>대기</code>) |
|||
* <em>주의: 이전 공정 이력 배지 중 하나라도 <code>FAIL</code> 상태인 경우 성능 검사를 시작할 수 없습니다.</em></p> |
|||
<h3>3.2.2 [카드 2] 측정 결과 (우측 상단)</h3> |
|||
<p>현재 장비에서 실제 계측한 3대 전기 파라미터(전압, 전류, 저항) 수치와 설정된 기준 규격 범위를 표시하는 영역입니다. |
|||
* <strong>측정 전압 (Voltage)</strong>: 전압 측정 장치가 측정한 전압 수치 (<strong>V</strong> 단위) |
|||
* <strong>측정 전류 (Current)</strong>: 전원 공급 장치가 측정한 소모 전류 수치 (<strong>mA</strong> 단위) |
|||
* <strong>측정 저항 (Resistance)</strong>: 저항 측정 장치가 측정한 전기적 저항 수치 (<strong>kΩ</strong> 단위) |
|||
* <em>알림: 각 물리량의 하단에는 현재 적용 중인 기준 규격 범위가 문구(<code>기준범위: X ~ Y</code>)로 표출되며, 실측값이 규격 범위 내에 도달하면 카드 테두리가 </em><em>초록색(PASS)</em><em>으로 표시되고, 범위를 벗어나면 테두리가 </em><em>빨간색(FAIL)</em><em>으로 바뀝니다.</em></p> |
|||
<h3>3.2.3 [카드 3] 진행상황 (좌측 하단)</h3> |
|||
<p>현재 설비가 수행하고 있는 단계별 자동 제어 시퀀스를 보여주는 안내 창입니다. |
|||
* "대기 상태", "제품 정보 수집 중...", "이전 공정 검사 결과 조회 중...", "측정 계측기 데이터 수집 중...", "제품 합격 - 레이저 각인 중..." 등 작동 상태를 실시간 텍스트로 표출합니다.</p> |
|||
<h3>3.2.4 [카드 4] 판정결과 (우측 하단)</h3> |
|||
<p>제품의 최종 합격(PASS) 및 불합격(FAIL) 상태를 표시합니다. |
|||
* 계측 검사와 데이터 저장, 레이저 각인이 완료되었을 때 최종 합격인 경우 카드 배경이 <strong>초록색(PASS)</strong>으로 전환되며, 불합격인 경우 카드 배경이 <strong>빨간색(FAIL)</strong>으로 변경됩니다.</p> |
|||
<h3>3.2.5 최하단 제어 영역 (Control Box)</h3> |
|||
<ul> |
|||
<li><strong>검사 시작 (START)</strong>: 전체 검사 시퀀스를 기동하는 메인 버튼입니다. 이 버튼을 누르면 이전 계측 수치들이 초기화되고 새로운 측정 프로세스가 개시됩니다.</li> |
|||
<li><strong>강제 검사 (스킵)</strong>: 이전 가공 공정의 합격 이력이 없더라도 검증 단계를 건너뛰고 성능 계측 및 각인 시퀀스를 기동하는 버튼입니다.</li> |
|||
<li><strong>테스트 마킹</strong>: 성능 계측 없이 즉시 각인기에 테스트 마킹 신호를 전송하는 버튼입니다.</li> |
|||
<li><em>참고: <code>강제 검사 (스킵)</code> 및 <code>테스트 마킹</code> 버튼은 환경 설정에서 테스트 모드가 활성화된 상태에서만 화면 하단에 노출됩니다.</em></li> |
|||
</ul> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>4. 통신 설정 (Comm. Settings)</h1> |
|||
<hr /> |
|||
<h2>4.1 포트 설정 화면 사용법</h2> |
|||
<p>프로그램 상단의 <code>통신 설정</code> 버튼을 클릭하면 포트 설정 대화 상자가 나타납니다. 이 대화 상자에서 센서 판독 장치(4251 보드)의 연결 포트 및 채널을 설정할 수 있습니다.</p> |
|||
<h3>주요 설정 항목 및 설명</h3> |
|||
<ol> |
|||
<li><strong>통신 포트 (Port)</strong>:</li> |
|||
<li>센서 판독기가 연결되어 있는 PC의 연결 포트를 선택합니다. (예: <code>COM1</code>, <code>COM3</code>, <code>COM4</code> 등)</li> |
|||
<li> |
|||
<p>현재 PC에 인식되어 있는 포트 목록이 자동으로 표시됩니다.</p> |
|||
</li> |
|||
<li> |
|||
<p><strong>통신 속도 (BaudRate)</strong>:</p> |
|||
</li> |
|||
<li>센서 판독 장치와의 데이터 송수신 속도를 설정합니다.</li> |
|||
<li> |
|||
<p>기본 설정값은 <strong><code>115200</code></strong> 이며, 특수한 경우가 아니면 변경하지 않는 것을 권장합니다.</p> |
|||
</li> |
|||
<li> |
|||
<p><strong>통신 채널 (Channel)</strong>:</p> |
|||
</li> |
|||
<li>센서 판독기 내부의 연결 채널을 결정합니다.</li> |
|||
<li>드롭다운 메뉴를 통해 <strong><code>CH1</code></strong> 또는 <strong><code>CH2</code></strong>를 선택할 수 있습니다.</li> |
|||
<li>선택된 채널에 따라 센서 인식 모드가 변경됩니다.</li> |
|||
</ol> |
|||
<hr /> |
|||
<h2>4.2 설정 저장</h2> |
|||
<ul> |
|||
<li><strong>설정 저장</strong>:<ul> |
|||
<li>통신 포트와 채널을 선택한 후 <code>저장</code> 버튼을 누르면 설정 정보가 저장됩니다.</li> |
|||
<li>저장 시 기존 센서 연결을 해제하고 새로운 설정값으로 센서 인식 서비스를 다시 시작합니다. 프로그램을 재시작할 필요 없이 변경 사항이 즉시 적용됩니다.</li> |
|||
<li>저장하지 않고 창을 닫으려면 <code>취소</code> 버튼을 누릅니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>5. 시험 설정 (Parameters)</h1> |
|||
<hr /> |
|||
<h2>5.1 판정 기준 설정</h2> |
|||
<p>프로그램 상단 우측의 <code>시험 설정</code> 버튼을 클릭하면 판정 기준을 구성하는 대화 상자가 나타납니다. 이 화면에서 제품 합불 판정에 사용되는 전압, 전류, 저항의 기준값을 입력할 수 있습니다.</p> |
|||
<h3>5.1.1 각 항목별 한계치 입력 가이드</h3> |
|||
<ul> |
|||
<li><strong>전압 판정 범위</strong>:<ul> |
|||
<li><strong>하한값</strong>: 합격 전압 하한 규격 (V 단위)</li> |
|||
<li><strong>상한값</strong>: 합격 전압 상한 규격 (V 단위)</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>전류 판정 범위</strong>:<ul> |
|||
<li><strong>하한값</strong>: 합격 전류 하한 규격 (설정창 표기 단위 참조, 기본 mA/A)</li> |
|||
<li><strong>상한값</strong>: 합격 전류 상한 규격 (설정창 표기 단위 참조, 기본 mA/A)</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>저항 판정 범위</strong>:<ul> |
|||
<li><strong>하한값</strong>: 합격 저항 하한 규격 (설정창 표기 단위 참조, 기본 Ω/kΩ)</li> |
|||
<li><strong>상한값</strong>: 합격 저항 상한 규격 (설정창 표기 단위 참조, 기본 Ω/kΩ)</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<p><em>참고: 저장 버튼을 클릭하면 메인 화면의 하단 가이드 문구(<code>기준범위: X ~ Y</code>)가 즉시 갱신되어 새로 입력한 한계치가 다음 검사 시퀀스부터 반영됩니다.</em></p> |
|||
<hr /> |
|||
<h2>5.2 레이저 각인 도면 지정</h2> |
|||
<ul> |
|||
<li><strong>각인 파일 설정 경로</strong>:<ul> |
|||
<li>레이저 마킹기에서 사용할 작업 도면 파일 선택은 설정 대화 상자가 아닌, <strong>메인 화면 좌측 상단의 '작업 모델 설정' 영역에 있는 '파일 선택' 버튼</strong>을 클릭하여 수행합니다.</li> |
|||
<li>도면이 선택되면 상단 헤더 배지의 모델명 정보도 해당 도면 파일명으로 자동으로 변경됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>유의 사항</strong>:<ul> |
|||
<li>지정해 놓은 도면 파일이 실제 경로에 존재하지 않는 경우, 계측 성능 검사가 합격하더라도 각인 단계에서 에러가 납니다. 검사 전 파일 경로 상태를 확인하십시오.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<h2>5.3 설정 저장 및 적용</h2> |
|||
<ul> |
|||
<li>설정 창의 <code>저장</code> 버튼을 클릭하면 변경된 파라미터가 시스템 설정에 저장됩니다.</li> |
|||
<li>저장 완료 즉시 <strong>메인 화면 하단에 표시되는 판정 기준 가이드 텍스트</strong>가 업데이트되며, 이후에 새로 시작하는 성능 검사 시퀀스부터 새로운 규격치가 적용됩니다.</li> |
|||
</ul> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>6. 측정 데이터 조회 및 데이터베이스 연동</h1> |
|||
<hr /> |
|||
<h2>6.1 선행 공정 결과 조회 (이력 확인)</h2> |
|||
<p>본 프로그램은 검사 시작 시 입력된 제품 일련번호를 기반으로 생산 데이터베이스에 접속하여 이전 제조 공정의 합격 여부를 조회합니다.</p> |
|||
<h3>6.1.1 이력 검토 대상 공정</h3> |
|||
<p>시스템은 다음 3개의 선행 공정 검사 결과를 확인합니다. |
|||
1. <strong>하우징 조립 공정</strong> |
|||
2. <strong>센서 오차 보정 공정</strong> |
|||
3. <strong>1차 EOL 성능 검사</strong></p> |
|||
<h3>6.1.2 이전 단계 규격 교차 확인 동작</h3> |
|||
<ul> |
|||
<li>이전 3개 선행 단계의 이력이 <strong>모두 합격(PASS 또는 OK)</strong>된 제품인 경우에만 최종 성능검사(EOL2)를 진행할 수 있습니다.</li> |
|||
<li>선행 이력이 존재하지 않거나, 단 한 곳이라도 불합격(FAIL 또는 NG) 판정을 받은 경우 화면 진행 상황 표시창에 경고가 표시되며 최종 성능검사 시작이 제한됩니다.</li> |
|||
</ul> |
|||
<hr /> |
|||
<h2>6.2 검사 결과 자동 적재 및 최종 판정 기록</h2> |
|||
<p>자동 계측 프로세스가 종료되면 다음 정보가 생산 데이터베이스에 저장됩니다.</p> |
|||
<ul> |
|||
<li><strong>저장 정보</strong>:<ul> |
|||
<li>제품 일련번호</li> |
|||
<li>생산 라인, 로트 번호, 작업자 정보</li> |
|||
<li>실측 전압, 전류, 저항값<ul> |
|||
<li>실측값은 데이터베이스 저장 규격에 맞춰 시스템 내부에서 소수점 이하 자리로 정밀 정리되어 저장됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li>최종 판정 결과 (<code>PASS</code> / <code>FAIL</code>)</li> |
|||
<li>마킹 시퀀스 번호 및 성공 기록</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>비동기 데이터 처리</strong>:<ul> |
|||
<li>데이터베이스 통신 대기로 인한 화면 멈춤 현상을 방지하기 위해 데이터 조회 및 저장 작업은 프로그램 화면 동작과 별개로 백그라운드에서 비동기식으로 안전하게 처리됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<h2>6.3 오프라인 모드 운용</h2> |
|||
<p>데이터베이스 서버 접속이 불가능한 환경에서도 단독으로 설비를 가동할 수 있도록 <strong>오프라인 모드</strong>를 지원합니다.</p> |
|||
<ul> |
|||
<li><strong>활성화 목적</strong>:<ul> |
|||
<li>네트워크 연결이 끊긴 상태에서 프로그램의 단독 동작 및 장비 제어 상태를 확인하기 위함입니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>오프라인 작동 패턴</strong>:<ul> |
|||
<li><strong>공정 조회 우회</strong>: 입력된 일련번호에 대해 생산 데이터베이스 서버 접속 없이 이전 공정을 합격한 것으로 우회 처리합니다.</li> |
|||
<li><strong>임시 일련번호 생성</strong>: 일련번호가 비어 있는 상태에서 테스트를 개시하는 경우 현재 시간 기반의 임시 일련번호가 자동으로 부여되어 진행합니다.</li> |
|||
<li><strong>각인 모사</strong>: 실제 각인기에 데이터를 전송하는 단계를 가상 성공 처리하여 전체 흐름을 테스트합니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>7. 자동 시험 프로세스 및 15단계 시퀀스</h1> |
|||
<hr /> |
|||
<h2>7.1 자동 시험 및 마킹 프로세스 개요</h2> |
|||
<p>본 프로그램은 사용자가 메인 화면 하단의 <code>검사 시작 (START)</code> 버튼을 누르면 데이터 저장까지의 과정이 자동 계측 시퀀스에 따라 순차적으로 동작하도록 구성되어 있습니다.</p> |
|||
<pre><code class="language-mermaid">graph TD |
|||
A[START 버튼 클릭] --> B[UI 화면 수치 초기화] |
|||
B --> C[4~8단계: 센서 S/N 읽기 및 보정] |
|||
C --> D{선행 공정 이력 확인} |
|||
D -- 불합격/미진행 --> E[검사 중단 & 경고 팝업] |
|||
E --> F{강제 검사 스킵?} |
|||
F -- 취소 --> Z[대기 복구] |
|||
F -- 스킵 실행 --> G[9~15단계: 계측 시퀀스 기동] |
|||
D -- 3개 공정 모두 PASS --> G |
|||
G --> H[10단계: 테스트 주전원 ON] |
|||
H --> I[12~14단계: 전압 / 저항 / 전류 실측] |
|||
I --> J[15단계: 테스트 주전원 안전 차단] |
|||
J --> K{최종 규격 비교 판정} |
|||
K -- 1개 이상 이탈 FAIL --> L[대형 FAIL 표시 & 마킹 제외 & DB 불합격 적재] |
|||
K -- 모두 통과 PASS --> M[대형 PASS 표시 & DB 합격 적재 & LMC1 레이저 QR 각인] |
|||
L --> Z |
|||
M --> Z |
|||
</code></pre> |
|||
<hr /> |
|||
<h2>7.2 상세 15단계 자동 제어 시퀀스</h2> |
|||
<p>최종 검사가 시작되면 장비와 계측기들은 다음 15가지 단계에 따라 동작을 차례대로 수행합니다.</p> |
|||
<h3>[1단계] 사전 전원 인가 단계 (최초 가동/로그인 시 1회 진행)</h3> |
|||
<ul> |
|||
<li><strong>1단계 [장비 확인]</strong>: 전원 공급 장치와의 통신 연결 상태를 점검합니다.</li> |
|||
<li><strong>2단계 [센서 구동 전압 설정]</strong>: 센서 보드를 구동하는 데 필요한 전압을 전원 장치에 설정합니다.</li> |
|||
<li><strong>3단계 [센서 구동 전원 출력]</strong>: 설정된 전원을 출력하여 보드를 부팅합니다.</li> |
|||
<li><em>(참고: 이 단계는 로그인 성공 시 1회만 실행되며, 이후의 반복 검사 과정에서는 이미 투입된 전원을 재사용하여 4단계부터 즉각 검사가 수행됩니다)</em></li> |
|||
</ul> |
|||
<h3>[2단계] 제품 일련번호 수집 및 센서 통신 대기 단계</h3> |
|||
<ul> |
|||
<li><strong>4단계 [판독 장치 대기]</strong>: 센서 판독 장치를 초기 대기 상태로 설정합니다.</li> |
|||
<li><strong>5단계 [보드 통신 연결]</strong>: 통신 설정에 명시된 채널을 선택하여 센서 보드와 연결합니다.</li> |
|||
<li><strong>6단계 [일련번호 읽기]</strong>: 제품 메모리로부터 스캔한 고유 일련번호를 로드합니다.</li> |
|||
<li><strong>7단계 [보드 통신 해제]</strong>: 센서 데이터 전송을 중지하고 대기 상태로 되돌립니다.</li> |
|||
<li><strong>8단계 [보정 기준 전송]</strong>: 센서 장치에 보정 기준값을 인계하고 동작을 종료합니다.</li> |
|||
</ul> |
|||
<h3>[3단계] 계측기 연동 성능 평가 및 전원 차단 단계</h3> |
|||
<ul> |
|||
<li><strong>9단계 [전원 장비 확인]</strong>: 주 테스트 전원을 공급할 전원 장치의 통신 상태를 확인합니다.</li> |
|||
<li><strong>10단계 [테스트 전원 인가]</strong>: 테스트 전원 출력을 ON시키고, 전원 인가 후 신호 안정을 위해 잠시 대기합니다.</li> |
|||
<li><strong>11단계 [측정 장비 확인]</strong>: 측정 장치의 통신 상태를 확인합니다.</li> |
|||
<li><strong>12단계 [전압 측정]</strong>: 제품의 현재 작동 전압을 측정합니다.</li> |
|||
<li><strong>13단계 [저항 측정]</strong>: 제품의 전기적 저항값을 직접 실측합니다.</li> |
|||
<li><strong>14단계 [전류 측정]</strong>: 전원 공급 장치의 출력 채널을 통해 제품의 작동 소모 전류를 측정합니다.</li> |
|||
<li><strong>15단계 [테스트 전원 차단]</strong>: 수집 완료 후 테스트 전원 출력을 자동으로 차단하여 제품을 안전하게 보호합니다. (계측 도중 오류가 발생하더라도 강제로 전원이 차단되도록 안전 장치가 적용되어 있습니다.)</li> |
|||
</ul> |
|||
<hr /> |
|||
<h2>7.3 최종 판정 및 마킹 실행 조건</h2> |
|||
<p>계측이 완료되면 측정된 전압(V), 저항(kΩ), 전류(mA) 값을 설정한 기준 규격값(SPEC)과 비교하여 최종 판정을 내립니다.</p> |
|||
<ol> |
|||
<li><strong>기준 규격을 벗어난 경우 (FAIL)</strong>:<ul> |
|||
<li>전압, 전류, 저항 중 하나라도 기준을 벗어나면 최종 불합격(FAIL) 판정이 내려집니다.</li> |
|||
<li>이 경우 레이저 마킹 장비 구동은 자동으로 제외(Skip)되며, 불합격 내역으로 DB에 기록됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>모든 항목이 합격인 경우 (PASS)</strong>:<ul> |
|||
<li>모든 수치가 기준치 내에 들어오면 최종 합격(PASS) 판정이 내려집니다.</li> |
|||
<li>합격 판정과 동시에 레이저 마킹기에 각인 데이터가 전달되어 2D QR 코드 및 제품 일련번호 각인이 자동으로 실행됩니다.</li> |
|||
<li>마킹 완료 기록과 계측 수치는 최종 PASS 상태로 데이터베이스에 저장됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ol> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>8. 로그 및 데이터 관리</h1> |
|||
<hr /> |
|||
<h2>8.1 시스템 로그 수집 및 관리</h2> |
|||
<p>본 제어 프로그램은 설비 가동 중에 발생하는 계측기와의 통신 상태, 측정값 정보 및 각종 예외 오류 상황을 로그 파일로 기록합니다.</p> |
|||
<h3>8.1.1 로그 파일 보관 방법</h3> |
|||
<ul> |
|||
<li><strong>보관 폴더</strong>: 프로그램 실행 파일 경로의 하위 <strong><code>Logs</code></strong> 폴더에 저장됩니다.</li> |
|||
<li><strong>파일명 규칙</strong>: 날짜별로 파일이 자동으로 생성되어 보관됩니다.</li> |
|||
<li><strong>로그 중요도 분류</strong>:<ul> |
|||
<li><strong>정보 (INFO)</strong>: 정상적인 검사 프로세스 시작, 계측기 연결 성공, 레이저 인쇄 성공 및 데이터베이스 저장 완료 기록.</li> |
|||
<li><strong>경고 (WARN)</strong>: 센서 판독기 인식 지연, 제품 한계 기준치를 벗어난 불합격(FAIL) 발생 기록 등 설비 동작은 유지되나 품질 확인이 필요한 정보.</li> |
|||
<li><strong>오류 (ERROR)</strong>: 데이터베이스 네트워크 접속 끊김, 마킹 장치 연결 실패 등 조치가 필요한 장비 오류 정보.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<h2>8.2 장비 교체 및 프로그램 백업 방법</h2> |
|||
<p>장비를 교환하거나 PC 복구 상황에 대비하여, 정상 작동 상태에서의 설정 파일들을 정기적으로 백업해 둘 것을 권장합니다.</p> |
|||
<h3>8.2.1 백업 대상 리스트</h3> |
|||
<ol> |
|||
<li><strong>계측기 설정 및 검사 기준값 백업</strong>:<ul> |
|||
<li>계측기들의 연결 설정 정보와 합격 판정 기준 범위가 저장됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>데이터베이스 서버 정보 백업</strong>:<ul> |
|||
<li>생산 정보 데이터베이스 서버 주소와 로그인 정보가 저장됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>센서 채널 정보 백업</strong>:<ul> |
|||
<li>일련번호 판독 통신 포트 번호와 설정 채널 정보가 저장됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>레이저 마킹 도면 파일 백업</strong>:<ul> |
|||
<li>제품 표면에 각인할 마킹 도면 파일입니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ol> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
<div class="page-break"></div> |
|||
|
|||
<h1>9. 오류 대응 및 프로그램 종료</h1> |
|||
<hr /> |
|||
<h2>9.1 현장 장애 유형별 점검 및 예외 조치 요령</h2> |
|||
<p>공정 가동 중 장비 상태나 전산망에 이상이 생길 경우 발생할 수 있는 주요 화면 경고창 및 조치 요령입니다.</p> |
|||
<h3>9.1.1 [오류 1] "제품 ID(IC_SN)를 읽어오지 못했습니다"</h3> |
|||
<ul> |
|||
<li><strong>현상</strong>: 검사 시작 시 제품 일련번호 읽기 단계에서 경고창이 발생하고 검사가 취소됨.</li> |
|||
<li><strong>원인 및 해결</strong>:<ol> |
|||
<li><strong>접촉 상태 점검</strong>: 제품이 안착 지그에 완벽하게 안착되었는지 확인하고, 프레스 실린더 또는 핀 단자의 밀착 상태를 확인하십시오.</li> |
|||
<li><strong>통신 설정 점검</strong>: 프로그램 상단의 <code>통신 설정</code> 창을 열어 현재 설정된 포트 번호 및 물리 채널 번호가 실제 케이블 연결 상태와 일치하는지 확인하십시오.</li> |
|||
</ol> |
|||
</li> |
|||
</ul> |
|||
<h3>9.1.2 [오류 2] "이전 공정 이력이 조회되지 않는 제품입니다"</h3> |
|||
<ul> |
|||
<li><strong>현상</strong>: 검사 시작 시 이전 단계 결과가 조회되지 않아 검사가 진행되지 않음.</li> |
|||
<li><strong>원인 및 해결</strong>:<ul> |
|||
<li>해당 제품이 하우징 조립, 센서 보정, EOL 1차 성능 검사 등 이전 가공 공정을 진행하지 않았거나, 이전 설비에서 생산 DB에 데이터를 올바르게 전송하지 않은 상태입니다. 제품 바코드를 재확인하고 이전 설비의 데이터 전송 유무를 검토하십시오.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>비상 조치 (강제 검사)</strong>:<ul> |
|||
<li>이전 이력 등록 상태와 무관하게 <strong>제품 성능 계측 및 마킹을 실행하고 결과를 저장해야 하는 특수 테스트 상황</strong>인 경우, 화면 최하단의 <strong><code>강제 검사 (스킵)</code></strong> 버튼을 누르면 DB 검증을 건너뛰고 성능 검사를 강제로 실행할 수 있습니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<h3>9.1.3 [오류 3] "이전 공정 단계가 불합격 상태이므로 최종 성능 검사를 시작할 수 없습니다"</h3> |
|||
<ul> |
|||
<li><strong>현상</strong>: DB 조회 결과 이전 공정 중 불합격(FAIL 또는 NG) 판정을 받은 내역이 발견되어 검사가 중단됨.</li> |
|||
<li><strong>원인 및 해결</strong>:<ul> |
|||
<li>이전 공정에서 불합격 판정을 받은 제품은 최종 평가 및 레이저 마킹을 가동할 수 없습니다. 불량 제품 격리 기준에 따라 해당 제품을 생산 라인에서 제외 조치하십시오.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>비상 조치 (강제 검사)</strong>:<ul> |
|||
<li>설비 작동 확인이나 품질 분석 등을 위해 반드시 검사를 진행해야 하는 경우, 하단바의 <strong><code>강제 검사 (스킵)</code></strong> 버튼을 클릭하면 경고 상태를 건너뛰고 계측과 마킹을 실행할 수 있습니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<h3>9.1.4 [오류 4] "레이저 각인 작업 전송 실패"</h3> |
|||
<ul> |
|||
<li><strong>현상</strong>: 성능 검사는 합격(PASS)했으나, 레이저 장비로의 데이터 전송 단계에서 경고 에러가 발생함.</li> |
|||
<li><strong>원인 및 해결</strong>:<ol> |
|||
<li><strong>도면 파일 점검</strong>: <code>시험 설정</code> 화면에서 세팅해 놓은 작업 도면 파일이 실제 해당 경로에 존재하는지 점검하십시오.</li> |
|||
<li><strong>마킹기 전원/연결 점검</strong>: 레이저 마킹기의 전원이 켜져 있는지 확인하고, 제어 PC와 마킹기 간의 연결 케이블 상태를 확인하십시오.</li> |
|||
</ol> |
|||
</li> |
|||
</ul> |
|||
<h3>9.1.5 [오류 5] "각인 순번이 9999를 초과했습니다. 다음 Lot No로 변경하십시오."</h3> |
|||
<ul> |
|||
<li><strong>현상</strong>:<ul> |
|||
<li>프로그램 실행 또는 로그인 완료 후, 메인 화면 상태 알림창에 빨간색 경고 배너로 문구가 표시됩니다.</li> |
|||
<li><code>검사 시작 (START)</code> 또는 <code>강제 검사 (스킵)</code> 버튼을 누르면 작동 차단 경고창이 나타나며 설비 검사가 시작되지 않습니다.</li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>원인 및 해결</strong>:<ul> |
|||
<li><strong>순번 범위 초과</strong>: 현재 로트 번호(<code>Lot No</code>)에서 최종 합격을 받아 각인이 완료된 누적 수량이 9999개를 초과하여 더 이상 순차 번호를 인쇄할 수 없습니다.</li> |
|||
<li><strong>해결 방법</strong>: 새로운 생산 조 또는 로트 번호(<code>Lot No</code>)를 수정하여 <strong>프로그램에 재로그인</strong>하십시오. 로트 번호가 변경되면 순번 카운트가 다시 초기화됩니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<h2>9.2 프로그램 정상 종료 및 전원 자동 차단 규칙</h2> |
|||
<p>본 설비는 고전력 계측 및 전원 제어를 함께 수행하므로 대기 전력 소모 방지와 안전을 위해 아래 절차에 따라 정상 종료 프로세스를 밟아야 합니다.</p> |
|||
<ul> |
|||
<li><strong>로그아웃 (Logout)</strong>:<ul> |
|||
<li>상단 메뉴의 <code>로그아웃</code> 버튼을 클릭하면 현재 작업자 정보가 해제되고 초기 로그인 창으로 전환됩니다.</li> |
|||
<li><strong>이와 동시에 연동된 전원 공급 장치로 차단 신호가 자동으로 전송되어 주전원 및 보드 부팅용 상시전원 출력이 OFF 상태로 차단됩니다.</strong></li> |
|||
</ul> |
|||
</li> |
|||
<li><strong>프로그램 완전 종료</strong>:<ul> |
|||
<li>화면 우측 상단의 <code>닫기(X)</code> 버튼을 눌러 프로그램을 최종 종료할 때도, 자동으로 상시전원 차단 명령을 장비에 인계한 뒤 레이저 각인 드라이버 리소스를 닫고 메모리를 환원합니다.</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
<hr /> |
|||
<p><em>본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.</em></p> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,163 @@ |
|||
# -*- coding: utf-8 -*- |
|||
import os |
|||
import re |
|||
|
|||
def clean_markdown_content(filename, content, link_mapping): |
|||
# 1. 목차/이전/다음 등 내비게이션 링크 제거 패턴 |
|||
lines = content.split('\n') |
|||
cleaned_lines = [] |
|||
|
|||
for line in lines: |
|||
stripped = line.strip() |
|||
is_nav = False |
|||
if "메뉴얼 목차로 돌아가기" in stripped: |
|||
is_nav = True |
|||
elif "이전:" in stripped and "다음:" in stripped: |
|||
is_nav = True |
|||
elif stripped.startswith("[다음:") and stripped.endswith(")"): |
|||
is_nav = True |
|||
elif stripped.startswith("[← 이전:") and stripped.endswith(")"): |
|||
is_nav = True |
|||
|
|||
if not is_nav: |
|||
cleaned_lines.append(line) |
|||
|
|||
content = '\n'.join(cleaned_lines) |
|||
|
|||
# 2. Obsidian 위키링크 이미지 문법 -> HTML img 태그로 치환 |
|||
content = re.sub(r'!\[\[(.*?)\]\]', r'<img src="./\1" alt="\1" />', content) |
|||
|
|||
# 3. 마크다운 파일 참조 링크 -> 로컬 앵커로 치환 |
|||
for md_file, anchor in link_mapping.items(): |
|||
content = content.replace(f"({md_file})", f"({anchor})") |
|||
|
|||
# 4. 각 파일 시작 전에 페이지 나누기 추가 (표지 파일은 제외) |
|||
is_cover = "사용자" in filename or "메뉴얼" in filename |
|||
if not is_cover: |
|||
content = '<div class="page-break"></div>\n\n' + content |
|||
|
|||
# 5. 불필요하게 연속된 빈 라인 및 구분선 정리 |
|||
content = re.sub(r'^\s*---\s*\n', '', content) # 문서 시작 부분의 --- 제거 |
|||
content = re.sub(r'\n\s*---\s*$', '', content) # 문서 끝 부분의 --- 제거 |
|||
|
|||
return content |
|||
|
|||
def main(): |
|||
manual_dir = os.path.dirname(os.path.abspath(__file__)) |
|||
merged_md_path = os.path.join(manual_dir, "Manual_Merged.md") |
|||
style_path = os.path.join(manual_dir, "pdf_style.css") |
|||
|
|||
# CSS 파일 로드 |
|||
css_content = "" |
|||
if os.path.exists(style_path): |
|||
with open(style_path, "r", encoding="utf-8") as f: |
|||
css_content = f.read() |
|||
else: |
|||
print(f"경고: 스타일시트 파일을 찾을 수 없습니다: {style_path}") |
|||
|
|||
# 디렉토리 파일들을 UTF-8 유니코드로 스캔 |
|||
all_files = os.listdir(manual_dir) |
|||
|
|||
# 표지 파일 찾기 |
|||
cover_file = None |
|||
for f in all_files: |
|||
if f.endswith(".md") and ("사용자" in f or "메뉴얼" in f) and "Merged" not in f: |
|||
cover_file = f |
|||
break |
|||
|
|||
# "01_" ~ "09_"로 시작하는 검사 매뉴얼 파일 수집 |
|||
numbered_files = [] |
|||
for f in all_files: |
|||
if f.endswith(".md") and re.match(r'^\d+', f): |
|||
numbered_files.append(f) |
|||
|
|||
# 순서 보장을 위해 정렬 |
|||
numbered_files.sort() |
|||
|
|||
# 최종 병합 리스트 빌드 |
|||
final_file_list = [] |
|||
if cover_file: |
|||
final_file_list.append(cover_file) |
|||
final_file_list.extend(numbered_files) |
|||
|
|||
print("감지 및 병합할 파일 목록:") |
|||
for f in final_file_list: |
|||
print(f" - {f}") |
|||
|
|||
# 링크 치환용 맵 작성 (인코딩 호환성을 위해 파일명 동적 파싱) |
|||
link_mapping = {} |
|||
for f in final_file_list: |
|||
if "사용자" in f or "메뉴얼" in f: |
|||
link_mapping[f] = "#performance-inspect--laser-marking-system---사용자-메뉴얼" |
|||
elif f.startswith("01"): |
|||
link_mapping[f] = "#1-시스템-개요-및-요구사항" |
|||
elif f.startswith("02"): |
|||
link_mapping[f] = "#2-초기-설정-가이드" |
|||
elif f.startswith("03"): |
|||
link_mapping[f] = "#3-메인-화면-home-view" |
|||
elif f.startswith("04"): |
|||
link_mapping[f] = "#4-통신-설정-comm-settings" |
|||
elif f.startswith("05"): |
|||
link_mapping[f] = "#5-시험-설정-parameters" |
|||
elif f.startswith("06"): |
|||
link_mapping[f] = "#6-측정-데이터-조회-및-데이터베이스-연동" |
|||
elif f.startswith("07"): |
|||
link_mapping[f] = "#7-자동-시험-프로세스-및-14단계-시퀀스" |
|||
elif f.startswith("08"): |
|||
link_mapping[f] = "#8-로그-및-데이터-관리" |
|||
elif f.startswith("09"): |
|||
link_mapping[f] = "#9-오류-대응-및-프로그램-종료" |
|||
|
|||
merged_markdown_only = "" |
|||
|
|||
for file_name in final_file_list: |
|||
file_path = os.path.join(manual_dir, file_name) |
|||
print(f"병합 처리 중: {file_name}...") |
|||
with open(file_path, "r", encoding="utf-8") as f: |
|||
content = f.read() |
|||
|
|||
cleaned = clean_markdown_content(file_name, content, link_mapping) |
|||
merged_markdown_only += cleaned + "\n\n" |
|||
|
|||
# md 파일 저장용에는 style 포함 |
|||
merged_content = "" |
|||
if css_content: |
|||
merged_content += f"<style>\n{css_content}\n</style>\n\n" |
|||
merged_content += merged_markdown_only |
|||
|
|||
# 병합된 마크다운 저장 |
|||
with open(merged_md_path, "w", encoding="utf-8") as f: |
|||
f.write(merged_content) |
|||
|
|||
print(f"\n성공: 통합 마크다운 파일이 생성되었습니다 -> {merged_md_path}") |
|||
|
|||
# HTML 생성 시도 |
|||
try: |
|||
import markdown |
|||
merged_html_path = os.path.join(manual_dir, "Manual_for_pdf.html") |
|||
|
|||
# HTML 뼈대 구성 |
|||
html_output = f"""<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title>Performance Inspect & Laser Marking System - 사용자 메뉴얼</title> |
|||
<style> |
|||
{css_content} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
""" |
|||
html_body = markdown.markdown(merged_markdown_only, extensions=['tables', 'fenced_code']) |
|||
html_output += html_body |
|||
html_output += "\n</body>\n</html>" |
|||
|
|||
with open(merged_html_path, "w", encoding="utf-8") as f: |
|||
f.write(html_output) |
|||
|
|||
print(f"성공: 통합 HTML 파일이 생성되었습니다 -> {merged_html_path}") |
|||
except ImportError: |
|||
print("\n참고: 파이썬 'markdown' 패키지가 설치되지 않아 HTML 빌드를 건너뜁니다. (pip install markdown)") |
|||
|
|||
if __name__ == "__main__": |
|||
main() |
|||
@ -0,0 +1,213 @@ |
|||
/* |
|||
* A4 용지 기준 PDF 출력을 위한 스타일시트 (pdf_style.css) |
|||
*/ |
|||
|
|||
@page { |
|||
size: A4; |
|||
margin: 20mm 15mm 20mm 15mm; |
|||
@top-left { content: none !important; } |
|||
@top-right { content: none !important; } |
|||
@bottom-left { content: none !important; } |
|||
@bottom-right { content: none !important; } |
|||
@bottom-center { |
|||
content: counter(page) !important; |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans KR", sans-serif; |
|||
font-size: 8.5pt; |
|||
color: #7f8c8d; |
|||
} |
|||
} |
|||
|
|||
body { |
|||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans KR", sans-serif; |
|||
font-size: 10pt; |
|||
line-height: 1.6; |
|||
color: #333333; |
|||
background-color: #ffffff; |
|||
-webkit-print-color-adjust: exact !important; |
|||
print-color-adjust: exact !important; |
|||
} |
|||
|
|||
/* 제목 스타일 */ |
|||
h1, h2, h3, h4, h5, h6 { |
|||
color: #111111; |
|||
font-weight: bold; |
|||
page-break-after: avoid; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
h1 { |
|||
font-size: 18pt; |
|||
border-bottom: 2px solid #007acc; |
|||
padding-bottom: 4px; |
|||
margin-top: 20px; |
|||
margin-bottom: 12px; |
|||
} |
|||
|
|||
h2 { |
|||
font-size: 13pt; |
|||
border-bottom: 1px solid #e1e4e8; |
|||
padding-bottom: 3px; |
|||
margin-top: 16px; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
h3 { |
|||
font-size: 11pt; |
|||
margin-top: 12px; |
|||
margin-bottom: 6px; |
|||
} |
|||
|
|||
h4 { |
|||
font-size: 10pt; |
|||
margin-top: 10px; |
|||
margin-bottom: 6px; |
|||
} |
|||
|
|||
/* 문단 및 리스트 */ |
|||
p { |
|||
margin-top: 0; |
|||
margin-bottom: 8px; |
|||
text-align: justify; |
|||
} |
|||
|
|||
ul, ol { |
|||
margin-top: 0; |
|||
margin-bottom: 8px; |
|||
padding-left: 20px; |
|||
} |
|||
|
|||
li { |
|||
margin-bottom: 3px; |
|||
} |
|||
|
|||
/* 구분선 */ |
|||
hr { |
|||
height: 1px; |
|||
padding: 0; |
|||
margin: 15px 0; |
|||
background-color: #e1e4e8; |
|||
border: 0; |
|||
} |
|||
|
|||
/* 테이블 스타일 */ |
|||
table { |
|||
width: 100%; |
|||
border-collapse: collapse; |
|||
margin-top: 0; |
|||
margin-bottom: 10px; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
table th, table td { |
|||
padding: 4px 8px; |
|||
border: 1px solid #dfe2e5; |
|||
font-size: 8.5pt; |
|||
word-break: keep-all; |
|||
} |
|||
|
|||
table th { |
|||
font-weight: 600; |
|||
background-color: #f6f8fa; |
|||
text-align: left; |
|||
} |
|||
|
|||
table tr:nth-child(even) { |
|||
background-color: #f9fbfd; |
|||
} |
|||
|
|||
table tr { |
|||
page-break-inside: avoid; /* 표의 중간 행이 반으로 쪼개지는 것만 방지 */ |
|||
} |
|||
|
|||
/* 인용구 스타일 */ |
|||
blockquote { |
|||
padding: 6px 12px; |
|||
color: #6a737d; |
|||
border-left: 0.25em solid #007acc; |
|||
background-color: #f6f8fa; |
|||
margin: 0 0 10px 0; |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
blockquote p { |
|||
margin: 0; |
|||
} |
|||
|
|||
/* 코드 블록 (아스크 아트 등 포함) */ |
|||
pre, code { |
|||
font-family: "Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", monospace; |
|||
font-size: 8.5pt; |
|||
background-color: #f6f8fa; |
|||
border-radius: 3px; |
|||
} |
|||
|
|||
code { |
|||
padding: 0.2em 0.4em; |
|||
margin: 0; |
|||
border: 1px solid #eaecef; |
|||
} |
|||
|
|||
pre { |
|||
padding: 12px; |
|||
overflow: auto; |
|||
line-height: 1.45; |
|||
border: 1px solid #e1e4e8; |
|||
word-wrap: normal; |
|||
white-space: pre; /* 아스키 아트 정렬 유지를 위해 강제 줄바꿈 해제 */ |
|||
page-break-inside: avoid; |
|||
} |
|||
|
|||
pre code { |
|||
padding: 0; |
|||
margin: 0; |
|||
background-color: transparent; |
|||
border: none; |
|||
font-size: inherit; |
|||
white-space: inherit; |
|||
} |
|||
|
|||
/* 이미지 스타일 */ |
|||
img { |
|||
max-width: 100%; |
|||
max-height: 100mm; /* A4 높이의 약 절반 이하로 제한 */ |
|||
display: block; |
|||
margin: 15px auto; |
|||
object-fit: contain; |
|||
page-break-inside: avoid; |
|||
border: 1px solid #e1e4e8; |
|||
box-shadow: 0 1px 3px rgba(0,0,0,0.1); |
|||
} |
|||
|
|||
/* 페이지 나누기 요소 */ |
|||
.page-break { |
|||
page-break-before: always !important; |
|||
} |
|||
|
|||
/* 내비게이션 숨김 (인쇄 시) */ |
|||
.nav-link, .nav-links, .back-to-toc, .manual-nav, |
|||
a[href$=".md"] { |
|||
display: none !important; |
|||
} |
|||
|
|||
/* 링크 스타일 */ |
|||
a { |
|||
color: #007acc; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
a:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
/* 특별 배지 스타일 */ |
|||
.badge { |
|||
display: inline-block; |
|||
padding: 2px 6px; |
|||
font-size: 8pt; |
|||
font-weight: 600; |
|||
line-height: 1; |
|||
border-radius: 2px; |
|||
background-color: #e1e4e8; |
|||
color: #24292e; |
|||
margin-right: 4px; |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
# Performance Inspect & Laser Marking System - 사용자 메뉴얼 |
|||
|
|||
> **버전**: 1.0.0 | **최종 수정**: 2026-07-14 |
|||
|
|||
--- |
|||
|
|||
## 메뉴얼 목차 |
|||
|
|||
본 메뉴얼은 각 주제별로 별도 문서로 구성되어 있습니다. 아래 링크를 클릭하여 해당 문서로 이동하세요. |
|||
|
|||
| 번호 | 문서 | 설명 | |
|||
|------|------|------| |
|||
| 1 | [시스템 개요 및 요구사항](01_시스템_개요.md) | 프로그램 소개, 주요 기능, 하드웨어/소프트웨어 요구사항, 장비 구성 | |
|||
| 2 | [초기 설정 가이드](02_초기_설정.md) | 설정 파일의 구성 요소 안내 및 최초 장비 가동 시 점검 순서 | |
|||
| 3 | [메인 화면 (Home View)](03_메인_화면.md) | 상단 정보 표시, 제품 정보 카드, 검사 결과 화면, 진행 상황 확인 및 버튼 제어 가이드 | |
|||
| 4 | [통신 설정 (Comm. Settings)](04_통신_설정.md) | 4251 센서 통신 채널 설정 및 PC 통신 포트 연동 방법 | |
|||
| 5 | [시험 설정 (Parameters)](05_시험_설정.md) | 제품 규격치(전압, 전류, 저항 범위) 및 레이저 마킹 도면 파일 연동 | |
|||
| 6 | [측정 데이터 조회 (Data View)](06_데이터_조회.md) | 생산 데이터베이스를 통한 이전 공정 이력 자동 조회 및 최종 결과 저장 원리 | |
|||
| 7 | [자동 시험 프로세스](07_시험_프로세스.md) | 자동 계측 시퀀스 기동, 마킹 수행 및 최종 합격 판정 흐름 | |
|||
| 8 | [로그 및 데이터 관리](08_로그_관리.md) | 시스템 로그 파일 확인 방법 및 장비 설정 파일 백업 방법 | |
|||
| 9 | [오류 대응 및 프로그램 종료](09_오류_대응.md) | 센서 통신 오류, DB 조회 에러, 마킹 불량 등 현장 장애 대응 및 안전한 프로그램 종료 방법 | |
|||
|
|||
--- |
|||
|
|||
## 빠른 시작 가이드 (Quick Start) |
|||
|
|||
처음 시스템을 가동하여 검사를 진행하는 경우 다음 순서에 따라 작업을 수행해 주십시오. |
|||
|
|||
1. **프로그램 설치 (최초 1회)** |
|||
- 배포받은 단일 설치 프로그램 `MarkingSetup.exe`를 실행하여 클릭 한 번으로 `C:\marking` 경로 및 바탕화면 바로가기를 자동 생성합니다. |
|||
2. **하드웨어 연결 상태 확인** |
|||
- 계측 장비들과 제어용 PC 간의 네트워크(LAN)선 및 센서 리더용 시리얼 포트 케이블 연결을 확인합니다. |
|||
3. **프로그램 실행 및 로그인** |
|||
- 바탕화면의 `Marking System` (`marking_gui`) 프로그램을 실행한 뒤, 작업자 계정 정보를 입력하여 로그인합니다. (데이터베이스 점검 중인 경우 설정 파일을 통해 오프라인 모드로의 진입이 가능합니다.) |
|||
3. **통신 상태 확인 및 채널 설정** |
|||
- 우측 상단의 `통신 설정` 메뉴에서 센서가 올바른 포트와 채널에 연결되었는지 확인합니다. |
|||
4. **검사 규격값 검증** |
|||
- 우측 상단의 `시험 설정` 메뉴를 열고, 전압/전류/저항 검사 기준치와 각인 템플릿 도면 파일의 경로가 올바른지 점검합니다. |
|||
5. **성능 검사 및 마킹 시작** |
|||
- 안착 지그에 제품을 바르게 장착한 뒤 메인 화면 하단의 `검사 시작 (START)` 버튼을 눌러 계측 및 마킹을 수행합니다. |
|||
|
|||
--- |
|||
|
|||
*본 문서는 Performance Inspect & Laser Marking System v1.0.0 기준으로 작성되었습니다.* |
|||
|
After Width: | Height: | Size: 208 KiB |
@ -0,0 +1,70 @@ |
|||
using System; |
|||
|
|||
namespace marking_gui.Models |
|||
{ |
|||
public class MarkingRequest |
|||
{ |
|||
/// <summary>
|
|||
/// 제품 일련번호 (SERIAL 태그용)
|
|||
/// </summary>
|
|||
public string Serial { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 센서 IC S/N
|
|||
/// </summary>
|
|||
public string IcSerial { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// LOT 번호 (YYMMDD 태그용)
|
|||
/// </summary>
|
|||
public string LotNo { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 제품 고유 번호 (PRODUCT 태그용, 예: 35981-M5000)
|
|||
/// </summary>
|
|||
public string ProductNo { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 전체 QR 코드 문자열 (QRCODETAG 태그용)
|
|||
/// </summary>
|
|||
public string QrString { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 생산 라인 코드 (LCODE 태그용)
|
|||
/// </summary>
|
|||
public string LineCode { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 근무조 정보 (BAN 태그용)
|
|||
/// </summary>
|
|||
public string ShiftCode { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 도면 품번 (DRAWING_NO 태그용)
|
|||
/// </summary>
|
|||
public string DrawingNo { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// HKMC 품번 (HKMC_NO 태그용)
|
|||
/// </summary>
|
|||
public string HkmcNo { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 마킹에 사용할 EZD 도안 파일명 (예: AIC1.ezd)
|
|||
/// </summary>
|
|||
public string EzdFileName { get; set; } |
|||
|
|||
public MarkingRequest() |
|||
{ |
|||
Serial = string.Empty; |
|||
LotNo = string.Empty; |
|||
ProductNo = string.Empty; |
|||
QrString = string.Empty; |
|||
LineCode = string.Empty; |
|||
ShiftCode = string.Empty; |
|||
DrawingNo = string.Empty; |
|||
HkmcNo = string.Empty; |
|||
EzdFileName = string.Empty; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System; |
|||
|
|||
namespace marking_gui.Models |
|||
{ |
|||
public class MarkingResult |
|||
{ |
|||
/// <summary>
|
|||
/// 마킹 작업의 성공 여부
|
|||
/// </summary>
|
|||
public bool Success { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 에러 코드 (0 이면 성공, 그 외에는 각 에러 상태 코드)
|
|||
/// </summary>
|
|||
public int ErrorCode { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 에러 또는 상세 결과 메시지
|
|||
/// </summary>
|
|||
public string ErrorMessage { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 마킹이 실제 실행 및 완료된 시간
|
|||
/// </summary>
|
|||
public DateTime MarkedAt { get; set; } |
|||
|
|||
public MarkingResult() |
|||
{ |
|||
Success = false; |
|||
ErrorCode = -1; |
|||
ErrorMessage = "Uninitialized"; |
|||
MarkedAt = DateTime.MinValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
<Window x:Class="marking_gui.PortSettingsWindow" |
|||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
Title="포트 설정" Height="280" Width="380" |
|||
WindowStartupLocation="CenterOwner" ResizeMode="NoResize" |
|||
Background="#F3F4F6" ShowInTaskbar="False"> |
|||
<Window.Resources> |
|||
<!-- 버튼 스타일 --> |
|||
<Style x:Key="DialogButtonStyle" TargetType="Button"> |
|||
<Setter Property="Background" Value="#3B82F6"/> |
|||
<Setter Property="Foreground" Value="White"/> |
|||
<Setter Property="FontSize" Value="13"/> |
|||
<Setter Property="FontWeight" Value="Bold"/> |
|||
<Setter Property="BorderThickness" Value="0"/> |
|||
<Setter Property="Padding" Value="15,6"/> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="Button"> |
|||
<Border Background="{TemplateBinding Background}" CornerRadius="4"> |
|||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
<Style.Triggers> |
|||
<Trigger Property="IsMouseOver" Value="True"> |
|||
<Setter Property="Background" Value="#2563EB"/> |
|||
</Trigger> |
|||
</Style.Triggers> |
|||
</Style> |
|||
<Style x:Key="CancelButtonStyle" TargetType="Button" BasedOn="{StaticResource DialogButtonStyle}"> |
|||
<Setter Property="Background" Value="#9CA3AF"/> |
|||
<Style.Triggers> |
|||
<Trigger Property="IsMouseOver" Value="True"> |
|||
<Setter Property="Background" Value="#4B5563"/> |
|||
</Trigger> |
|||
</Style.Triggers> |
|||
</Style> |
|||
</Window.Resources> |
|||
|
|||
<Grid Margin="20"> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="*"/> |
|||
<RowDefinition Height="Auto"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<TextBlock Text="🔌 4251 센서 통신 포트 설정" FontSize="16" FontWeight="Bold" Foreground="#1F2937" Margin="0,0,0,15"/> |
|||
|
|||
<Grid Grid.Row="1"> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="10"/> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="10"/> |
|||
<RowDefinition Height="Auto"/> |
|||
</Grid.RowDefinitions> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto"/> |
|||
<ColumnDefinition Width="12"/> |
|||
<ColumnDefinition Width="*"/> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<!-- 포트 선택 --> |
|||
<TextBlock Grid.Row="0" Grid.Column="0" Text="통신 포트 (Port):" FontSize="14" VerticalAlignment="Center" Foreground="#4B5563" FontWeight="SemiBold"/> |
|||
<ComboBox x:Name="cbPort" Grid.Row="0" Grid.Column="2" FontSize="14" Padding="4" VerticalContentAlignment="Center"/> |
|||
|
|||
<!-- BaudRate 선택 --> |
|||
<TextBlock Grid.Row="2" Grid.Column="0" Text="통신 속도 (Baud):" FontSize="14" VerticalAlignment="Center" Foreground="#4B5563" FontWeight="SemiBold"/> |
|||
<ComboBox x:Name="cbBaudRate" Grid.Row="2" Grid.Column="2" FontSize="14" Padding="4" VerticalContentAlignment="Center"/> |
|||
|
|||
<!-- 채널 선택 --> |
|||
<TextBlock Grid.Row="4" Grid.Column="0" Text="통신 채널 (Channel):" FontSize="14" VerticalAlignment="Center" Foreground="#4B5563" FontWeight="SemiBold"/> |
|||
<ComboBox x:Name="cbChannel" Grid.Row="4" Grid.Column="2" FontSize="14" Padding="4" VerticalContentAlignment="Center"/> |
|||
</Grid> |
|||
|
|||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,15,0,0"> |
|||
<Button x:Name="btnSave" Content="저장" Style="{StaticResource DialogButtonStyle}" Width="70" Height="32" Click="btnSave_Click" Margin="0,0,10,0"/> |
|||
<Button x:Name="btnCancel" Content="취소" Style="{StaticResource CancelButtonStyle}" Width="70" Height="32" Click="btnCancel_Click"/> |
|||
</StackPanel> |
|||
</Grid> |
|||
</Window> |
|||
@ -0,0 +1,156 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.IO.Ports; |
|||
using System.Windows; |
|||
|
|||
namespace marking_gui |
|||
{ |
|||
/// <summary>
|
|||
/// PortSettingsWindow.xaml에 대한 상호 작용 논리
|
|||
/// </summary>
|
|||
public partial class PortSettingsWindow : Window |
|||
{ |
|||
private string _iniPath; |
|||
|
|||
public PortSettingsWindow() |
|||
{ |
|||
InitializeComponent(); |
|||
_iniPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sensor.ini"); |
|||
|
|||
Loaded += PortSettingsWindow_Loaded; |
|||
} |
|||
|
|||
private void PortSettingsWindow_Loaded(object sender, RoutedEventArgs e) |
|||
{ |
|||
// 1. 시스템에 유효한 COM 포트 목록 조회
|
|||
string[] ports = SerialPort.GetPortNames(); |
|||
cbPort.Items.Clear(); |
|||
foreach (var port in ports) |
|||
{ |
|||
cbPort.Items.Add(port); |
|||
} |
|||
|
|||
// 2. BaudRate 목록 추가
|
|||
cbBaudRate.Items.Clear(); |
|||
cbBaudRate.Items.Add("9600"); |
|||
cbBaudRate.Items.Add("19200"); |
|||
cbBaudRate.Items.Add("38400"); |
|||
cbBaudRate.Items.Add("57600"); |
|||
cbBaudRate.Items.Add("115200"); |
|||
|
|||
// 2-2. 채널 목록 추가 (1~4 채널)
|
|||
cbChannel.Items.Clear(); |
|||
cbChannel.Items.Add("1"); |
|||
cbChannel.Items.Add("2"); |
|||
|
|||
// 3. Sensor.ini 에서 현재 설정 로드
|
|||
string currentPort = "COM3"; |
|||
string currentBaud = "115200"; |
|||
string currentChannel = "1"; |
|||
|
|||
if (File.Exists(_iniPath)) |
|||
{ |
|||
try |
|||
{ |
|||
var lines = File.ReadAllLines(_iniPath); |
|||
foreach (var line in lines) |
|||
{ |
|||
var trimmed = line.Trim(); |
|||
if (trimmed.StartsWith("Port", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) currentPort = parts[1].Trim(); |
|||
} |
|||
else if (trimmed.StartsWith("BaudRate", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) currentBaud = parts[1].Trim(); |
|||
} |
|||
else if (trimmed.StartsWith("Channel", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) currentChannel = parts[1].Trim(); |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[PortSettings] 설정 로딩 중 오류: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
// 4. 조회한 포트 목록에 현재 설정된 포트가 없으면 임시 추가
|
|||
if (!cbPort.Items.Contains(currentPort)) |
|||
{ |
|||
cbPort.Items.Add(currentPort); |
|||
} |
|||
|
|||
// 5. 선택 상태 반영
|
|||
cbPort.SelectedItem = currentPort; |
|||
if (cbBaudRate.Items.Contains(currentBaud)) |
|||
{ |
|||
cbBaudRate.SelectedItem = currentBaud; |
|||
} |
|||
else |
|||
{ |
|||
cbBaudRate.SelectedItem = "115200"; |
|||
} |
|||
|
|||
if (cbChannel.Items.Contains(currentChannel)) |
|||
{ |
|||
cbChannel.SelectedItem = currentChannel; |
|||
} |
|||
else |
|||
{ |
|||
cbChannel.SelectedItem = "1"; |
|||
} |
|||
} |
|||
|
|||
private void btnSave_Click(object sender, RoutedEventArgs e) |
|||
{ |
|||
if (cbPort.SelectedItem == null || cbBaudRate.SelectedItem == null || cbChannel.SelectedItem == null) |
|||
{ |
|||
MessageBox.Show("포트, 통신 속도 및 채널을 선택해 주십시오.", "알림", MessageBoxButton.OK, MessageBoxImage.Warning); |
|||
return; |
|||
} |
|||
|
|||
string port = cbPort.SelectedItem.ToString(); |
|||
string baud = cbBaudRate.SelectedItem.ToString(); |
|||
string channel = cbChannel.SelectedItem.ToString(); |
|||
|
|||
try |
|||
{ |
|||
// Sensor.ini 에 저장
|
|||
using (var sw = new StreamWriter(_iniPath, false)) |
|||
{ |
|||
sw.WriteLine("; ================================================================="); |
|||
sw.WriteLine("; 성능 검사 모니터링 시스템 - 4251 센서 하드웨어 통신 설정"); |
|||
sw.WriteLine("; ================================================================="); |
|||
sw.WriteLine(); |
|||
sw.WriteLine("[Sensor]"); |
|||
sw.WriteLine("; 연결할 장치 센서 시리얼(COM) 포트명"); |
|||
sw.WriteLine("Port=" + port); |
|||
sw.WriteLine(); |
|||
sw.WriteLine("; 시리얼 통신 속도 (Baud Rate, 기본값: 115200)"); |
|||
sw.WriteLine("BaudRate=" + baud); |
|||
sw.WriteLine(); |
|||
sw.WriteLine("; 4251 센서 통신 채널 (기본값: 1, 범위: 1~4)"); |
|||
sw.WriteLine("Channel=" + channel); |
|||
} |
|||
|
|||
DialogResult = true; |
|||
Close(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
MessageBox.Show("설정을 저장하는 중 오류가 발생했습니다: " + ex.Message, "저장 실패", MessageBoxButton.OK, MessageBoxImage.Error); |
|||
} |
|||
} |
|||
|
|||
private void btnCancel_Click(object sender, RoutedEventArgs e) |
|||
{ |
|||
DialogResult = false; |
|||
Close(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. --> |
|||
<Project> |
|||
<PropertyGroup> |
|||
<Configuration>Release</Configuration> |
|||
<Platform>Any CPU</Platform> |
|||
<PublishDir>C:\Users\COMPUTER1\Downloads</PublishDir> |
|||
<PublishProtocol>FileSystem</PublishProtocol> |
|||
<_TargetId>Folder</_TargetId> |
|||
<TargetFramework>net9.0-windows</TargetFramework> |
|||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> |
|||
<SelfContained>true</SelfContained> |
|||
<PublishReadyToRun>false</PublishReadyToRun> |
|||
</PropertyGroup> |
|||
</Project> |
|||
@ -0,0 +1,389 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
/// <summary>
|
|||
/// 제품 ID 센서에서 읽은 제품 ID 정보.
|
|||
/// </summary>
|
|||
public class SensorIdData |
|||
{ |
|||
public int Year { get; set; } |
|||
public int Month { get; set; } |
|||
public int Day { get; set; } |
|||
public string Serial { get; set; } = ""; |
|||
public string McLine { get; set; } = ""; |
|||
public string LineNo { get; set; } = ""; |
|||
public string Item { get; set; } = ""; |
|||
public string ID { get; set; } = ""; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 제품 ID 센서 서비스의 추상 인터페이스.
|
|||
/// </summary>
|
|||
public interface IIdSensorService : IDisposable |
|||
{ |
|||
event EventHandler<string> ProgressMessage; |
|||
event EventHandler<string> ErrorMessage; |
|||
event EventHandler<bool> ConnectionChanged; |
|||
|
|||
bool Connect(); |
|||
void Disconnect(); |
|||
Task<SensorIdData> ReadSensorAsync(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 신규 4251 보드와의 통신을 관리하는 서비스.
|
|||
/// </summary>
|
|||
public class Board4251Service : IDisposable |
|||
{ |
|||
private readonly ICommunication _communication; |
|||
private readonly StringBuilder _receiveBuffer = new StringBuilder(); |
|||
private readonly object _bufferLock = new object(); |
|||
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1); |
|||
private TaskCompletionSource<string> _currentTcs; |
|||
public int TimeoutMs { get; set; } = 5000; |
|||
private bool _shouldBeConnected = false; |
|||
private System.Timers.Timer _reconnectTimer; |
|||
|
|||
public event EventHandler<string> ErrorOccurred; |
|||
public event EventHandler<bool> ConnectionChanged; |
|||
|
|||
public string LastResponse { get; private set; } = ""; |
|||
|
|||
public string GetLastBuffer() |
|||
{ |
|||
string currentBuf; |
|||
lock (_bufferLock) |
|||
{ |
|||
currentBuf = _receiveBuffer.ToString().Trim(); |
|||
} |
|||
return string.IsNullOrEmpty(currentBuf) ? LastResponse : currentBuf; |
|||
} |
|||
|
|||
public Board4251Service(ICommunication communication) |
|||
{ |
|||
_communication = communication; |
|||
_communication.DataReceived += OnDataReceived; |
|||
_communication.ConnectionStatusChanged += (s, isConnected) => { |
|||
ConnectionChanged?.Invoke(this, isConnected); |
|||
if (!isConnected && _shouldBeConnected) StartReconnectTimer(); |
|||
}; |
|||
|
|||
_reconnectTimer = new System.Timers.Timer(1000); |
|||
_reconnectTimer.AutoReset = false; |
|||
_reconnectTimer.Elapsed += (s, e) => { |
|||
if (_shouldBeConnected && !_communication.IsOpen) |
|||
{ |
|||
if (!_communication.Open()) |
|||
{ |
|||
if (_shouldBeConnected) _reconnectTimer.Start(); |
|||
} |
|||
} |
|||
else if (_shouldBeConnected) |
|||
{ |
|||
_reconnectTimer.Start(); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
private void StartReconnectTimer() |
|||
{ |
|||
if (_reconnectTimer != null && !_reconnectTimer.Enabled) _reconnectTimer.Start(); |
|||
} |
|||
|
|||
public bool Connect() |
|||
{ |
|||
_shouldBeConnected = true; |
|||
bool opened = _communication.Open(); |
|||
if (!opened) StartReconnectTimer(); |
|||
return opened; |
|||
} |
|||
|
|||
public void Disconnect() |
|||
{ |
|||
_shouldBeConnected = false; |
|||
_reconnectTimer?.Stop(); |
|||
_communication.Close(); |
|||
} |
|||
|
|||
public async Task<bool> CheckStatusAsync(int channel = 1) |
|||
{ |
|||
string response = await SendCommandAsync($"x00c_00{channel}101:owt28006727ea97c7801\r\n"); |
|||
if (response == null) return false; |
|||
if (response.IndexOf("Success", StringComparison.OrdinalIgnoreCase) >= 0) return true; |
|||
if (response.IndexOf("Fail", StringComparison.OrdinalIgnoreCase) >= 0) return false; |
|||
return false; |
|||
} |
|||
|
|||
public async Task<string> ReadIdAsync(int channel = 1) |
|||
{ |
|||
string response = await SendCommandAsync($"x00c_00{channel}101:ow2800326003e\r\n"); |
|||
if (response == null) return null; |
|||
|
|||
// 16자리 16진수 또는 ID 형태 파싱 추출
|
|||
// 보드 응답 예: "x00c_001101:ow2800326003e:Success:1234567890ABCDEF" 형태
|
|||
// 혹은 단순히 "1234567890ABCDEF" 형태의 데이터가 수신됨
|
|||
try |
|||
{ |
|||
string[] parts = response.Split(':'); |
|||
if (parts.Length >= 4) |
|||
{ |
|||
return parts[parts.Length - 1].Trim(); |
|||
} |
|||
return response.Trim(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[Board4251] ReadIdAsync 파싱 예외: " + ex.Message); |
|||
return response.Trim(); |
|||
} |
|||
} |
|||
|
|||
private string _activeCommand = null; |
|||
|
|||
public async Task<string> SendCommandAsync(string command) |
|||
{ |
|||
await _lock.WaitAsync(); |
|||
try |
|||
{ |
|||
lock (_bufferLock) |
|||
{ |
|||
_receiveBuffer.Clear(); |
|||
} |
|||
var tcs = new TaskCompletionSource<string>(); |
|||
_currentTcs = tcs; |
|||
_activeCommand = command; |
|||
|
|||
_communication.ClearBuffer(); |
|||
if (!_communication.Write(command)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
using (var cts = new CancellationTokenSource(TimeoutMs)) |
|||
{ |
|||
// 타임아웃 발생 시 TCS 취소 상태 전달
|
|||
cts.Token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false); |
|||
|
|||
try |
|||
{ |
|||
string response = await tcs.Task; |
|||
if (response != null) |
|||
{ |
|||
response = response.Replace("<end>", "").Trim(); |
|||
} |
|||
return response; |
|||
} |
|||
catch (TaskCanceledException) |
|||
{ |
|||
LoggerService.Warn($"[Board4251] 명령 전송 타임아웃 ({TimeoutMs}ms): {command.Trim()}"); |
|||
lock (_bufferLock) |
|||
{ |
|||
LastResponse = _receiveBuffer.ToString().Trim(); |
|||
} |
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
ErrorOccurred?.Invoke(this, "명령 전송 예외: " + ex.Message); |
|||
return null; |
|||
} |
|||
finally |
|||
{ |
|||
_currentTcs = null; |
|||
_activeCommand = null; |
|||
_lock.Release(); |
|||
} |
|||
} |
|||
|
|||
private void OnDataReceived(object sender, string data) |
|||
{ |
|||
if (string.IsNullOrEmpty(data)) return; |
|||
|
|||
string currentData; |
|||
lock (_bufferLock) |
|||
{ |
|||
_receiveBuffer.Append(data); |
|||
currentData = _receiveBuffer.ToString(); |
|||
} |
|||
|
|||
var targetTcs = _currentTcs; |
|||
if (targetTcs == null || targetTcs.Task.IsCompleted) return; |
|||
|
|||
// <end> 기반 완료 확인 (시스템상 종단 확인 메커니즘 우선 적용)
|
|||
if (_activeCommand != null && _activeCommand.Contains("x00c_")) |
|||
{ |
|||
if (currentData.Contains("<end>")) |
|||
{ |
|||
targetTcs.TrySetResult(currentData.Trim()); |
|||
} |
|||
return; |
|||
} |
|||
|
|||
// <end>가 명시되지 않는 기타 일반 패킷은 개행(\n) 또는 Success/Fail 기반으로 완료 판정
|
|||
if (currentData.Contains("<end>") || currentData.Contains("\n") || currentData.Contains("Success") || currentData.Contains("Fail")) |
|||
{ |
|||
targetTcs.TrySetResult(currentData.Trim()); |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
Disconnect(); |
|||
_reconnectTimer?.Dispose(); |
|||
_lock.Dispose(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 신규 4251 보드를 사용하여 제품 ID를 읽는 센서 서비스.
|
|||
/// </summary>
|
|||
public class Board4251SensorService : IIdSensorService |
|||
{ |
|||
private readonly Board4251Service _service; |
|||
private readonly int _sensorIndex; |
|||
private readonly EventHandler<bool> _connectionChangedHandler; |
|||
|
|||
public event EventHandler<string> ProgressMessage; |
|||
public event EventHandler<string> ErrorMessage; |
|||
public event EventHandler<bool> ConnectionChanged; |
|||
|
|||
public Board4251SensorService(Board4251Service service, int sensorIndex) |
|||
{ |
|||
_service = service; |
|||
_sensorIndex = sensorIndex; |
|||
_connectionChangedHandler = (s, isConnected) => ConnectionChanged?.Invoke(this, isConnected); |
|||
_service.ConnectionChanged += _connectionChangedHandler; |
|||
} |
|||
|
|||
public bool Connect() => _service.Connect(); |
|||
public void Disconnect() => _service.Disconnect(); |
|||
|
|||
public async Task<SensorIdData> ReadSensorAsync() |
|||
{ |
|||
try |
|||
{ |
|||
int channel = _sensorIndex + 1; |
|||
ProgressMessage?.Invoke(this, "4251 보드 초기화 중..."); |
|||
_ = _service.SendCommandAsync("x00o\r\n"); |
|||
await Task.Delay(350); |
|||
|
|||
ProgressMessage?.Invoke(this, "4251 보드 데이터 읽는 중..."); |
|||
int extendedTimeout = 15000; |
|||
string statusCmd = $"x00c_00{channel}101:owt28006727ea97c7801"; |
|||
bool statusResult = false; |
|||
|
|||
using (var cts = new CancellationTokenSource(extendedTimeout)) |
|||
{ |
|||
var statusTask = _service.CheckStatusAsync(channel); |
|||
var delayTask = Task.Delay(extendedTimeout, cts.Token); |
|||
var completedTask = await Task.WhenAny(statusTask, delayTask); |
|||
if (completedTask == delayTask) |
|||
{ |
|||
string buf = _service.GetLastBuffer(); |
|||
ErrorMessage?.Invoke(this, $"CH{channel} 상태 타임아웃\r\n송신: {statusCmd}\r\n수신: {buf}"); |
|||
return null; |
|||
} |
|||
cts.Cancel(); |
|||
statusResult = await statusTask; |
|||
} |
|||
|
|||
if (!statusResult) |
|||
{ |
|||
string buf = _service.GetLastBuffer(); |
|||
ErrorMessage?.Invoke(this, $"CH{channel} 상태 실패\r\n송신: {statusCmd}\r\n수신: {buf}"); |
|||
return null; |
|||
} |
|||
|
|||
// ID 읽기 (최대 3회 시도)
|
|||
string idCmd = $"x00c_00{channel}101:ow2800326003e"; |
|||
string rawId = null; |
|||
int maxAttempts = 3; |
|||
|
|||
for (int attempt = 1; attempt <= maxAttempts; attempt++) |
|||
{ |
|||
using (var cts = new CancellationTokenSource(extendedTimeout)) |
|||
{ |
|||
var idTask = _service.ReadIdAsync(channel); |
|||
var delayTask = Task.Delay(extendedTimeout, cts.Token); |
|||
var completedTask = await Task.WhenAny(idTask, delayTask); |
|||
if (completedTask == delayTask) |
|||
{ |
|||
if (attempt == maxAttempts) |
|||
{ |
|||
string buf = _service.GetLastBuffer(); |
|||
ErrorMessage?.Invoke(this, $"CH{channel} ID 타임아웃\r\n송신: {idCmd}\r\n수신: {buf}"); |
|||
return null; |
|||
} |
|||
continue; |
|||
} |
|||
cts.Cancel(); |
|||
rawId = await idTask; |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(rawId)) |
|||
{ |
|||
if (attempt == maxAttempts) |
|||
{ |
|||
string buf = _service.GetLastBuffer(); |
|||
ErrorMessage?.Invoke(this, $"CH{channel} ID 응답 없음\r\n송신: {idCmd}\r\n수신: {buf}"); |
|||
return null; |
|||
} |
|||
continue; |
|||
} |
|||
|
|||
if (rawId.EndsWith("F", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
if (attempt < maxAttempts) |
|||
{ |
|||
ProgressMessage?.Invoke(this, $"ID 읽기 재시도 중... ({attempt}/{maxAttempts})"); |
|||
await Task.Delay(350); |
|||
continue; |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
|
|||
// Step 7: 보드 OFF/후처리 (x00o)
|
|||
ProgressMessage?.Invoke(this, "4251 보드 OFF/후처리 중..."); |
|||
await _service.SendCommandAsync("x00o\r\n"); |
|||
await Task.Delay(350); |
|||
|
|||
// Step 8: 보드 CAL 기본값 (x00c_00{channel}001:owt28006727ea97c7801)
|
|||
ProgressMessage?.Invoke(this, "4251 보드 CAL 기본값 설정 중..."); |
|||
string calCmd = $"x00c_00{channel}001:owt28006727ea97c7801\r\n"; |
|||
await _service.SendCommandAsync(calCmd); |
|||
await Task.Delay(350); |
|||
|
|||
var data = new SensorIdData |
|||
{ |
|||
ID = rawId, |
|||
Serial = "", |
|||
Item = "N/A" |
|||
}; |
|||
|
|||
ProgressMessage?.Invoke(this, "ID 읽기 성공: " + rawId); |
|||
return data; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
ErrorMessage?.Invoke(this, $"4251 읽기 예외: {ex.Message}"); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
if (_service != null && _connectionChangedHandler != null) |
|||
{ |
|||
_service.ConnectionChanged -= _connectionChangedHandler; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
using System; |
|||
using System.IO.Ports; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
/// <summary>
|
|||
/// 하드웨어 통신을 위한 추상화 인터페이스.
|
|||
/// 시리얼(RS232), 이더넷(TCP/IP) 등 통신 방식에 상관없이
|
|||
/// 상위 서비스에서 동일한 방식으로 하드웨어에 접근할 수 있도록 정의함.
|
|||
/// </summary>
|
|||
public interface ICommunication |
|||
{ |
|||
/// <summary> 통신 채널 식별 이름 (예: COM1, TCP_192.168.0.1) </summary>
|
|||
string Name { get; } |
|||
|
|||
/// <summary> 현재 통신 채널이 열려 있는지 여부 </summary>
|
|||
bool IsOpen { get; } |
|||
|
|||
/// <summary> 통신 채널을 연결함 </summary>
|
|||
bool Open(); |
|||
|
|||
/// <summary> 통신 채널 연결을 해제함 </summary>
|
|||
void Close(); |
|||
|
|||
/// <summary> 데이터를 하드웨어로 전송함 </summary>
|
|||
bool Write(string data); |
|||
|
|||
/// <summary> 수신 버퍼를 비워 잔류 데이터를 제거함 </summary>
|
|||
void ClearBuffer(); |
|||
|
|||
/// <summary> 하드웨어로부터 데이터를 수신했을 때 발생하는 이벤트 </summary>
|
|||
event System.EventHandler<string> DataReceived; |
|||
|
|||
/// <summary> 연결 상태가 변경되었을 때 발생하는 이벤트 (connected, disconnected) </summary>
|
|||
event System.EventHandler<bool> ConnectionStatusChanged; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// RS232 시리얼 통신을 담당하는 구현체.
|
|||
/// 연결 안정성 강화를 위한 예외 처리 및 상태 감지 로직 포함.
|
|||
/// </summary>
|
|||
public class SerialProvider : ICommunication, IDisposable |
|||
{ |
|||
private SerialPort _serialPort; |
|||
private bool _disposed = false; |
|||
|
|||
public string Name { get; private set; } |
|||
public bool IsOpen => _serialPort != null && !_disposed && _serialPort.IsOpen; |
|||
|
|||
public event EventHandler<string> DataReceived; |
|||
public event EventHandler<bool> ConnectionStatusChanged; |
|||
|
|||
public SerialProvider(string portName, int baudRate) |
|||
{ |
|||
Name = portName; |
|||
_serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One); |
|||
_serialPort.Handshake = Handshake.None; |
|||
_serialPort.DtrEnable = true; // 터미널 프로그램(포트몬)과 동일하게 제어 신호 활성화
|
|||
_serialPort.RtsEnable = true; |
|||
_serialPort.ReadTimeout = 500; |
|||
_serialPort.WriteTimeout = 500; |
|||
|
|||
_serialPort.DataReceived += (s, e) => { |
|||
try { |
|||
string data = _serialPort.ReadExisting(); |
|||
if (!string.IsNullOrEmpty(data)) |
|||
DataReceived?.Invoke(this, data); |
|||
} catch (Exception ex) { |
|||
Console.WriteLine($"[Serial Error] Read error on {Name}: {ex.Message}"); |
|||
} |
|||
}; |
|||
|
|||
// 기기가 끊겼을 때 감지 (일부 환경에서는 PinChanged 등으로 감지 가능)
|
|||
_serialPort.ErrorReceived += (s, e) => { |
|||
ConnectionStatusChanged?.Invoke(this, false); |
|||
}; |
|||
} |
|||
|
|||
public bool Open() |
|||
{ |
|||
if (_disposed) return false; |
|||
try { |
|||
if (IsOpen) return true; |
|||
_serialPort.Open(); |
|||
ConnectionStatusChanged?.Invoke(this, true); |
|||
return true; |
|||
} catch (Exception ex) { |
|||
Console.WriteLine($"[Serial Error] Failed to open {Name}: {ex.Message}"); |
|||
ConnectionStatusChanged?.Invoke(this, false); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public void Close() |
|||
{ |
|||
try { |
|||
if (IsOpen) { |
|||
_serialPort.Close(); |
|||
ConnectionStatusChanged?.Invoke(this, false); |
|||
} |
|||
} catch (Exception ex) { |
|||
Console.WriteLine($"[Serial Error] Error closing {Name}: {ex.Message}"); |
|||
} |
|||
} |
|||
|
|||
public bool Write(string data) |
|||
{ |
|||
if (!IsOpen) return false; |
|||
try { |
|||
_serialPort.Write(data); |
|||
return true; |
|||
} catch (Exception ex) { |
|||
Console.WriteLine($"[Serial Error] Write error on {Name}: {ex.Message}"); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public void ClearBuffer() |
|||
{ |
|||
if (IsOpen) { |
|||
try { |
|||
_serialPort.DiscardInBuffer(); |
|||
_serialPort.DiscardOutBuffer(); |
|||
_serialPort.ReadExisting(); |
|||
} catch (Exception ex) { |
|||
System.Diagnostics.Debug.WriteLine($"[CommunicationBase ClearBuffer Error] {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
if (!_disposed) |
|||
{ |
|||
_disposed = true; |
|||
Close(); |
|||
_serialPort?.Dispose(); |
|||
_serialPort = null; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,406 @@ |
|||
using System; |
|||
using System.Configuration; |
|||
using marking_gui.Models; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public class DatabaseService |
|||
{ |
|||
private readonly string _connectionString; |
|||
private readonly bool _offlineMode = false; |
|||
|
|||
public bool OfflineMode => _offlineMode; |
|||
|
|||
public DatabaseService() |
|||
{ |
|||
try |
|||
{ |
|||
string dbServer = string.Empty; |
|||
string dbName = string.Empty; |
|||
string dbUser = string.Empty; |
|||
string dbPassword = string.Empty; |
|||
string rawConnStr = string.Empty; |
|||
|
|||
// AppDomain.CurrentDomain.BaseDirectory 에서 Database.ini 로드 시도
|
|||
string iniPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Database.ini"); |
|||
if (System.IO.File.Exists(iniPath)) |
|||
{ |
|||
var lines = System.IO.File.ReadAllLines(iniPath); |
|||
foreach (var line in lines) |
|||
{ |
|||
var trimmed = line.Trim(); |
|||
if (trimmed.StartsWith(";") || trimmed.StartsWith("#")) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
if (trimmed.StartsWith("ConnectionString", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
rawConnStr = parts[1].Trim(); |
|||
} |
|||
} |
|||
else if (trimmed.StartsWith("Db_Server", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
dbServer = parts[1].Trim(); |
|||
} |
|||
} |
|||
else if (trimmed.StartsWith("Db_Name", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
dbName = parts[1].Trim(); |
|||
} |
|||
} |
|||
else if (trimmed.StartsWith("Db_User", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
dbUser = parts[1].Trim(); |
|||
} |
|||
} |
|||
else if (trimmed.StartsWith("Db_Password", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
dbPassword = parts[1].Trim(); |
|||
} |
|||
} |
|||
else if (trimmed.StartsWith("OfflineMode", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
bool.TryParse(parts[1].Trim(), out _offlineMode); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 개별 설정이 있는 경우 조합해서 사용
|
|||
if (!string.IsNullOrWhiteSpace(dbServer) && |
|||
!string.IsNullOrWhiteSpace(dbName) && |
|||
!string.IsNullOrWhiteSpace(dbUser) && |
|||
!string.IsNullOrWhiteSpace(dbPassword)) |
|||
{ |
|||
_connectionString = $"Server={dbServer};Database={dbName};User Id={dbUser};Password={dbPassword};"; |
|||
} |
|||
else |
|||
{ |
|||
_connectionString = rawConnStr; |
|||
} |
|||
|
|||
// Database.ini 에 없을 경우 App.config 백업 사용
|
|||
if (string.IsNullOrEmpty(_connectionString)) |
|||
{ |
|||
var connSettings = ConfigurationManager.ConnectionStrings["MssqlConnection"]; |
|||
if (connSettings != null) |
|||
{ |
|||
_connectionString = connSettings.ConnectionString; |
|||
} |
|||
else |
|||
{ |
|||
_connectionString = "Server=localhost;Database=MarkingDb;Trusted_Connection=True;"; |
|||
} |
|||
} |
|||
|
|||
// SSL 인증서 체인 신뢰성 오류(TrustServerCertificate=True 누락) 방지 조치 추가
|
|||
if (!string.IsNullOrWhiteSpace(_connectionString) && _connectionString.IndexOf("TrustServerCertificate", StringComparison.OrdinalIgnoreCase) < 0) |
|||
{ |
|||
if (!_connectionString.EndsWith(";")) _connectionString += ";"; |
|||
_connectionString += "TrustServerCertificate=True;"; |
|||
} |
|||
|
|||
// DB 서버 오프라인 시 지연 방지를 위해 연결 타임아웃(Connection Timeout)을 3초로 강제 조정
|
|||
if (!string.IsNullOrWhiteSpace(_connectionString) && |
|||
_connectionString.IndexOf("Connect Timeout", StringComparison.OrdinalIgnoreCase) < 0 && |
|||
_connectionString.IndexOf("Connection Timeout", StringComparison.OrdinalIgnoreCase) < 0) |
|||
{ |
|||
if (!_connectionString.EndsWith(";")) _connectionString += ";"; |
|||
_connectionString += "Connect Timeout=3;"; |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_connectionString = string.Empty; |
|||
System.Diagnostics.Debug.WriteLine("설정 로드 중 예외 발생: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
public bool CheckConnection() |
|||
{ |
|||
if (_offlineMode) |
|||
return true; |
|||
|
|||
if (string.IsNullOrWhiteSpace(_connectionString)) |
|||
return false; |
|||
|
|||
try |
|||
{ |
|||
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) |
|||
{ |
|||
conn.Open(); |
|||
return true; |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public Product GetProductBySerial(string serial) |
|||
{ |
|||
if (string.IsNullOrEmpty(serial)) |
|||
return null; |
|||
|
|||
string searchSerial = serial.Trim().ToUpper(); |
|||
|
|||
// 오프라인 모드인 경우 데이터베이스가 없으므로 항상 이전 공정 통과(PASS)로 가정하여 가상 데이터 반환
|
|||
if (_offlineMode) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[OfflineMode] 제품 조회 우회 (오프라인 모드 활성화). S/N: " + searchSerial); |
|||
return new Product(searchSerial, "PASS", "PASS", "PASS"); |
|||
} |
|||
|
|||
try |
|||
{ |
|||
// 이전 3개 공정 테이블(Housing_Assembly, Cal_EOL_Result, EOL)에서 IC_SN 기준으로 Result 각각 조회
|
|||
// Housing_Assembly 테이블에서 PCB_Barcode 가져옴
|
|||
string query = @"
|
|||
SELECT |
|||
(SELECT TOP 1 [Result] FROM [dbo].[Housing_Assembly] WHERE UPPER([IC_SN]) = @Serial) AS HousingResult, |
|||
(SELECT TOP 1 [Final_Result] FROM [dbo].[Cal_EOL_Result] WHERE UPPER([IC_SN]) = @Serial) AS CalResult, |
|||
(SELECT TOP 1 [Result] FROM [dbo].[EOL] WHERE UPPER([IC_SN]) = @Serial) AS EolResult, |
|||
(SELECT TOP 1 [PCB_Barcode] FROM [dbo].[Housing_Assembly] WHERE UPPER([IC_SN]) = @Serial) AS PcbBarcode";
|
|||
|
|||
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) |
|||
{ |
|||
using (var cmd = new System.Data.SqlClient.SqlCommand(query, conn)) |
|||
{ |
|||
cmd.CommandTimeout = 5; // DB 응답 대기 최대 5초
|
|||
cmd.Parameters.AddWithValue("@Serial", searchSerial); |
|||
conn.Open(); |
|||
|
|||
using (var reader = cmd.ExecuteReader()) |
|||
{ |
|||
if (reader.Read()) |
|||
{ |
|||
// 데이터베이스 값이 NULL 이거나 빈 값일 경우 "대기"로 처리
|
|||
string housingRes = reader["HousingResult"] != DBNull.Value ? reader["HousingResult"].ToString().Trim() : "대기"; |
|||
string calRes = reader["CalResult"] != DBNull.Value ? reader["CalResult"].ToString().Trim() : "대기"; |
|||
string eolRes = reader["EolResult"] != DBNull.Value ? reader["EolResult"].ToString().Trim() : "대기"; |
|||
string pcbBarcode = reader["PcbBarcode"] != DBNull.Value ? reader["PcbBarcode"].ToString().Trim() : string.Empty; |
|||
|
|||
// 세 공정 중 하나라도 데이터 흔적이 있는 경우 Product 객체 생성 반환
|
|||
if (housingRes != "대기" || calRes != "대기" || eolRes != "대기") |
|||
{ |
|||
return new Product(searchSerial, housingRes, calRes, eolRes) |
|||
{ |
|||
PcbBarcode = pcbBarcode |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[DB GetProduct] 이전 공정 결과 조회 중 에러: " + ex.Message); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 최종 성능 검출 값을 데이터베이스에 저장합니다.
|
|||
/// 전압과 전류 수치는 3,2 포맷(DECIMAL(3, 2) 등)에 대응하기 위해 소수점 이하 2자리로 반올림하여 처리합니다.
|
|||
/// </summary>
|
|||
public bool SaveProductResult( |
|||
string serial, |
|||
string maker, |
|||
string model, |
|||
string variant1, |
|||
string variant2, |
|||
string operatorId, |
|||
string line, |
|||
string lotNo, |
|||
string jigNo, |
|||
double voltage, |
|||
double current, |
|||
double resistance, |
|||
string result, |
|||
DateTime startTime, |
|||
DateTime endTime, |
|||
string markedSerial, |
|||
string pcbBarcode = null, |
|||
string drawingNo = "", |
|||
string hkmcNo = "") |
|||
{ |
|||
// 전압과 전류, 저항을 소수점 이하 2자리(3,2 포맷 규격)로 반올림 처리
|
|||
decimal roundedVoltage = Math.Round((decimal)voltage, 2); |
|||
decimal roundedCurrent = Math.Round((decimal)current, 2); |
|||
decimal roundedResistance = Math.Round((decimal)resistance, 3); |
|||
|
|||
// IC_SN 및 PCB_Barcode 컬럼 규격(NVARCHAR(30), NOT NULL) 방어 처리
|
|||
if (string.IsNullOrWhiteSpace(serial)) |
|||
{ |
|||
serial = "UNKNOWN_" + DateTime.Now.ToString("HHmmss"); |
|||
} |
|||
if (serial.Length > 30) |
|||
{ |
|||
serial = serial.Substring(0, 30); |
|||
} |
|||
// PCB_Barcode: Housing_Assembly 테이블에서 가져온 값 우선 사용, 없으면 IC_SN으로 대체
|
|||
string safePcbBarcode = !string.IsNullOrWhiteSpace(pcbBarcode) ? pcbBarcode : serial; |
|||
if (safePcbBarcode.Length > 30) safePcbBarcode = safePcbBarcode.Substring(0, 30); |
|||
string safeProcessLabel = "Marking"; |
|||
string safeProcessLabelScan = string.IsNullOrEmpty(result) ? "OK" : (result.Length > 5 ? result.Substring(0, 5) : result); |
|||
string safeResult = string.IsNullOrEmpty(result) ? "NG" : (result.Length > 5 ? result.Substring(0, 5) : result); |
|||
string safeErrorCode = (safeResult == "OK" || safeResult == "PASS") ? "0" : "E01"; |
|||
|
|||
// DB 컬럼 길이 한계에 맞춰서 문자열 안전하게 자르기 (Truncate)
|
|||
string safeMaker = string.IsNullOrEmpty(maker) ? "" : (maker.Length > 10 ? maker.Substring(0, 10) : maker); |
|||
string safeModel = string.IsNullOrEmpty(model) ? "" : (model.Length > 10 ? model.Substring(0, 10) : model); |
|||
string safeVariant1 = string.IsNullOrEmpty(variant1) ? "" : (variant1.Length > 10 ? variant1.Substring(0, 10) : variant1); |
|||
string safeVariant2 = string.IsNullOrEmpty(variant2) ? "" : (variant2.Length > 10 ? variant2.Substring(0, 10) : variant2); |
|||
string safeOperator = string.IsNullOrEmpty(operatorId) ? "" : (operatorId.Length > 10 ? operatorId.Substring(0, 10) : operatorId); |
|||
string safeLine = string.IsNullOrEmpty(line) ? "" : (line.Length > 10 ? line.Substring(0, 10) : line); |
|||
string safeLotNo = string.IsNullOrEmpty(lotNo) ? "" : (lotNo.Length > 10 ? lotNo.Substring(0, 10) : lotNo); |
|||
string safeJigNo = string.IsNullOrEmpty(jigNo) ? "" : (jigNo.Length > 10 ? jigNo.Substring(0, 10) : jigNo); |
|||
|
|||
DateTime prodDate = endTime; |
|||
// QR Code 조합 포맷 생성 ([IC S/N];[도면품번];[HKMC품번];[제품 S/N];) (Marking_QR: NVARCHAR(60))
|
|||
string markingQr = string.Format("{0};{1};{2};{3};", serial, drawingNo ?? "", hkmcNo ?? "", markedSerial); |
|||
if (markingQr.Length > 60) |
|||
{ |
|||
markingQr = markingQr.Substring(0, 60); |
|||
} |
|||
|
|||
// 오프라인 모드인 경우 실제 DB 저장을 생략하고 정상 통과 처리
|
|||
if (_offlineMode) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine(string.Format( |
|||
"[OfflineMode] DB 저장 생략 (오프라인 모드 활성화) S/N: {0} | 각인번호: {1} | QR: {2} | Maker: {3} | Model: {4} | Line: {5} | LotNo: {6} | Vol_1: {7:F2}V | Cur_1: {8:F2}mA | Res_1: {9:F3}kΩ | 결과: {10} | 시작:{11} | 종료:{12}", |
|||
serial, markedSerial, markingQr, safeMaker, safeModel, safeLine, safeLotNo, roundedVoltage, roundedCurrent, roundedResistance, result, |
|||
startTime.ToString("HH:mm:ss"), endTime.ToString("HH:mm:ss"))); |
|||
return true; |
|||
} |
|||
|
|||
// 실제 MSSQL DB 적재 실행 (동일 IC_SN 재검사 시 데이터가 덮어씌워지도록 MERGE 문 도입)
|
|||
try |
|||
{ |
|||
string query = @"MERGE INTO [dbo].[Marking] AS target
|
|||
USING (SELECT @Serial AS IC_SN) AS source |
|||
ON (target.[IC_SN] = source.IC_SN) |
|||
WHEN MATCHED THEN |
|||
UPDATE SET |
|||
[Maker] = @Maker, |
|||
[Model] = @Model, |
|||
[Variant_1] = @Var1, |
|||
[Variant_2] = @Var2, |
|||
[Operator] = @Operator, |
|||
[Production_Date] = @ProdDate, |
|||
[Line] = @Line, |
|||
[Lot_No] = @LotNo, |
|||
[JIG_No] = @JigNo, |
|||
[PCB_Barcode] = @PcbBarcode, |
|||
[Process_Label] = @ProcessLabel, |
|||
[Process_Label_Scan] = @ProcessLabelScan, |
|||
[PT_Vol_1] = @Vol1, |
|||
[PT_Current_1] = @Cur1, |
|||
[Marking_QR] = @Qr, |
|||
[Result] = @Result, |
|||
[Error_Code] = @ErrorCode |
|||
WHEN NOT MATCHED THEN |
|||
INSERT ([Maker], [Model], [Variant_1], [Variant_2], [Operator], [Production_Date], [Line], [Lot_No], [JIG_No], [IC_SN], [PCB_Barcode], [Process_Label], [Process_Label_Scan], [PT_Vol_1], [PT_Current_1], [Marking_QR], [Result], [Error_Code]) |
|||
VALUES (@Maker, @Model, @Var1, @Var2, @Operator, @ProdDate, @Line, @LotNo, @JigNo, @Serial, @PcbBarcode, @ProcessLabel, @ProcessLabelScan, @Vol1, @Cur1, @Qr, @Result, @ErrorCode);";
|
|||
|
|||
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) |
|||
{ |
|||
using (var cmd = new System.Data.SqlClient.SqlCommand(query, conn)) |
|||
{ |
|||
cmd.CommandTimeout = 5; // DB 응답 대기 최대 5초
|
|||
cmd.Parameters.AddWithValue("@Maker", safeMaker); |
|||
cmd.Parameters.AddWithValue("@Model", safeModel); |
|||
cmd.Parameters.AddWithValue("@Var1", safeVariant1); |
|||
cmd.Parameters.AddWithValue("@Var2", safeVariant2); |
|||
cmd.Parameters.AddWithValue("@Operator", safeOperator); |
|||
cmd.Parameters.AddWithValue("@ProdDate", prodDate); |
|||
cmd.Parameters.AddWithValue("@Line", safeLine); |
|||
cmd.Parameters.AddWithValue("@LotNo", safeLotNo); |
|||
cmd.Parameters.AddWithValue("@JigNo", safeJigNo); |
|||
cmd.Parameters.AddWithValue("@Serial", serial); |
|||
cmd.Parameters.AddWithValue("@PcbBarcode", safePcbBarcode); |
|||
cmd.Parameters.AddWithValue("@ProcessLabel", safeProcessLabel); |
|||
cmd.Parameters.AddWithValue("@ProcessLabelScan", safeProcessLabelScan); |
|||
|
|||
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Vol1", System.Data.SqlDbType.Decimal) { Precision = 5, Scale = 2, Value = roundedVoltage }); |
|||
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Cur1", System.Data.SqlDbType.Decimal) { Precision = 5, Scale = 2, Value = roundedCurrent }); |
|||
|
|||
cmd.Parameters.AddWithValue("@Qr", markingQr); |
|||
cmd.Parameters.AddWithValue("@Result", safeResult); |
|||
cmd.Parameters.AddWithValue("@ErrorCode", safeErrorCode); |
|||
|
|||
conn.Open(); |
|||
cmd.ExecuteNonQuery(); |
|||
} |
|||
} |
|||
|
|||
// 성공 로그 출력 및 true 반환
|
|||
System.Diagnostics.Debug.WriteLine(string.Format( |
|||
"[DB 저장 로그] S/N: {0} | 각인번호: {1} | QR: {2} | Maker: {3} | Model: {4} | Line: {5} | LotNo: {6} | Vol_1: {7:F2}V | Cur_1: {8:F2}mA | Res_1: {9:F3}kΩ | 결과: {10} | 시작:{11} | 종료:{12}", |
|||
serial, markedSerial, markingQr, safeMaker, safeModel, safeLine, safeLotNo, roundedVoltage, roundedCurrent, roundedResistance, result, |
|||
startTime.ToString("HH:mm:ss"), endTime.ToString("HH:mm:ss"))); |
|||
|
|||
return true; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[DB SaveResult] DB 저장 실패 (메시지: " + ex.Message + ")"); |
|||
throw; // 예외 원인을 상위로 전파하여 UI 상태창에 구체적인 오류 원인(ex.Message)이 그대로 노출되도록 함
|
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 지정한 LotNo로 기존에 저장 완료(PASS)된 제품들의 개수를 카운트하여 다음 각인 일련번호를 구합니다.
|
|||
/// </summary>
|
|||
public int GetNextMarkingSequence(string lotNo) |
|||
{ |
|||
if (_offlineMode) |
|||
{ |
|||
return 1; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
string query = "SELECT COUNT(*) FROM [dbo].[Marking] WHERE [Lot_No] = @LotNo AND ([Result] = 'PASS' OR [Result] = 'OK')"; |
|||
|
|||
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) |
|||
{ |
|||
using (var cmd = new System.Data.SqlClient.SqlCommand(query, conn)) |
|||
{ |
|||
cmd.CommandTimeout = 5; // DB 응답 대기 최대 5초
|
|||
cmd.Parameters.AddWithValue("@LotNo", lotNo); |
|||
conn.Open(); |
|||
int count = (int)cmd.ExecuteScalar(); |
|||
return count + 1; |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[DB GetNextMarkingSequence] 에러: " + ex.Message); |
|||
throw; // 예외를 상위로 전파하여 DB 장애 시 중복 순번 발급 방지
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,417 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.IO; |
|||
using System.Text; |
|||
using System.Text.RegularExpressions; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
/// <summary>
|
|||
/// DMM(전압+저항, .10) + DMM(전류, .11) + Power Supply(출력제어, .12) SCPI 계측기 연동 서비스.
|
|||
/// Setting.ini 의 [DMM] / [CurrentDMM] / [PowerSupply] 섹션에서 연결 설정을 읽습니다.
|
|||
/// </summary>
|
|||
public sealed class EquipmentMeasurementService : IDisposable |
|||
{ |
|||
// ── 설정 내부 데이터 클래스 ──────────────────────────────────────
|
|||
private sealed class ScpiChannelSettings |
|||
{ |
|||
public string Connection { get; set; } = string.Empty; |
|||
public string Host { get; set; } = string.Empty; |
|||
public int Port { get; set; } = 5025; |
|||
public string IdnMatch { get; set; } = string.Empty; |
|||
public string PortName { get; set; } = string.Empty; |
|||
public int BaudRate { get; set; } = 9600; |
|||
public string Terminator { get; set; } = "LF"; |
|||
public string SetupCommand { get; set; } = string.Empty; |
|||
public string CleanupCommand { get; set; } = string.Empty; |
|||
public string ReadCommand { get; set; } = string.Empty; |
|||
|
|||
public bool IsDisabled => |
|||
string.IsNullOrWhiteSpace(Connection) || |
|||
(Connection.ToUpperInvariant() is not ("LAN" or "TCP" or "ETHERNET" or "SERIAL" or "COM") && |
|||
string.IsNullOrWhiteSpace(Host)); |
|||
|
|||
public string[] GetIdnMatches() => |
|||
string.IsNullOrWhiteSpace(IdnMatch) |
|||
? Array.Empty<string>() |
|||
: IdnMatch.Split(',', StringSplitOptions.RemoveEmptyEntries); |
|||
|
|||
public char GetTerminator() => |
|||
Terminator.ToUpperInvariant() == "CR" ? '\r' : '\n'; |
|||
} |
|||
|
|||
// ── 필드 ────────────────────────────────────────────────────────
|
|||
private int _timeoutMs = 5000; |
|||
private int _settleMs = 300; |
|||
private string _preBoardCommand = string.Empty; |
|||
private int _preBoardDelayMs = 2000; |
|||
private string _logoutCommand = string.Empty; |
|||
private string _resistanceReadCommand = "MEAS:RES?"; |
|||
|
|||
private ScpiChannelSettings _voltageDmm; // 전압 측정 전용 DMM 계측기
|
|||
private ScpiChannelSettings _currentDmm; // 전류 측정 전용 DMM 계측기
|
|||
private ScpiChannelSettings _resistanceDmm; // 저항 측정 전용 DMM 계측기
|
|||
private ScpiChannelSettings _psu; // 출력 제어 Power Supply (전원 및 상시전원 인가)
|
|||
|
|||
private IScpiClient _voltageDmmClient; |
|||
private IScpiClient _currentDmmClient; |
|||
private IScpiClient _resistanceDmmClient; |
|||
private IScpiClient _psuClient; |
|||
|
|||
private bool _disposed; |
|||
|
|||
// ── 생성자 ──────────────────────────────────────────────────────
|
|||
public EquipmentMeasurementService(string iniPath) |
|||
{ |
|||
LoadSettings(iniPath); |
|||
} |
|||
|
|||
private IScpiClient GetPsuClient() |
|||
{ |
|||
if (_psuClient == null && !_psu.IsDisabled) |
|||
{ |
|||
_psuClient = CreateClient("PSU", _psu); |
|||
} |
|||
return _psuClient; |
|||
} |
|||
|
|||
private IScpiClient GetVoltageClient() |
|||
{ |
|||
if (_voltageDmmClient == null && !_voltageDmm.IsDisabled) |
|||
{ |
|||
_voltageDmmClient = CreateClient("VOLTAGE_DMM", _voltageDmm); |
|||
} |
|||
return _voltageDmmClient; |
|||
} |
|||
|
|||
private IScpiClient GetCurrentDmmClient() |
|||
{ |
|||
if (_currentDmmClient == null && !_currentDmm.IsDisabled) |
|||
{ |
|||
_currentDmmClient = CreateClient("CURRENT_DMM", _currentDmm); |
|||
} |
|||
return _currentDmmClient; |
|||
} |
|||
|
|||
private IScpiClient GetResistanceDmmClient() |
|||
{ |
|||
if (_resistanceDmmClient == null && !_resistanceDmm.IsDisabled) |
|||
{ |
|||
_resistanceDmmClient = CreateClient("RESISTANCE_DMM", _resistanceDmm); |
|||
} |
|||
// 저항 전용 DMM이 비활성화되어 있는 경우, 전압 DMM 클라이언트를 대체 사용
|
|||
return _resistanceDmmClient ?? GetVoltageClient(); |
|||
} |
|||
|
|||
// ── 설정 로드 ────────────────────────────────────────────────────
|
|||
private void LoadSettings(string iniPath) |
|||
{ |
|||
var values = ParseIni(iniPath); |
|||
|
|||
_timeoutMs = GetInt(values, "Timeout", 5000); |
|||
_settleMs = GetInt(values, "SettleMilliseconds", 300); |
|||
_preBoardCommand = GetString(values, "PreBoardCommand", string.Empty); |
|||
_preBoardDelayMs = GetInt(values, "PreBoardDelayMilliseconds", 2000); |
|||
_logoutCommand = GetString(values, "LogoutCommand", string.Empty); |
|||
_resistanceReadCommand = GetString(values, "ResistanceReadCommand", "MEAS:RES?"); |
|||
|
|||
_voltageDmm = LoadChannel(values, "Voltage", "MEAS:VOLT:DC?", "34460,34461,34465,34470"); |
|||
_currentDmm = LoadChannel(values, "CurrentDMM", "MEAS:CURR:DC?", "34460,34461,34465,34470"); |
|||
_resistanceDmm = LoadChannel(values, "ResistanceDMM", "MEAS:RES?", "34460,34461,34465,34470"); |
|||
_psu = LoadChannel(values, "Current", string.Empty, "E362"); |
|||
} |
|||
|
|||
private static ScpiChannelSettings LoadChannel( |
|||
Dictionary<string, string> values, |
|||
string prefix, |
|||
string defaultReadCommand, |
|||
string defaultIdnMatch) |
|||
{ |
|||
return new ScpiChannelSettings |
|||
{ |
|||
Connection = GetString(values, prefix + "Connection", string.Empty), |
|||
Host = GetString(values, prefix + "Host", string.Empty), |
|||
Port = GetInt(values, prefix + "Port", 5025), |
|||
IdnMatch = GetString(values, prefix + "IdnMatch", defaultIdnMatch), |
|||
PortName = GetString(values, prefix + "PortName", string.Empty), |
|||
BaudRate = GetInt(values, prefix + "BaudRate", 9600), |
|||
Terminator = GetString(values, prefix + "Terminator", "LF"), |
|||
SetupCommand = GetString(values, prefix + "SetupCommand", string.Empty), |
|||
CleanupCommand = GetString(values, prefix + "CleanupCommand", string.Empty), |
|||
ReadCommand = GetString(values, prefix + "ReadCommand", defaultReadCommand), |
|||
}; |
|||
} |
|||
|
|||
// ── Public API ───────────────────────────────────────────────────
|
|||
|
|||
/// <summary>
|
|||
/// 전압 DMM + 저항 DMM + 전류 DMM(또는 PSU) 독립 계측기 3-장비 측정 시퀀스.
|
|||
/// </summary>
|
|||
public async Task<(double Voltage, double Current, double Resistance)> MeasureAsync(Action<double?, double?, double?> onUpdate = null) |
|||
{ |
|||
var log = new StringBuilder(); |
|||
IScpiClient psuClient = GetPsuClient(); |
|||
IScpiClient voltageClient = GetVoltageClient(); |
|||
IScpiClient resistanceClient = GetResistanceDmmClient(); |
|||
IScpiClient currentDmmClient = GetCurrentDmmClient(); |
|||
|
|||
try |
|||
{ |
|||
if (psuClient == null) |
|||
throw new InvalidOperationException("PSU 파워서플라이 장치가 설정되지 않았거나 비활성화 상태입니다."); |
|||
if (voltageClient == null) |
|||
throw new InvalidOperationException("전압 측정 DMM 장치가 설정되지 않았거나 비활성화 상태입니다."); |
|||
|
|||
// 1. 파워서플라이(PSU) CH1 출력 ON
|
|||
log.AppendLine($"> PSU CONNECT ({_psu.Host})"); |
|||
string psuSetup = !string.IsNullOrWhiteSpace(_psu.SetupCommand) ? _psu.SetupCommand : "OUTP ON, (@1)"; |
|||
log.AppendLine($"> PSU SETUP: {psuSetup}"); |
|||
await SendCommandListAsync(psuClient, psuSetup); |
|||
|
|||
// settle 지연 대기
|
|||
await Task.Delay(_settleMs).ConfigureAwait(false); |
|||
|
|||
// 2. 전압 측정 (전압 전용 계측기에서 MEAS:VOLT:DC? 로 측정)
|
|||
log.AppendLine($"> 전압 DMM CONNECT ({_voltageDmm.Host})"); |
|||
if (!string.IsNullOrWhiteSpace(_voltageDmm.SetupCommand)) |
|||
{ |
|||
log.AppendLine($"> 전압 DMM SETUP: {_voltageDmm.SetupCommand}"); |
|||
await SendCommandListAsync(voltageClient, _voltageDmm.SetupCommand); |
|||
} |
|||
|
|||
string voltageReadCmd = !string.IsNullOrWhiteSpace(_voltageDmm.ReadCommand) ? _voltageDmm.ReadCommand : "MEAS:VOLT:DC?"; |
|||
log.AppendLine($"> 전압 DMM SEND: {voltageReadCmd}"); |
|||
string vResponse = await voltageClient.QueryAsync(voltageReadCmd); |
|||
log.AppendLine($" 응답: {vResponse.Trim()}"); |
|||
double voltage = (double)ExtractFirstDecimal(vResponse, "VOLTAGE"); |
|||
|
|||
// 실시간 전압 업데이트
|
|||
onUpdate?.Invoke(voltage, null, null); |
|||
|
|||
// 3. 저항 측정 (저항 전용 계측기에서 MEAS:RES? 로 측정)
|
|||
log.AppendLine($"> 저항 DMM CONNECT ({_resistanceDmm.Host ?? _voltageDmm.Host})"); |
|||
if (resistanceClient != null && !string.IsNullOrWhiteSpace(_resistanceDmm.SetupCommand)) |
|||
{ |
|||
log.AppendLine($"> 저항 DMM SETUP: {_resistanceDmm.SetupCommand}"); |
|||
await SendCommandListAsync(resistanceClient, _resistanceDmm.SetupCommand); |
|||
} |
|||
|
|||
string resReadCmd = !string.IsNullOrWhiteSpace(_resistanceDmm.ReadCommand) ? _resistanceDmm.ReadCommand : _resistanceReadCommand; |
|||
log.AppendLine($"> 저항 DMM SEND: {resReadCmd}"); |
|||
string rResponse = await (resistanceClient ?? voltageClient).QueryAsync(resReadCmd); |
|||
log.AppendLine($" 응답: {rResponse.Trim()}"); |
|||
double rawResistance = (double)ExtractFirstDecimal(rResponse, "RESISTANCE"); |
|||
double resistance = rawResistance / 1000.0; // Ohms -> kOhms 변환 (kΩ 단위 표출)
|
|||
|
|||
// 실시간 저항 업데이트
|
|||
onUpdate?.Invoke(voltage, null, resistance); |
|||
|
|||
// 4. 전류 측정 (파워서플라이 CH1에서 MEAS:CURR? (@1) 로 측정)
|
|||
log.AppendLine($"> PSU 전류 측정 CONNECT ({_psu.Host})"); |
|||
string currentReadCmd = !string.IsNullOrWhiteSpace(_psu.ReadCommand) ? _psu.ReadCommand : "MEAS:CURR? (@1)"; |
|||
log.AppendLine($"> PSU SEND: {currentReadCmd}"); |
|||
string aResponse = await psuClient.QueryAsync(currentReadCmd); |
|||
log.AppendLine($" 응답: {aResponse.Trim()}"); |
|||
double rawCurrent = (double)ExtractFirstDecimal(aResponse, "CURRENT"); |
|||
double current = rawCurrent * 1000.0; // Amperes -> mA 변환
|
|||
|
|||
// 실시간 전류 및 최종 업데이트
|
|||
onUpdate?.Invoke(voltage, current, resistance); |
|||
|
|||
return (voltage, current, resistance); |
|||
} |
|||
finally |
|||
{ |
|||
// 5. 파워서플라이 CH1 출력 OFF
|
|||
if (psuClient != null) |
|||
{ |
|||
try |
|||
{ |
|||
string psuCleanup = !string.IsNullOrWhiteSpace(_psu.CleanupCommand) ? _psu.CleanupCommand : "OUTP OFF, (@1)"; |
|||
log.AppendLine($"> PSU CLEANUP: {psuCleanup}"); |
|||
await SendCommandListAsync(psuClient, psuCleanup); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
log.AppendLine($"> PSU OUTP OFF FAILED: {ex.Message}"); |
|||
} |
|||
} |
|||
LoggerService.Info("[Equipment] 독립 계측기 측정 시퀀스 로그:\n" + log); |
|||
} |
|||
} |
|||
|
|||
/// <summary>검사 전 보드 초기화 커맨드 실행 (PreBoardCommand).</summary>
|
|||
public async Task RunPreBoardCommandAsync() |
|||
{ |
|||
if (_psu.IsDisabled) |
|||
{ |
|||
LoggerService.Warn("[Equipment] PreBoard 커맨드 실행 불가: Power Supply 설정이 비활성화되어 있거나 올바르지 않습니다."); |
|||
throw new InvalidOperationException("Power Supply 장치가 비활성화 상태이거나 [PowerSupply] 설정이 올바르지 않습니다."); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(_preBoardCommand)) |
|||
{ |
|||
LoggerService.Warn("[Equipment] PreBoard 커맨드 실행 불가: Setting.ini 에 PreBoardCommand 설정이 없습니다."); |
|||
throw new InvalidOperationException("Setting.ini [Equipment] 섹션의 PreBoardCommand 설정이 비어있습니다."); |
|||
} |
|||
|
|||
var client = GetPsuClient(); |
|||
if (client == null) |
|||
{ |
|||
LoggerService.Error("[Equipment] PreBoard 커맨드 실행 불가: Power Supply 클라이언트 생성 실패"); |
|||
throw new InvalidOperationException("Power Supply 클라이언트를 생성할 수 없습니다 (연동 설식을 확인하세요)."); |
|||
} |
|||
|
|||
LoggerService.Info($"[Equipment] PreBoard 커맨드 실행 시작: {_preBoardCommand}"); |
|||
await SendCommandListAsync(client, _preBoardCommand); |
|||
await Task.Delay(_preBoardDelayMs).ConfigureAwait(false); |
|||
LoggerService.Info("[Equipment] PreBoard 커맨드(상시전원 ON) 실행 완료"); |
|||
} |
|||
|
|||
/// <summary>로그아웃 시 보드 전원 차단 (LogoutCommand).</summary>
|
|||
public async Task RunLogoutCommandAsync() |
|||
{ |
|||
if (_psu.IsDisabled || string.IsNullOrWhiteSpace(_logoutCommand)) |
|||
{ |
|||
LoggerService.Warn("[Equipment] Logout 커맨드 실행 스킵: Power Supply 비활성화 상태이거나 LogoutCommand 설정이 없습니다."); |
|||
return; |
|||
} |
|||
|
|||
var client = GetPsuClient(); |
|||
if (client == null) |
|||
{ |
|||
LoggerService.Error("[Equipment] Logout 커맨드 실행 실패: Power Supply 클라이언트 생성 불가"); |
|||
return; |
|||
} |
|||
|
|||
LoggerService.Info($"[Equipment] Logout 커맨드 실행: {_logoutCommand}"); |
|||
await SendCommandListAsync(client, _logoutCommand); |
|||
} |
|||
|
|||
// ── 내부 측정 헬퍼 ──────────────────────────────────────────────
|
|||
private async Task<double> ReadChannelAsync( |
|||
string label, |
|||
ScpiChannelSettings ch, |
|||
StringBuilder log) |
|||
{ |
|||
if (ch.IsDisabled) |
|||
{ |
|||
log.AppendLine($"> {label} SKIP: Setting.ini 에서 비활성화됨"); |
|||
return 0.0; |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(ch.ReadCommand)) |
|||
throw new InvalidOperationException($"Setting.ini [{label}] ReadCommand 값을 확인하세요."); |
|||
|
|||
var client = label == "VOLTAGE" ? GetVoltageClient() : GetPsuClient(); |
|||
if (client == null) throw new InvalidOperationException($"{label} 장치 클라이언트를 생성할 수 없습니다."); |
|||
return (double)await ReadChannelWithClientAsync(label, ch, client, log); |
|||
} |
|||
|
|||
private static async Task<decimal> ReadChannelWithClientAsync( |
|||
string label, |
|||
ScpiChannelSettings ch, |
|||
IScpiClient client, |
|||
StringBuilder log, |
|||
bool skipSetupCommand = false) |
|||
{ |
|||
log.AppendLine($"> {label} CONNECT OK"); |
|||
|
|||
if (!skipSetupCommand && !string.IsNullOrWhiteSpace(ch.SetupCommand)) |
|||
{ |
|||
log.AppendLine($"> {label} SETUP: {ch.SetupCommand}"); |
|||
await SendCommandListAsync(client, ch.SetupCommand); |
|||
} |
|||
|
|||
log.AppendLine($"> {label} READ: {ch.ReadCommand}"); |
|||
string response = await client.QueryAsync(ch.ReadCommand); |
|||
log.AppendLine($" 응답: {response.Trim()}"); |
|||
|
|||
return ExtractFirstDecimal(response, label); |
|||
} |
|||
|
|||
private IScpiClient CreateClient(string label, ScpiChannelSettings ch) |
|||
{ |
|||
string conn = ch.Connection.ToUpperInvariant(); |
|||
if (conn is "LAN" or "TCP" or "ETHERNET") |
|||
{ |
|||
return new TcpScpiClient(ch.Host, ch.Port, _timeoutMs, ch.GetIdnMatches(), ch.GetTerminator()); |
|||
} |
|||
throw new InvalidOperationException( |
|||
$"{label} 장비 연결 방식 '{ch.Connection}' 은 지원되지 않습니다. LAN/TCP 만 지원됩니다."); |
|||
} |
|||
|
|||
private static async Task SendCommandListAsync(IScpiClient client, string commands) |
|||
{ |
|||
foreach (var cmd in commands.Split(';', StringSplitOptions.RemoveEmptyEntries)) |
|||
{ |
|||
string trimmed = cmd.Trim(); |
|||
if (string.IsNullOrWhiteSpace(trimmed)) continue; |
|||
// (@2) 채널에 OUTP OFF 명령은 보호 대상 — 실수로 보드 전원 차단 방지
|
|||
if (Regex.IsMatch(trimmed, @"^\s*OUTP(?:UT)?\s+OFF\s*,?\s*\(@2\)\s*$", RegexOptions.IgnoreCase)) |
|||
continue; |
|||
|
|||
await client.SendAsync(trimmed); |
|||
await Task.Delay(100).ConfigureAwait(false); |
|||
} |
|||
} |
|||
|
|||
private static decimal ExtractFirstDecimal(string response, string label) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(response)) |
|||
throw new InvalidOperationException($"[{label}] 계측기 응답이 비어있습니다 (응답 수신 실패)."); |
|||
|
|||
var match = Regex.Match(response, @"[-+]?\d+(?:\.\d+)?(?:[Ee][-+]?\d+)?"); |
|||
if (!match.Success) |
|||
throw new InvalidOperationException($"[{label}] 수치 파싱 실패. 원본 응답: [{response.Trim()}]"); |
|||
|
|||
if (!decimal.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out decimal val)) |
|||
throw new InvalidOperationException($"[{label}] 수치 변환 실패 (값: '{match.Value}'). 원본 응답: [{response.Trim()}]"); |
|||
|
|||
return val; |
|||
} |
|||
|
|||
// ── INI 파서 ────────────────────────────────────────────────────
|
|||
private static Dictionary<string, string> ParseIni(string path) |
|||
{ |
|||
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); |
|||
if (!File.Exists(path)) return result; |
|||
|
|||
foreach (var raw in File.ReadAllLines(path)) |
|||
{ |
|||
string line = raw.Trim(); |
|||
if (string.IsNullOrEmpty(line) || line.StartsWith(";") || line.StartsWith("[")) continue; |
|||
int eq = line.IndexOf('='); |
|||
if (eq <= 0) continue; |
|||
string key = line.Substring(0, eq).Trim(); |
|||
string value = line.Substring(eq + 1).Trim(); |
|||
result[key] = value; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
private static string GetString(Dictionary<string, string> d, string key, string def) |
|||
=> d.TryGetValue(key, out var v) && !string.IsNullOrWhiteSpace(v) ? v : def; |
|||
|
|||
private static int GetInt(Dictionary<string, string> d, string key, int def) |
|||
=> d.TryGetValue(key, out var v) && int.TryParse(v, out int n) ? n : def; |
|||
|
|||
// ── IDisposable ──────────────────────────────────────────────────
|
|||
public void Dispose() |
|||
{ |
|||
if (_disposed) return; |
|||
_disposed = true; |
|||
try { _voltageDmmClient?.Dispose(); } catch { } |
|||
try { _currentDmmClient?.Dispose(); } catch { } |
|||
try { _resistanceDmmClient?.Dispose(); } catch { } |
|||
try { _psuClient?.Dispose(); } catch { } |
|||
_voltageDmmClient = null; |
|||
_currentDmmClient = null; |
|||
_resistanceDmmClient = null; |
|||
_psuClient = null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,336 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Runtime.InteropServices; |
|||
using marking_gui.Models; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public class EzdMarkingService : IMarkingService |
|||
{ |
|||
private bool _isInitialized = false; |
|||
private IntPtr _markingHandle = IntPtr.Zero; // 마킹 장치 기기 핸들 포인터
|
|||
private string _ezdFolderPath = string.Empty; |
|||
private MarkingConfigService _config; |
|||
private string _lastInitErrorMessage = "초기화가 진행되지 않았습니다."; |
|||
|
|||
public string LastInitErrorMessage => _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 = "ChangeTextByName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] |
|||
private static extern int ChangeTextByNameA(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 = "GetTextByName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] |
|||
private static extern int GetTextByNameA(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); |
|||
|
|||
public bool Initialize(string configPath, IntPtr windowHandle) |
|||
{ |
|||
try |
|||
{ |
|||
_lastInitErrorMessage = string.Empty; |
|||
_config = new MarkingConfigService(); |
|||
_ezdFolderPath = _config.EzdFolderPath; |
|||
|
|||
if (string.IsNullOrEmpty(_ezdFolderPath)) |
|||
{ |
|||
_lastInitErrorMessage = "Marking.ini 내 EzdFolderPath 경로가 비어 있습니다."; |
|||
_isInitialized = false; |
|||
return false; |
|||
} |
|||
|
|||
if (!Directory.Exists(_ezdFolderPath)) |
|||
{ |
|||
_lastInitErrorMessage = string.Format("EzCad 폴더가 존재하지 않습니다: {0} (Marking.ini 설정 확인 필요)", _ezdFolderPath); |
|||
_isInitialized = false; |
|||
return false; |
|||
} |
|||
|
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 마킹 기계 LMC 초기화 시도. EzCadPath: " + _ezdFolderPath + ", WindowHandle: " + windowHandle); |
|||
|
|||
// 1. InitMarkEzd() 호출로 디바이스 전역 제어 핸들 획득
|
|||
_markingHandle = InitMarkEzd(); |
|||
System.Diagnostics.Debug.WriteLine(string.Format("[EzdMarking] InitMarkEzd() 완료. 생성된 핸들 포인터: 0x{0:X}", _markingHandle.ToInt64())); |
|||
|
|||
if (_markingHandle == IntPtr.Zero) |
|||
{ |
|||
_isInitialized = false; |
|||
_lastInitErrorMessage = "InitMarkEzd() 실행 결과 생성된 핸들 포인터가 Zero(Null)입니다. 마킹 보드 및 드라이버 연결 상태를 점검하세요."; |
|||
return false; |
|||
} |
|||
|
|||
// 2. 획득된 핸들을 이용해 Init() 장치 매핑 수행
|
|||
int result = Init(_markingHandle, _ezdFolderPath, windowHandle); |
|||
|
|||
if (result == 0) // 0 이 성공 코드
|
|||
{ |
|||
_isInitialized = true; |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 실서버 LMC 컨트롤 보드 장치 연결 및 초기화 성공."); |
|||
} |
|||
else |
|||
{ |
|||
_isInitialized = false; |
|||
_lastInitErrorMessage = string.Format("LMC 컨트롤 카드 통신 실패 (Init 에러코드: {0})", result); |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] LMC 장치 연결 실패. 에러 코드: " + result); |
|||
try { Close(_markingHandle); } catch { } |
|||
_markingHandle = IntPtr.Zero; |
|||
} |
|||
|
|||
return _isInitialized; |
|||
} |
|||
catch (DllNotFoundException ex) |
|||
{ |
|||
_isInitialized = false; |
|||
_lastInitErrorMessage = "MarkEzdWrapper.dll 또는 하위 C++ DLL 로드 실패 (x86/32비트 아키텍처 타겟팅 컴파일 여부 확인 필요)"; |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] MarkEzdWrapper.dll 또는 하위 DLL(Lmc1.dll 등)을 로드할 수 없습니다. 실행 폴더에 복사했는지 확인하세요. 상세: " + ex.Message); |
|||
return false; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_isInitialized = false; |
|||
_lastInitErrorMessage = "마킹 컨트롤 보드 연동 예외 발생: " + ex.Message; |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 초기화 예외 발생: " + ex.Message); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions] |
|||
[System.Security.SecurityCritical] |
|||
public MarkingResult RequestMarking(MarkingRequest request) |
|||
{ |
|||
if (!_isInitialized || _markingHandle == IntPtr.Zero) |
|||
{ |
|||
return new MarkingResult |
|||
{ |
|||
Success = false, |
|||
ErrorCode = -10, |
|||
ErrorMessage = "LMC 마킹 디바이스가 연결 및 초기화되지 않았습니다. 상세 원인: " + _lastInitErrorMessage, |
|||
MarkedAt = DateTime.Now |
|||
}; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
// 1. 도안 파일 경로 확인
|
|||
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 |
|||
}; |
|||
} |
|||
|
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 도안 파일 로드 시작: " + ezdPath); |
|||
string absoluteEzdPath = Path.GetFullPath(ezdPath); |
|||
int loadResult = LoadEzdFile(_markingHandle, absoluteEzdPath); // 획득한 핸들 전달
|
|||
if (loadResult != 0) |
|||
{ |
|||
return new MarkingResult |
|||
{ |
|||
Success = false, |
|||
ErrorCode = loadResult, |
|||
ErrorMessage = string.Format("도안 파일(.ezd) 로드 실패. (경로: {0}, LoadEzdFile 에러코드: {1})", absoluteEzdPath, loadResult), |
|||
MarkedAt = DateTime.Now |
|||
}; |
|||
} |
|||
|
|||
// 1-1. 도안 파일(.ezd) 내부의 고정 텍스트 오브젝트(도면품번, HKMC 품번)를 직접 읽어오기
|
|||
string ezdDrawingNo = GetTextFromEzd(_config.DrawingNoTag); |
|||
string ezdHkmcNo = GetTextFromEzd(_config.HkmcNoTag); |
|||
|
|||
if (!string.IsNullOrWhiteSpace(ezdDrawingNo)) |
|||
{ |
|||
request.DrawingNo = ezdDrawingNo; |
|||
} |
|||
if (!string.IsNullOrWhiteSpace(ezdHkmcNo)) |
|||
{ |
|||
request.HkmcNo = ezdHkmcNo; |
|||
} |
|||
|
|||
// EZD 고정값 기반으로 QR 코드 데이터 문자열 최종 재조합 ([IC S/N];[도면품번];[HKMC품번];[제품 S/N];)
|
|||
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); |
|||
|
|||
// 2. 도안 내 변수 태그 치환 (사양서 4대 태그: S/N, DMC, 도면품번, HKMC품번)
|
|||
ChangeTextInEzd(_config.SerialTag, request.Serial); |
|||
ChangeTextInEzd(_config.QrCodeTag, request.QrString); |
|||
ChangeTextInEzd(_config.DrawingNoTag, request.DrawingNo); |
|||
ChangeTextInEzd(_config.HkmcNoTag, request.HkmcNo); |
|||
|
|||
System.Diagnostics.Debug.WriteLine(string.Format( |
|||
"[EzdMarking] 도안 텍스트 치환 완료. Serial:{0}, LotNo:{1}, Product:{2}, Drawing:{3}, Hkmc:{4}, Qr:{5}", |
|||
request.Serial, request.LotNo, request.ProductNo, request.DrawingNo, request.HkmcNo, request.QrString)); |
|||
|
|||
// 3. 레이저 마킹 시작 (획득한 핸들 전달)
|
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 레이저 마킹 기계 동작 시작..."); |
|||
int markResult = Mark(_markingHandle); |
|||
|
|||
if (markResult == 0) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 마킹 기계 동작 완료 (성공)"); |
|||
return new MarkingResult |
|||
{ |
|||
Success = true, |
|||
ErrorCode = 0, |
|||
ErrorMessage = "마킹 완료", |
|||
MarkedAt = DateTime.Now |
|||
}; |
|||
} |
|||
else |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] 마킹 기계 동작 에러 발생: " + markResult); |
|||
return new MarkingResult |
|||
{ |
|||
Success = false, |
|||
ErrorCode = markResult, |
|||
ErrorMessage = string.Format("레이저 각인 하드웨어 동작 에러 (에러코드: {0})", markResult), |
|||
MarkedAt = DateTime.Now |
|||
}; |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[EzdMarking] RequestMarking 실행 중 예외 발생: " + ex.Message); |
|||
return new MarkingResult |
|||
{ |
|||
Success = false, |
|||
ErrorCode = -99, |
|||
ErrorMessage = "마킹 처리 중 예외 발생: " + ex.Message, |
|||
MarkedAt = DateTime.Now |
|||
}; |
|||
} |
|||
} |
|||
|
|||
private bool _disposed = false; |
|||
|
|||
private string GetTextFromEzd(string tagName) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(tagName) || _markingHandle == IntPtr.Zero) |
|||
return string.Empty; |
|||
|
|||
try |
|||
{ |
|||
// 1차: Unicode (UTF-16) 시도
|
|||
var sbW = new System.Text.StringBuilder(512); |
|||
int resW = GetTextByNameW(_markingHandle, tagName, sbW); |
|||
if (resW == 0 && sbW.Length > 0) |
|||
{ |
|||
return sbW.ToString().Trim(); |
|||
} |
|||
|
|||
// 2차: Ansi (CP949/EUC-KR) 시도 (C++ Wrapper가 ANSI인 경우 대비)
|
|||
var sbA = new System.Text.StringBuilder(512); |
|||
int resA = GetTextByNameA(_markingHandle, tagName, sbA); |
|||
if (resA == 0 && sbA.Length > 0) |
|||
{ |
|||
return sbA.ToString().Trim(); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine($"[EzdMarking] GetTextByName({tagName}) 읽기 예외: {ex.Message}"); |
|||
} |
|||
return string.Empty; |
|||
} |
|||
|
|||
private void ChangeTextInEzd(string tagName, string textNew) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(tagName) || _markingHandle == IntPtr.Zero) return; |
|||
try |
|||
{ |
|||
int resW = ChangeTextByNameW(_markingHandle, tagName, textNew); |
|||
if (resW != 0) |
|||
{ |
|||
ChangeTextByNameA(_markingHandle, tagName, textNew); |
|||
} |
|||
} |
|||
catch |
|||
{ |
|||
// Fallback
|
|||
} |
|||
} |
|||
|
|||
public void Shutdown() |
|||
{ |
|||
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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using marking_gui.Models; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public interface IMarkingService : IDisposable |
|||
{ |
|||
/// <summary>
|
|||
/// 마킹 서비스 및 하드웨어를 초기화합니다.
|
|||
/// </summary>
|
|||
/// <param name="configPath">설정 파일(Config.ini 등)의 경로</param>
|
|||
/// <returns>초기화 성공 여부</returns>
|
|||
bool Initialize(string configPath, IntPtr windowHandle); |
|||
|
|||
/// <summary>
|
|||
/// 지정한 매개변수로 마킹 작업을 요청합니다.
|
|||
/// </summary>
|
|||
/// <param name="request">마킹 파라미터 묶음</param>
|
|||
/// <returns>마킹 처리 결과</returns>
|
|||
MarkingResult RequestMarking(MarkingRequest request); |
|||
|
|||
/// <summary>
|
|||
/// 마지막 초기화 실패 시의 상세 에러 메시지
|
|||
/// </summary>
|
|||
string LastInitErrorMessage { get; } |
|||
|
|||
/// <summary>
|
|||
/// 마킹 드라이버 및 리소스를 정상적으로 해제합니다.
|
|||
/// </summary>
|
|||
void Shutdown(); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
/// <summary>
|
|||
/// SCPI 계측기와 명령을 주고받는 클라이언트 인터페이스.
|
|||
/// LAN(TCP), Serial 등 다양한 연결 방식에 대응합니다.
|
|||
/// </summary>
|
|||
public interface IScpiClient : System.IDisposable |
|||
{ |
|||
/// <summary>계측기에 SCPI 명령을 전송합니다 (응답 없음).</summary>
|
|||
Task SendAsync(string command); |
|||
|
|||
/// <summary>계측기에 SCPI 명령을 전송하고 응답 문자열을 반환합니다.</summary>
|
|||
Task<string> QueryAsync(string command); |
|||
} |
|||
} |
|||
@ -0,0 +1,96 @@ |
|||
using System; |
|||
using System.IO; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public static class LoggerService |
|||
{ |
|||
private static readonly string LogDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); |
|||
private static readonly object LockObj = new object(); |
|||
|
|||
static LoggerService() |
|||
{ |
|||
try |
|||
{ |
|||
if (!Directory.Exists(LogDirectory)) |
|||
{ |
|||
Directory.CreateDirectory(LogDirectory); |
|||
} |
|||
|
|||
// 오래된 로그 정리 태스크 백그라운드 구동 (애플리케이션 시작 차단 방지)
|
|||
System.Threading.Tasks.Task.Run(() => CleanUpOldLogs(30)); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("Log directory creation failed: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
private static void CleanUpOldLogs(int retentionDays) |
|||
{ |
|||
try |
|||
{ |
|||
var dirInfo = new DirectoryInfo(LogDirectory); |
|||
if (!dirInfo.Exists) return; |
|||
|
|||
DateTime threshold = DateTime.Now.AddDays(-retentionDays); |
|||
foreach (var file in dirInfo.GetFiles("*.log")) |
|||
{ |
|||
try |
|||
{ |
|||
if (file.LastWriteTime < threshold) |
|||
{ |
|||
file.Delete(); |
|||
System.Diagnostics.Debug.WriteLine($"[SRE Logger] 만료된 로그 파일 삭제 완료: {file.Name}"); |
|||
} |
|||
} |
|||
catch (Exception fileEx) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine($"[SRE Logger] 로그 파일 삭제 중 예외 (파일명: {file.Name}): {fileEx.Message}"); |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[SRE Logger] 만료 로그 정리 중 예외 발생: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
public static void Info(string message) |
|||
{ |
|||
WriteLog("INFO", message); |
|||
} |
|||
|
|||
public static void Warn(string message) |
|||
{ |
|||
WriteLog("WARN", message); |
|||
} |
|||
|
|||
public static void Error(string message, Exception ex = null) |
|||
{ |
|||
string detail = message; |
|||
if (ex != null) |
|||
{ |
|||
detail += string.Format("\n[Exception] {0}\n[StackTrace]\n{1}", ex.Message, ex.StackTrace); |
|||
} |
|||
WriteLog("ERROR", detail); |
|||
} |
|||
|
|||
private static void WriteLog(string level, string message) |
|||
{ |
|||
lock (LockObj) |
|||
{ |
|||
try |
|||
{ |
|||
string logFile = Path.Combine(LogDirectory, DateTime.Now.ToString("yyyy-MM-dd") + ".log"); |
|||
string logLine = string.Format("[{0}] [{1}] {2}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), level, message) + Environment.NewLine; |
|||
File.AppendAllText(logFile, logLine); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("Writing log failed: " + ex.Message); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,259 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public class MarkingConfigService |
|||
{ |
|||
private readonly Dictionary<string, string> _settings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); |
|||
private readonly Dictionary<string, string> _tags = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); |
|||
|
|||
public string EzdFolderPath |
|||
{ |
|||
get |
|||
{ |
|||
string path = GetSetting("EzdFolderPath", @"c:\EzCad\EasyCfg"); |
|||
|
|||
// 1. C:\EzCad\EasyCfg 및 설정 경로 체크, 없으면 실행 파일 기준 폴더 사용
|
|||
string defaultFallback = Directory.Exists(@"c:\EzCad\EasyCfg") ? @"c:\EzCad\EasyCfg" : AppDomain.CurrentDomain.BaseDirectory; |
|||
|
|||
// 1. 설정값이 비어있을 시 실행 파일 기준 폴더 사용
|
|||
if (string.IsNullOrWhiteSpace(path)) |
|||
{ |
|||
return defaultFallback; |
|||
} |
|||
|
|||
// 2. 상대 경로일 시 실행 파일 디렉토리 기준으로 절대 경로 병합
|
|||
if (!Path.IsPathRooted(path)) |
|||
{ |
|||
return Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path)); |
|||
} |
|||
|
|||
// 3. 절대 경로이지만 타깃 경로가 실재하지 않는 경우 실행 파일 폴더로 Fallback
|
|||
if (!Directory.Exists(path)) |
|||
{ |
|||
return defaultFallback; |
|||
} |
|||
|
|||
return path; |
|||
} |
|||
} |
|||
|
|||
public string LastSelectedEzdFile => GetSetting("LastSelectedEzdFile", string.Empty); |
|||
|
|||
public void SaveLastSelectedEzdFile(string filePath) |
|||
{ |
|||
try |
|||
{ |
|||
_settings["LastSelectedEzdFile"] = filePath; |
|||
string baseDir = AppDomain.CurrentDomain.BaseDirectory; |
|||
string iniPath = Path.Combine(baseDir, "Setting.ini"); |
|||
|
|||
if (File.Exists(iniPath)) |
|||
{ |
|||
var lines = new List<string>(File.ReadAllLines(iniPath)); |
|||
bool found = false; |
|||
for (int i = 0; i < lines.Count; i++) |
|||
{ |
|||
string trimmed = lines[i].Trim(); |
|||
if (trimmed.StartsWith("LastSelectedEzdFile=", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
lines[i] = "LastSelectedEzdFile=" + filePath; |
|||
found = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (!found) |
|||
{ |
|||
// [Settings] 섹션 아래에 추가
|
|||
for (int i = 0; i < lines.Count; i++) |
|||
{ |
|||
if (lines[i].Trim().Equals("[Settings]", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
lines.Insert(i + 1, "LastSelectedEzdFile=" + filePath); |
|||
found = true; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (found) |
|||
{ |
|||
File.WriteAllLines(iniPath, lines); |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[MarkingConfig] LastSelectedEzdFile 저장 중 에러: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
public string SerialTag => GetTag("SerialTag", "SERIAL"); |
|||
public string LotNoTag => GetTag("LotNoTag", "YYMMDD"); |
|||
public string ProductTag => GetTag("ProductTag", "PRODUCT"); |
|||
public string QrCodeTag => GetTag("QrCodeTag", "QRCODETAG"); |
|||
public string LineTag => GetTag("LineTag", "LCODE"); |
|||
public string ShiftTag => GetTag("ShiftTag", "BAN"); |
|||
public string DrawingNoTag => GetTag("DrawingNoTag", "DRAWING_NO"); |
|||
public string HkmcNoTag => GetTag("HkmcNoTag", "HKMC_NO"); |
|||
|
|||
public string DrawingNo => GetSetting("DrawingNo", string.Empty); |
|||
public string HkmcNo => GetSetting("HkmcNo", string.Empty); |
|||
|
|||
public bool IsTestMode |
|||
{ |
|||
get |
|||
{ |
|||
string val = GetSetting("test", "false"); |
|||
return bool.TryParse(val, out bool result) && result; |
|||
} |
|||
} |
|||
|
|||
public MarkingConfigService() |
|||
{ |
|||
LoadConfig(); |
|||
} |
|||
|
|||
private void LoadConfig() |
|||
{ |
|||
try |
|||
{ |
|||
// BaseDirectory에서 Setting.ini 로드 시도
|
|||
string baseDir = AppDomain.CurrentDomain.BaseDirectory; |
|||
string iniPath = Path.Combine(baseDir, "Setting.ini"); |
|||
|
|||
// BaseDirectory에 없으면 한 단계 위 프로젝트 폴더에서도 탐색 (개발 편의성)
|
|||
if (!File.Exists(iniPath)) |
|||
{ |
|||
string parentDir = Directory.GetParent(baseDir)?.Parent?.Parent?.FullName; |
|||
if (parentDir != null) |
|||
{ |
|||
string devPath = Path.Combine(parentDir, "marking_gui", "Setting.ini"); |
|||
if (File.Exists(devPath)) |
|||
{ |
|||
iniPath = devPath; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (File.Exists(iniPath)) |
|||
{ |
|||
byte[] bytes = File.ReadAllBytes(iniPath); |
|||
string fileText; |
|||
if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) |
|||
{ |
|||
fileText = System.Text.Encoding.UTF8.GetString(bytes, 3, bytes.Length - 3); |
|||
} |
|||
else |
|||
{ |
|||
try |
|||
{ |
|||
var strictUtf8 = new System.Text.UTF8Encoding(false, true); |
|||
fileText = strictUtf8.GetString(bytes); |
|||
} |
|||
catch |
|||
{ |
|||
fileText = System.Text.Encoding.Default.GetString(bytes); |
|||
} |
|||
} |
|||
|
|||
var lines = fileText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); |
|||
string currentSection = string.Empty; |
|||
|
|||
foreach (var line in lines) |
|||
{ |
|||
var trimmed = line.Trim(); |
|||
if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith(";")) |
|||
continue; |
|||
|
|||
if (trimmed.StartsWith("[") && trimmed.EndsWith("]")) |
|||
{ |
|||
currentSection = trimmed.Substring(1, trimmed.Length - 2).Trim(); |
|||
continue; |
|||
} |
|||
|
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
var key = parts[0].Trim(); |
|||
var val = parts[1].Trim(); |
|||
|
|||
if (currentSection.Equals("Settings", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
_settings[key] = val; |
|||
} |
|||
else if (currentSection.Equals("Tags", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
_tags[key] = val; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[MarkingConfig] 설정 로드 중 에러: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
private string GetSetting(string key, string defaultVal) |
|||
{ |
|||
return _settings.TryGetValue(key, out string val) ? val : defaultVal; |
|||
} |
|||
|
|||
private string GetTag(string key, string defaultVal) |
|||
{ |
|||
return _tags.TryGetValue(key, out string val) ? val : defaultVal; |
|||
} |
|||
|
|||
public int GetLastSequence(string lotNo) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(lotNo)) return 0; |
|||
string key = "Seq_" + lotNo.Trim(); |
|||
if (_settings.TryGetValue(key, out string valStr) && int.TryParse(valStr, out int seq)) |
|||
{ |
|||
return seq; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
public void SaveLastSequence(string lotNo, int sequence) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(lotNo)) return; |
|||
try |
|||
{ |
|||
string key = "Seq_" + lotNo.Trim(); |
|||
_settings[key] = sequence.ToString(); |
|||
|
|||
string iniPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Setting.ini"); |
|||
if (File.Exists(iniPath)) |
|||
{ |
|||
var lines = new List<string>(File.ReadAllLines(iniPath)); |
|||
bool found = false; |
|||
for (int i = 0; i < lines.Count; i++) |
|||
{ |
|||
string trimmed = lines[i].Trim(); |
|||
if (trimmed.StartsWith(key + "=", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
lines[i] = string.Format("{0}={1}", key, sequence); |
|||
found = true; |
|||
break; |
|||
} |
|||
} |
|||
if (!found) |
|||
{ |
|||
lines.Add(string.Format("{0}={1}", key, sequence)); |
|||
} |
|||
File.WriteAllLines(iniPath, lines); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine("[MarkingConfig] 순번 저장 실패: " + ex.Message); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
using System; |
|||
using marking_gui.Models; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public class MockDatabase |
|||
{ |
|||
public Product GetProductBySerial(string serial) |
|||
{ |
|||
if (string.IsNullOrEmpty(serial)) |
|||
return null; |
|||
|
|||
string searchSerial = serial.Trim().ToUpper(); |
|||
|
|||
if (searchSerial == "PASS1234") |
|||
{ |
|||
// 이전 검사 모두 합격
|
|||
return new Product(searchSerial, "PASS", "PASS", "PASS"); |
|||
} |
|||
else if (searchSerial == "FAIL5678") |
|||
{ |
|||
// 이전 검사 중 Calibration 단계 실패
|
|||
return new Product(searchSerial, "PASS", "FAIL", "PASS"); |
|||
} |
|||
|
|||
// 등록되지 않은 S/N
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -1,75 +0,0 @@ |
|||
using System; |
|||
using marking_gui.Models; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public class MockMeasurer |
|||
{ |
|||
private readonly Random _random = new Random(); |
|||
|
|||
// 2초 동안 측정 중 요동칠 가상 데이터 생성
|
|||
public void GenerateNoiseValues(MeasurementLimits limits, out double voltage, out double current, out double resistance) |
|||
{ |
|||
double midVoltage = (limits.MinVoltage + limits.MaxVoltage) / 2.0; |
|||
double midCurrent = (limits.MinCurrent + limits.MaxCurrent) / 2.0; |
|||
double midResistance = (limits.MinResistance + limits.MaxResistance) / 2.0; |
|||
|
|||
// 설정 범위 폭에 맞추어 ±50% 범위의 노이즈 생성
|
|||
double voltageSpan = limits.MaxVoltage - limits.MinVoltage; |
|||
double currentSpan = limits.MaxCurrent - limits.MinCurrent; |
|||
double resistanceSpan = limits.MaxResistance - limits.MinResistance; |
|||
|
|||
voltage = midVoltage + (_random.NextDouble() * voltageSpan - (voltageSpan / 2.0)); |
|||
current = midCurrent + (_random.NextDouble() * currentSpan - (currentSpan / 2.0)); |
|||
resistance = midResistance + (_random.NextDouble() * resistanceSpan - (resistanceSpan / 2.0)); |
|||
} |
|||
|
|||
// 최종 합/불 판정 측정값 결정 (80% 확률로 합격 범위, 20% 확률로 불합격 범위 값 생성)
|
|||
public void GenerateFinalValues(MeasurementLimits limits, out double voltage, out double current, out double resistance) |
|||
{ |
|||
double voltageSpan = limits.MaxVoltage - limits.MinVoltage; |
|||
double currentSpan = limits.MaxCurrent - limits.MinCurrent; |
|||
double resistanceSpan = limits.MaxResistance - limits.MinResistance; |
|||
|
|||
if (_random.Next(0, 10) < 8) |
|||
{ |
|||
// 합격 범위 내의 가상 측정값 생성
|
|||
voltage = limits.MinVoltage + (_random.NextDouble() * voltageSpan); |
|||
current = limits.MinCurrent + (_random.NextDouble() * currentSpan); |
|||
resistance = limits.MinResistance + (_random.NextDouble() * resistanceSpan); |
|||
} |
|||
else |
|||
{ |
|||
// 불합격 범위 유도
|
|||
int errorType = _random.Next(0, 3); |
|||
if (errorType == 0) |
|||
{ |
|||
// 전압 에러 유도 (범위 폭의 50% 정도 벗어나도록 가/감산하여 음수 방지)
|
|||
voltage = _random.Next(0, 2) == 0 |
|||
? (limits.MinVoltage - (voltageSpan * 0.5)) |
|||
: (limits.MaxVoltage + (voltageSpan * 0.5)); |
|||
current = limits.MinCurrent + (_random.NextDouble() * currentSpan); |
|||
resistance = limits.MinResistance + (_random.NextDouble() * resistanceSpan); |
|||
} |
|||
else if (errorType == 1) |
|||
{ |
|||
// 전류 에러 유도
|
|||
voltage = limits.MinVoltage + (_random.NextDouble() * voltageSpan); |
|||
current = _random.Next(0, 2) == 0 |
|||
? (limits.MinCurrent - (currentSpan * 0.5)) |
|||
: (limits.MaxCurrent + (currentSpan * 0.5)); |
|||
resistance = limits.MinResistance + (_random.NextDouble() * resistanceSpan); |
|||
} |
|||
else |
|||
{ |
|||
// 저항 에러 유도
|
|||
voltage = limits.MinVoltage + (_random.NextDouble() * voltageSpan); |
|||
current = limits.MinCurrent + (_random.NextDouble() * currentSpan); |
|||
resistance = _random.Next(0, 2) == 0 |
|||
? (limits.MinResistance - (resistanceSpan * 0.5)) |
|||
: (limits.MaxResistance + (resistanceSpan * 0.5)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,173 +0,0 @@ |
|||
using System; |
|||
using System.Configuration; |
|||
using marking_gui.Models; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
public class MssqlDatabaseService |
|||
{ |
|||
private readonly string _connectionString; |
|||
|
|||
public MssqlDatabaseService() |
|||
{ |
|||
try |
|||
{ |
|||
// AppDomain.CurrentDomain.BaseDirectory 에서 Database.ini 로드 시도
|
|||
string iniPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Database.ini"); |
|||
if (System.IO.File.Exists(iniPath)) |
|||
{ |
|||
var lines = System.IO.File.ReadAllLines(iniPath); |
|||
foreach (var line in lines) |
|||
{ |
|||
var trimmed = line.Trim(); |
|||
if (trimmed.StartsWith("ConnectionString", StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
var parts = trimmed.Split(new[] { '=' }, 2); |
|||
if (parts.Length == 2) |
|||
{ |
|||
_connectionString = parts[1].Trim(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Database.ini 에 없을 경우 App.config 백업 사용
|
|||
if (string.IsNullOrEmpty(_connectionString)) |
|||
{ |
|||
var connSettings = ConfigurationManager.ConnectionStrings["MssqlConnection"]; |
|||
if (connSettings != null) |
|||
{ |
|||
_connectionString = connSettings.ConnectionString; |
|||
} |
|||
else |
|||
{ |
|||
_connectionString = "Server=localhost;Database=MarkingDb;Trusted_Connection=True;"; |
|||
} |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_connectionString = string.Empty; |
|||
System.Diagnostics.Debug.WriteLine("설정 로드 중 예외 발생: " + ex.Message); |
|||
} |
|||
} |
|||
|
|||
public Product GetProductBySerial(string serial) |
|||
{ |
|||
if (string.IsNullOrEmpty(serial)) |
|||
return null; |
|||
|
|||
string searchSerial = serial.Trim().ToUpper(); |
|||
|
|||
// TODO: 사용자의 지시에 따라 실제 MSSQL DB 질의 쿼리는 아직 작성하지 않고 대기합니다.
|
|||
// 추후 실제 연동 시 아래 SQL Connection 및 SELECT 쿼리를 구현할 수 있도록 준비만 해둡니다.
|
|||
/* |
|||
string query = "SELECT SerialNumber, HousingResult, CalResult, EolResult FROM ProductResults WHERE UPPER(SerialNumber) = @Serial"; |
|||
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) |
|||
{ |
|||
... |
|||
} |
|||
*/ |
|||
|
|||
// 준비 단계 동안 임시로 기존 Mock 데이터를 반환하도록 구현 (Stub)
|
|||
if (searchSerial == "PASS1234") |
|||
{ |
|||
return new Product(searchSerial, "PASS", "PASS", "PASS"); |
|||
} |
|||
else if (searchSerial == "FAIL5678") |
|||
{ |
|||
return new Product(searchSerial, "PASS", "FAIL", "PASS"); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 최종 성능 검출 값을 데이터베이스에 저장합니다.
|
|||
/// 전압과 전류 수치는 3,2 포맷(DECIMAL(3, 2) 등)에 대응하기 위해 소수점 이하 2자리로 반올림하여 처리합니다.
|
|||
/// </summary>
|
|||
public bool SaveProductResult( |
|||
string serial, |
|||
string maker, |
|||
string model, |
|||
string variant1, |
|||
string variant2, |
|||
string operatorId, |
|||
string line, |
|||
string lotNo, |
|||
string jigNo, |
|||
double voltage, |
|||
double current, |
|||
double resistance, |
|||
string result) |
|||
{ |
|||
// 전압과 전류, 저항을 소수점 이하 2자리(3,2 포맷 규격)로 반올림 처리
|
|||
decimal roundedVoltage = Math.Round((decimal)voltage, 2); |
|||
decimal roundedCurrent = Math.Round((decimal)current, 2); |
|||
decimal roundedResistance = Math.Round((decimal)resistance, 2); |
|||
|
|||
// DB 컬럼 길이 한계에 맞춰서 문자열 안전하게 자르기 (Truncate)
|
|||
string safeMaker = string.IsNullOrEmpty(maker) ? "" : (maker.Length > 10 ? maker.Substring(0, 10) : maker); |
|||
string safeModel = string.IsNullOrEmpty(model) ? "" : (model.Length > 10 ? model.Substring(0, 10) : model); |
|||
string safeVariant1 = string.IsNullOrEmpty(variant1) ? "" : (variant1.Length > 10 ? variant1.Substring(0, 10) : variant1); |
|||
string safeVariant2 = string.IsNullOrEmpty(variant2) ? "" : (variant2.Length > 10 ? variant2.Substring(0, 10) : variant2); |
|||
string safeOperator = string.IsNullOrEmpty(operatorId) ? "" : (operatorId.Length > 10 ? operatorId.Substring(0, 10) : operatorId); |
|||
string safeLine = string.IsNullOrEmpty(line) ? "" : (line.Length > 5 ? line.Substring(0, 5) : line); |
|||
string safeLotNo = string.IsNullOrEmpty(lotNo) ? "" : (lotNo.Length > 8 ? lotNo.Substring(0, 8) : lotNo); |
|||
string safeJigNo = string.IsNullOrEmpty(jigNo) ? "" : (jigNo.Length > 10 ? jigNo.Substring(0, 10) : jigNo); |
|||
|
|||
DateTime prodDate = DateTime.Now; |
|||
// QR Code 조합 포맷 생성 (Maker;Model;Variant_1;Variant_2;Operator;Production_Date)
|
|||
string markingQr = string.Format("{0};{1};{2};{3};{4};{5}", |
|||
safeMaker, safeModel, safeVariant1, safeVariant2, safeOperator, prodDate.ToString("yyyyMMddHHmmss")); |
|||
if (markingQr.Length > 100) |
|||
{ |
|||
markingQr = markingQr.Substring(0, 100); |
|||
} |
|||
|
|||
// TODO: 실제 MSSQL DB 적재를 위해 SQL 명령문 구현 템플릿 준비
|
|||
/* |
|||
string query = @"INSERT INTO [dbo].[Marking]
|
|||
([IC_SN], [Marking_QR], [Maker], [Model], [Variant_1], [Variant_2], [Operator], [Production_Date], [Line], [Lot_No], [Jig_No], |
|||
[PT_Vol_1], [PT_Vol_2], [PT_Vol_3], [PT_Current_1], [PT_Current_2], [PT_Current_3], [PT_Resistance_1], [PT_Resistance_2], [PT_Resistance_3], [Result]) |
|||
VALUES |
|||
(@Serial, @Qr, @Maker, @Model, @Var1, @Var2, @Operator, @ProdDate, @Line, @LotNo, @JigNo, |
|||
@Vol1, 0.00, 0.00, @Cur1, 0.00, 0.00, @Res1, 0.00, 0.00, @Result)";
|
|||
|
|||
using (var conn = new System.Data.SqlClient.SqlConnection(_connectionString)) |
|||
{ |
|||
using (var cmd = new System.Data.SqlClient.SqlCommand(query, conn)) |
|||
{ |
|||
cmd.Parameters.AddWithValue("@Serial", serial); |
|||
cmd.Parameters.AddWithValue("@Qr", markingQr); |
|||
cmd.Parameters.AddWithValue("@Maker", safeMaker); |
|||
cmd.Parameters.AddWithValue("@Model", safeModel); |
|||
cmd.Parameters.AddWithValue("@Var1", safeVariant1); |
|||
cmd.Parameters.AddWithValue("@Var2", safeVariant2); |
|||
cmd.Parameters.AddWithValue("@Operator", safeOperator); |
|||
cmd.Parameters.AddWithValue("@ProdDate", prodDate); |
|||
cmd.Parameters.AddWithValue("@Line", safeLine); |
|||
cmd.Parameters.AddWithValue("@LotNo", safeLotNo); |
|||
cmd.Parameters.AddWithValue("@JigNo", safeJigNo); |
|||
|
|||
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Vol1", System.Data.SqlDbType.Decimal) { Precision = 3, Scale = 2, Value = roundedVoltage }); |
|||
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Cur1", System.Data.SqlDbType.Decimal) { Precision = 3, Scale = 2, Value = roundedCurrent }); |
|||
cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Res1", System.Data.SqlDbType.Decimal) { Precision = 3, Scale = 2, Value = roundedResistance }); |
|||
cmd.Parameters.AddWithValue("@Result", result); |
|||
|
|||
conn.Open(); |
|||
cmd.ExecuteNonQuery(); |
|||
} |
|||
} |
|||
*/ |
|||
|
|||
// 데모 단계 로그 출력 및 성공 반환
|
|||
System.Diagnostics.Debug.WriteLine(string.Format( |
|||
"[DB 저장 로그] S/N: {0} | QR: {1} | Maker: {2} | Model: {3} | Line: {4} | LotNo: {5} | Vol_1: {6:F2}V | Cur_1: {7:F2}A | Res_1: {8:F2}Ω | 결과: {9}", |
|||
serial, markingQr, safeMaker, safeModel, safeLine, safeLotNo, roundedVoltage, roundedCurrent, roundedResistance, result)); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,200 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Net.Sockets; |
|||
using System.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace marking_gui.Services |
|||
{ |
|||
/// <summary>
|
|||
/// TCP(LAN) 소켓을 사용하여 SCPI 계측기와 통신하는 클라이언트.
|
|||
/// Keysight DMM 34465A, Power Supply E36233A 등 LAN 장비에 사용합니다.
|
|||
/// </summary>
|
|||
public sealed class TcpScpiClient : IScpiClient, IDisposable |
|||
{ |
|||
private readonly string _host; |
|||
private readonly int _port; |
|||
private readonly int _timeoutMs; |
|||
private readonly string[] _idnMatches; |
|||
private readonly byte _terminator; |
|||
|
|||
private TcpClient _tcp; |
|||
private NetworkStream _stream; |
|||
private readonly SemaphoreSlim _networkLock = new SemaphoreSlim(1, 1); |
|||
private bool _disposed = false; |
|||
|
|||
public TcpScpiClient(string host, int port, int timeoutMs, string[] idnMatches, char terminator = '\n') |
|||
{ |
|||
_host = host; |
|||
_port = port; |
|||
_timeoutMs = timeoutMs; |
|||
_idnMatches = idnMatches ?? Array.Empty<string>(); |
|||
_terminator = (byte)terminator; |
|||
} |
|||
|
|||
// ── 연결 (필요 시 자동) ────────────────────────────────────────────
|
|||
private async Task EnsureConnectedAsync() |
|||
{ |
|||
if (_tcp != null && _tcp.Connected) return; |
|||
|
|||
await _networkLock.WaitAsync().ConfigureAwait(false); |
|||
try |
|||
{ |
|||
if (_tcp != null && _tcp.Connected) return; |
|||
|
|||
CleanUpSocket(); |
|||
_tcp = new TcpClient(); |
|||
_tcp.SendTimeout = _timeoutMs; |
|||
_tcp.ReceiveTimeout = _timeoutMs; |
|||
|
|||
// 연결 시도 시 CancellationToken을 사용해 OS 타임아웃 대기를 피함
|
|||
using (var cts = new CancellationTokenSource(_timeoutMs)) |
|||
{ |
|||
var connectTask = _tcp.ConnectAsync(_host, _port); |
|||
var delayTask = Task.Delay(_timeoutMs, cts.Token); |
|||
var completedTask = await Task.WhenAny(connectTask, delayTask).ConfigureAwait(false); |
|||
|
|||
if (completedTask == delayTask) |
|||
{ |
|||
CleanUpSocket(); |
|||
throw new TimeoutException($"SCPI 계측기 연결 대기 시간 초과 ({_host}:{_port})"); |
|||
} |
|||
|
|||
cts.Cancel(); // delayTask 취소
|
|||
await connectTask; // 예외 전파 확인
|
|||
} |
|||
|
|||
_stream = _tcp.GetStream(); |
|||
|
|||
// IDN 검증
|
|||
if (_idnMatches.Length > 0) |
|||
{ |
|||
string idn = await QueryRawAsync("*IDN?").ConfigureAwait(false); |
|||
bool matched = false; |
|||
foreach (var m in _idnMatches) |
|||
{ |
|||
if (!string.IsNullOrWhiteSpace(m) && |
|||
idn.IndexOf(m, StringComparison.OrdinalIgnoreCase) >= 0) |
|||
{ |
|||
matched = true; |
|||
break; |
|||
} |
|||
} |
|||
if (!matched) |
|||
throw new InvalidOperationException( |
|||
$"SCPI IDN 불일치: 기대=[{string.Join(",", _idnMatches)}] 실제=[{idn.Trim()}] ({_host}:{_port})"); |
|||
} |
|||
|
|||
LoggerService.Info($"[TcpScpi] 연결 완료 및 IDN 검증 성공: {_host}:{_port}"); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
CleanUpSocket(); |
|||
LoggerService.Error($"[TcpScpi] 연결 중 예외 발생: {_host}:{_port}", ex); |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
_networkLock.Release(); |
|||
} |
|||
} |
|||
|
|||
// ── IScpiClient ───────────────────────────────────────────────────
|
|||
public async Task SendAsync(string command) |
|||
{ |
|||
await EnsureConnectedAsync().ConfigureAwait(false); |
|||
await _networkLock.WaitAsync().ConfigureAwait(false); |
|||
try |
|||
{ |
|||
string trimmedCommand = (command ?? "").TrimEnd('\r', '\n'); |
|||
byte[] data = Encoding.ASCII.GetBytes(trimmedCommand + (char)_terminator); |
|||
await _stream.WriteAsync(data, 0, data.Length).ConfigureAwait(false); |
|||
await _stream.FlushAsync().ConfigureAwait(false); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
CleanUpSocket(); |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
_networkLock.Release(); |
|||
} |
|||
} |
|||
|
|||
public async Task<string> QueryAsync(string command) |
|||
{ |
|||
await EnsureConnectedAsync().ConfigureAwait(false); |
|||
await _networkLock.WaitAsync().ConfigureAwait(false); |
|||
try |
|||
{ |
|||
return await QueryRawAsync(command).ConfigureAwait(false); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
CleanUpSocket(); |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
_networkLock.Release(); |
|||
} |
|||
} |
|||
|
|||
private async Task<string> QueryRawAsync(string command) |
|||
{ |
|||
string trimmedCommand = (command ?? "").TrimEnd('\r', '\n'); |
|||
byte[] data = Encoding.ASCII.GetBytes(trimmedCommand + (char)_terminator); |
|||
await _stream.WriteAsync(data, 0, data.Length).ConfigureAwait(false); |
|||
await _stream.FlushAsync().ConfigureAwait(false); |
|||
|
|||
// 응답 수신 (터미네이터 LF가 검출될 때까지 안전하게 수신)
|
|||
using (var cts = new CancellationTokenSource(_timeoutMs)) |
|||
{ |
|||
var sb = new StringBuilder(); |
|||
var buf = new byte[1024]; |
|||
try |
|||
{ |
|||
while (true) |
|||
{ |
|||
int n = await _stream.ReadAsync(buf, 0, buf.Length, cts.Token).ConfigureAwait(false); |
|||
if (n == 0) break; |
|||
sb.Append(Encoding.ASCII.GetString(buf, 0, n)); |
|||
|
|||
// 버퍼의 마지막 바이트가 터미네이터(종단문자)인지 체크
|
|||
if (buf[n - 1] == _terminator) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
catch (OperationCanceledException) |
|||
{ |
|||
throw new TimeoutException($"SCPI 명령 '{trimmedCommand}' 응답 수신 타임아웃 ({_timeoutMs}ms) ({_host}:{_port})"); |
|||
} |
|||
|
|||
return sb.ToString(); |
|||
} |
|||
} |
|||
|
|||
private void CleanUpSocket() |
|||
{ |
|||
try { _stream?.Dispose(); } catch { } |
|||
try { _tcp?.Dispose(); } catch { } |
|||
_stream = null; |
|||
_tcp = null; |
|||
} |
|||
|
|||
// ── IDisposable ───────────────────────────────────────────────────
|
|||
public void Dispose() |
|||
{ |
|||
if (!_disposed) |
|||
{ |
|||
_disposed = true; |
|||
CleanUpSocket(); |
|||
_networkLock.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,113 @@ |
|||
; ================================================================= |
|||
; 성능 검사 모니터링 시스템 - 레이저 마킹기 연동 설정 파일 |
|||
; ================================================================= |
|||
|
|||
[Settings] |
|||
; 마킹 제어 라이브러리 및 드라이버(EzCad) 폴더 경로 |
|||
EzdFolderPath=c:\EzCad\EasyCfg |
|||
|
|||
; 테스트 모드 여부 (true 시 하단 테스트 마킹, 강제 검사 버튼 노출) |
|||
test=false |
|||
|
|||
; 도면품번 (EZD 도안의 도면품번 태그에 채워질 값 — DrawingNoTag에 매핑) |
|||
DrawingNo= |
|||
|
|||
; HKMC 품번 (EZD 도안의 HKMC 품번 태그에 채워질 값 — HkmcNoTag에 매핑) |
|||
HkmcNo= |
|||
|
|||
|
|||
[Tags] |
|||
; 도안(.ezd) 파일 내의 텍스트 오브젝트 치환용 태그명 매핑 리스트 |
|||
; (도안에 정의된 오브젝트명과 동일하게 설정해야 정상 작동합니다) |
|||
|
|||
; 일련번호 (Serial Number) 치환 태그 |
|||
SerialTag=SERIAL |
|||
|
|||
; 작업 년월일 (Lot No) 치환 태그 |
|||
LotNoTag=YYMMDD |
|||
|
|||
; 제품 모델명 (Product Name) 치환 태그 |
|||
ProductTag=PRODUCT |
|||
|
|||
; DMC 치환 태그 |
|||
QrCodeTag=QRCODETAG |
|||
|
|||
; 도면품번 치환 태그 (EZD 도안 내 도면품번 오브젝트명) |
|||
DrawingNoTag=DRAWING_NO |
|||
|
|||
; HKMC 품번 치환 태그 (EZD 도안 내 HKMC 품번 오브젝트명) |
|||
HkmcNoTag=HKMC_NO |
|||
|
|||
|
|||
; ================================================================= |
|||
; 계측기 연동 설정 (SCPI / LAN) |
|||
; ================================================================= |
|||
|
|||
[Equipment] |
|||
; 계측기 통신 타임아웃 (ms) |
|||
Timeout=5000 |
|||
|
|||
; 측정 안정화 대기 시간 (ms) — Power Supply ON 후 이 시간만큼 대기 후 읽음 |
|||
SettleMilliseconds=2000 |
|||
|
|||
; 검사 전 보드 전원 공급 커맨드 (세미콜론으로 구분) |
|||
PreBoardCommand=VOLT 5, (@2); CURR 2, (@2); OUTP ON, (@2) |
|||
PreBoardDelayMilliseconds=2000 |
|||
|
|||
; 로그아웃 시 전원 차단 커맨드 |
|||
LogoutCommand=OUTP OFF, (@1) |
|||
|
|||
|
|||
[DMM] |
|||
; Digital Multimeter — 전압(Voltage) 측정 전용 계측기 |
|||
VoltageConnection=LAN |
|||
VoltageHost=192.168.10.14 |
|||
VoltagePort=5025 |
|||
VoltageIdnMatch=34465A |
|||
VoltageBaudRate=115200 |
|||
VoltageTerminator=LF |
|||
VoltageSetupCommand= |
|||
VoltageReadCommand=MEAS:VOLT:DC? |
|||
|
|||
|
|||
[ResistanceDMM] |
|||
; Digital Multimeter — 저항(Resistance) 측정 전용 계측기 |
|||
ResistanceDMMConnection=LAN |
|||
ResistanceDMMHost=192.168.10.13 |
|||
ResistanceDMMPort=5025 |
|||
ResistanceDMMIdnMatch=34465A |
|||
ResistanceDMMBaudRate=115200 |
|||
ResistanceDMMTerminator=LF |
|||
ResistanceDMMReadCommand=MEAS:RES? |
|||
|
|||
|
|||
[PowerSupply] |
|||
; Power Supply — 전류(Current) 측정 및 상시전원(PreBoard)/테스트전원 출력 제어 |
|||
CurrentConnection=LAN |
|||
CurrentHost=192.168.10.15 |
|||
CurrentPort=5025 |
|||
CurrentIdnMatch=E36233A |
|||
CurrentBaudRate=9600 |
|||
CurrentTerminator=LF |
|||
CurrentSetupCommand=OUTP ON, (@1) |
|||
CurrentCleanupCommand=OUTP OFF, (@1) |
|||
CurrentReadCommand=MEAS:CURR? (@1) |
|||
|
|||
|
|||
; ================================================================= |
|||
; 계측 합격/불합격 판정 기준 범위 설정 (Limits) |
|||
; ================================================================= |
|||
|
|||
[Limits] |
|||
; 전압 판정 기준 범위 (V) |
|||
MinVoltage=1.00 |
|||
MaxVoltage=6.00 |
|||
|
|||
; 전류 판정 기준 범위 (mA) |
|||
MinCurrent=5.00 |
|||
MaxCurrent=10.00 |
|||
|
|||
; 저항 판정 기준 범위 (kΩ) |
|||
MinResistance=8.000 |
|||
MaxResistance=13.000 |
|||
|
|||
Binary file not shown.
@ -1,11 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<configuration> |
|||
<connectionStrings> |
|||
<add name="MssqlConnection" |
|||
connectionString="Server=localhost;Database=MarkingDb;Trusted_Connection=True;" |
|||
providerName="System.Data.SqlClient" /> |
|||
</connectionStrings> |
|||
<startup> |
|||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> |
|||
</startup> |
|||
</configuration> |
|||
Binary file not shown.
@ -1,125 +1,163 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{9E96D5BE-9375-4ED3-82DE-F200F83EBC2F}</ProjectGuid> |
|||
<OutputType>WinExe</OutputType> |
|||
<RootNamespace>marking_gui</RootNamespace> |
|||
<AssemblyName>marking_gui</AssemblyName> |
|||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> |
|||
<TargetFramework>net9.0-windows</TargetFramework> |
|||
<UseWPF>true</UseWPF> |
|||
<LangVersion>10.0</LangVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> |
|||
<WarningLevel>4</WarningLevel> |
|||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> |
|||
<Deterministic>true</Deterministic> |
|||
<!-- AssemblyInfo 중복 방지 설정 --> |
|||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> |
|||
|
|||
<!-- 32비트 런타임 및 아키텍처 고정 설정 --> |
|||
<PlatformTarget>x86</PlatformTarget> |
|||
<Platforms>AnyCPU;x86</Platforms> |
|||
|
|||
<!-- 응용 프로그램 아이콘 설정 --> |
|||
<ApplicationIcon>Marking.ico</ApplicationIcon> |
|||
|
|||
<!-- 단일 파일 배포 및 자립 실행(Self-Contained) 설정 --> |
|||
<PublishSingleFile>true</PublishSingleFile> |
|||
<SelfContained>true</SelfContained> |
|||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> |
|||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Xml" /> |
|||
<Reference Include="Microsoft.CSharp" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="System.Net.Http" /> |
|||
<Reference Include="System.Xaml"> |
|||
<RequiredTargetFramework>4.0</RequiredTargetFramework> |
|||
</Reference> |
|||
<Reference Include="WindowsBase" /> |
|||
<Reference Include="PresentationCore" /> |
|||
<Reference Include="PresentationFramework" /> |
|||
<Reference Include="System.Configuration" /> |
|||
<!-- .NET 9.0에 필요한 시리얼 통신 및 SQL 클라이언트 NuGet 패키지 추가 --> |
|||
<PackageReference Include="System.IO.Ports" Version="9.0.0" /> |
|||
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ApplicationDefinition Include="App.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
<SubType>Designer</SubType> |
|||
</ApplicationDefinition> |
|||
<Page Include="MainWindow.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
<SubType>Designer</SubType> |
|||
</Page> |
|||
<Page Include="SettingsWindow.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
<SubType>Designer</SubType> |
|||
</Page> |
|||
<Page Include="StartupLoginWindow.xaml"> |
|||
<Generator>MSBuild:Compile</Generator> |
|||
<SubType>Designer</SubType> |
|||
</Page> |
|||
<Compile Include="App.xaml.cs"> |
|||
<DependentUpon>App.xaml</DependentUpon> |
|||
<SubType>Code</SubType> |
|||
</Compile> |
|||
<Compile Include="MainWindow.xaml.cs"> |
|||
<DependentUpon>MainWindow.xaml</DependentUpon> |
|||
<SubType>Code</SubType> |
|||
</Compile> |
|||
<Compile Include="SettingsWindow.xaml.cs"> |
|||
<DependentUpon>SettingsWindow.xaml</DependentUpon> |
|||
<SubType>Code</SubType> |
|||
</Compile> |
|||
<Compile Include="StartupLoginWindow.xaml.cs"> |
|||
<DependentUpon>StartupLoginWindow.xaml</DependentUpon> |
|||
<SubType>Code</SubType> |
|||
</Compile> |
|||
<Compile Include="Models\Product.cs" /> |
|||
<Compile Include="Models\MeasurementLimits.cs" /> |
|||
<Compile Include="Services\MssqlDatabaseService.cs" /> |
|||
<Compile Include="Services\MockMeasurer.cs" /> |
|||
<Compile Include="Services\MemoryReaderService.cs" /> |
|||
<Compile Include="Services\LoginServicesStub.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="Properties\AssemblyInfo.cs"> |
|||
<SubType>Code</SubType> |
|||
</Compile> |
|||
<Compile Include="Properties\Resources.Designer.cs"> |
|||
<AutoGen>True</AutoGen> |
|||
<DesignTime>True</DesignTime> |
|||
<DependentUpon>Resources.resx</DependentUpon> |
|||
</Compile> |
|||
<Compile Include="Properties\Settings.Designer.cs"> |
|||
<AutoGen>True</AutoGen> |
|||
<DependentUpon>Settings.settings</DependentUpon> |
|||
<DesignTimeSharedInput>True</DesignTimeSharedInput> |
|||
</Compile> |
|||
<EmbeddedResource Include="Properties\Resources.resx"> |
|||
<Generator>ResXFileCodeGenerator</Generator> |
|||
<LastGenOutput>Resources.Designer.cs</LastGenOutput> |
|||
</EmbeddedResource> |
|||
<None Include="Properties\Settings.settings"> |
|||
<Generator>SettingsSingleFileGenerator</Generator> |
|||
<LastGenOutput>Settings.Designer.cs</LastGenOutput> |
|||
<Resource Include="Marking.ico" /> |
|||
<None Update="Database.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Include="App.config" /> |
|||
<None Include="Database.ini"> |
|||
<None Update="Setting.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="LoginOptions.json"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
|
|||
<!-- 빌드 후 EzCad DLL을 빌드 결과 디렉토리에 복사 (DLL은 libs 하위 폴더로 격리 복사) --> |
|||
<Target Name="CopyEzCadFiles" AfterTargets="Build"> |
|||
<ItemGroup> |
|||
<EzCadDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
</ItemGroup> |
|||
<MakeDir Directories="$(TargetDir)libs" Condition="!Exists('$(TargetDir)libs')" /> |
|||
<Copy SourceFiles="@(EzCadDlls)" DestinationFolder="$(TargetDir)libs\" SkipUnchangedFiles="true" /> |
|||
</Target> |
|||
|
|||
<!-- Publish 단계 완료 후 작동하는 EzCad 파일 복사 Target (libs 하위 폴더로 복사) --> |
|||
<Target Name="CopyEzCadFilesToPublish" AfterTargets="Publish"> |
|||
<ItemGroup> |
|||
<PublishEzCadDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
</ItemGroup> |
|||
<MakeDir Directories="$(PublishDir)libs" Condition="!Exists('$(PublishDir)libs')" /> |
|||
<Copy SourceFiles="@(PublishEzCadDlls)" DestinationFolder="$(PublishDir)libs\" SkipUnchangedFiles="true" /> |
|||
|
|||
<MakeDir Directories="$(TargetDir)publish\libs" Condition="!Exists('$(TargetDir)publish\libs')" /> |
|||
<Copy SourceFiles="@(PublishEzCadDlls)" DestinationFolder="$(TargetDir)publish\libs\" SkipUnchangedFiles="true" /> |
|||
</Target> |
|||
|
|||
<!-- C:\marking\ 설치 및 단일 설치 EXE(marking_setup.exe) 제작 전용 Target --> |
|||
<!-- C:\marking\ 설치 및 단일 설치 EXE(MarkingSetup.exe) 제작 전용 Target --> |
|||
<Target Name="FolderPublish" DependsOnTargets="Publish" AfterTargets="Publish"> |
|||
<PropertyGroup> |
|||
<!-- VS GUI에서 지정한 최종 게시 대상 경로 추출 (기본값은 C:\marking_setup\) --> |
|||
<TargetPublishDir Condition="'$(PublishDir)' != ''">$(PublishDir)</TargetPublishDir> |
|||
<TargetPublishDir Condition="'$(PublishDir)' == ''">C:\marking_setup\</TargetPublishDir> |
|||
|
|||
<DeployTargetFolder>C:\marking\</DeployTargetFolder> |
|||
<PublishBackupDir>$(MSBuildProjectDirectory)\bin\Release\net9.0-windows\win-x86\publish_backup\</PublishBackupDir> |
|||
</PropertyGroup> |
|||
<Message Text="Deploying clean publish output to $(DeployTargetFolder)..." Importance="high" /> |
|||
|
|||
<!-- 1. 기존 대상 디렉토리 클린업 및 재생성 (지저분한 기존 dll 파일들 소거, 실패 시 스킵) --> |
|||
<RemoveDir Directories="$(DeployTargetFolder)" ContinueOnError="true" /> |
|||
<MakeDir Directories="$(DeployTargetFolder)" /> |
|||
<MakeDir Directories="$(DeployTargetFolder)libs" /> |
|||
|
|||
<!-- 2. 실행 파일, 구성 파일 복사 (VS 게시 출력 폴더로부터 격리 복사) --> |
|||
<Copy SourceFiles="$(PublishDir)marking_gui.exe" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(TargetDir)marking_gui.dll.config" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
|
|||
<!-- 설정 파일 및 아이콘 복사 (프로젝트 소스 루트에서 직접 이관) --> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Database.ini" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Setting.ini" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\LoginOptions.json" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Marking.ico" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
|
|||
<!-- 3. 모든 DLL 라이브러리는 C:\marking\libs\ 폴더로 격리 복사 --> |
|||
<ItemGroup> |
|||
<EzCadSourceDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
<DeployLibFiles Include="$(PublishDir)libs\*.dll" /> |
|||
<TargetLibFiles Include="$(TargetDir)libs\*.dll" /> |
|||
</ItemGroup> |
|||
<Copy SourceFiles="@(EzCadSourceDlls)" DestinationFolder="$(DeployTargetFolder)libs\" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="@(DeployLibFiles)" DestinationFolder="$(DeployTargetFolder)libs\" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="@(TargetLibFiles)" DestinationFolder="$(DeployTargetFolder)libs\" SkipUnchangedFiles="true" /> |
|||
|
|||
<!-- [WiX Toolset 단일 MSI 설치 파일 자동 빌드 스텝] --> |
|||
<Message Text="Compiling single installer MSI via WiX Toolset..." Importance="high" /> |
|||
<Exec Command="wix build "$(MSBuildProjectDirectory)\..\marking_gui.Setup\Product.wxs" -o "$(DeployTargetFolder)MarkingSetup.msi"" WorkingDirectory="$(MSBuildProjectDirectory)" /> |
|||
|
|||
<!-- [WiX Toolset 단일 EXE 설치 파일 자동 빌드 스텝] --> |
|||
<Message Text="Compiling single installer EXE via WiX Toolset Bundle..." Importance="high" /> |
|||
<Exec Command="wix build "$(MSBuildProjectDirectory)\..\marking_gui.Setup\Bundle.wxs" -o "$(DeployTargetFolder)MarkingSetup.exe" -ext WixToolset.BootstrapperApplications.wixext/5.0.2" WorkingDirectory="$(MSBuildProjectDirectory)" /> |
|||
|
|||
<!-- 빌드 중간 산출물 .wixpdb 및 MSI 파일 정리 --> |
|||
<Delete Files="$(DeployTargetFolder)MarkingSetup.wixpdb" /> |
|||
<Delete Files="$(DeployTargetFolder)MarkingSetup.msi" /> |
|||
|
|||
<!-- 비주얼 스튜디오 게시 출력 폴더(TargetPublishDir 및 PublishDir) 정화 작업 --> |
|||
<Message Text="Purging publish output directories and leaving only MarkingSetup.exe..." Importance="high" /> |
|||
|
|||
<!-- 1. MarkingSetup.exe 파일을 임시 대피 경로로 복사 --> |
|||
<RemoveDir Directories="$(PublishBackupDir)" ContinueOnError="true" /> |
|||
<MakeDir Directories="$(PublishBackupDir)" /> |
|||
<Copy SourceFiles="$(DeployTargetFolder)MarkingSetup.exe" DestinationFolder="$(PublishBackupDir)" /> |
|||
|
|||
<!-- 2. 게시 폴더(TargetPublishDir 및 내부 PublishDir) 하위의 모든 자원 삭제 (dll, config, json, exe, libs 폴더 등) --> |
|||
<ItemGroup> |
|||
<FilesToClean Include="$(TargetPublishDir)*.dll" /> |
|||
<FilesToClean Include="$(TargetPublishDir)marking_gui.exe" /> |
|||
<FilesToClean Include="$(TargetPublishDir)marking_gui.pdb" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.config" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.json" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.pdb" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.ini" /> |
|||
|
|||
<!-- 내부 PublishDir 하위 찌꺼기 파일 클린업 (중요!) --> |
|||
<FilesToClean Include="$(PublishDir)*.dll" /> |
|||
<FilesToClean Include="$(PublishDir)marking_gui.exe" /> |
|||
<FilesToClean Include="$(PublishDir)marking_gui.pdb" /> |
|||
<FilesToClean Include="$(PublishDir)*.config" /> |
|||
<FilesToClean Include="$(PublishDir)*.json" /> |
|||
<FilesToClean Include="$(PublishDir)*.pdb" /> |
|||
<FilesToClean Include="$(PublishDir)*.ini" /> |
|||
</ItemGroup> |
|||
<Delete Files="@(FilesToClean)" ContinueOnError="true" /> |
|||
|
|||
<!-- libs 및 기타 번역 리소스 디렉토리 완전 소거 (TargetPublishDir 및 PublishDir 양쪽 모두) --> |
|||
<RemoveDir Directories="$(TargetPublishDir)libs" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(TargetPublishDir)cs;$(TargetPublishDir)de;$(TargetPublishDir)es;$(TargetPublishDir)fr;$(TargetPublishDir)it;$(TargetPublishDir)ja;$(TargetPublishDir)ko;$(TargetPublishDir)pl;$(TargetPublishDir)pt-BR;$(TargetPublishDir)ru;$(TargetPublishDir)tr;$(TargetPublishDir)zh-Hans;$(TargetPublishDir)zh-Hant" ContinueOnError="true" /> |
|||
|
|||
<RemoveDir Directories="$(PublishDir)libs" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(PublishDir)cs;$(PublishDir)de;$(PublishDir)es;$(PublishDir)fr;$(PublishDir)it;$(PublishDir)ja;$(PublishDir)ko;$(PublishDir)pl;$(PublishDir)pt-BR;$(PublishDir)ru;$(PublishDir)tr;$(PublishDir)zh-Hans;$(PublishDir)zh-Hant" ContinueOnError="true" /> |
|||
|
|||
<!-- 3. 대피시켰던 단일 설치 EXE 파일만 다시 게시 폴더(TargetPublishDir 및 PublishDir)로 원복 이관 --> |
|||
<Copy SourceFiles="$(PublishBackupDir)MarkingSetup.exe" DestinationFolder="$(TargetPublishDir)" /> |
|||
<Copy SourceFiles="$(PublishBackupDir)MarkingSetup.exe" DestinationFolder="$(PublishDir)" /> |
|||
|
|||
<!-- 4. 대피 임시 폴더 및 조립 폴더 C:\marking 삭제 정리 --> |
|||
<RemoveDir Directories="$(PublishBackupDir)" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(DeployTargetFolder)" ContinueOnError="true" /> |
|||
|
|||
<Message Text="Single Installer successfully compiled at both C:\marking\MarkingSetup.exe and $(TargetPublishDir)MarkingSetup.exe" Importance="high" /> |
|||
</Target> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,363 @@ |
|||
<Project> |
|||
<PropertyGroup> |
|||
<AssemblyName>marking_gui</AssemblyName> |
|||
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath> |
|||
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath> |
|||
<MSBuildProjectExtensionsPath>C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\</MSBuildProjectExtensionsPath> |
|||
<_TargetAssemblyProjectName>marking_gui</_TargetAssemblyProjectName> |
|||
<RootNamespace>marking_gui</RootNamespace> |
|||
</PropertyGroup> |
|||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> |
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>net9.0-windows</TargetFramework> |
|||
<UseWPF>true</UseWPF> |
|||
<LangVersion>10.0</LangVersion> |
|||
<Deterministic>true</Deterministic> |
|||
<!-- AssemblyInfo 중복 방지 설정 --> |
|||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> |
|||
<!-- 32비트 런타임 및 아키텍처 고정 설정 --> |
|||
<PlatformTarget>x86</PlatformTarget> |
|||
<Platforms>AnyCPU;x86</Platforms> |
|||
<!-- 단일 파일 배포 및 자립 실행(Self-Contained) 설정 --> |
|||
<PublishSingleFile>true</PublishSingleFile> |
|||
<SelfContained>true</SelfContained> |
|||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> |
|||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<!-- .NET 9.0에 필요한 시리얼 통신 및 SQL 클라이언트 NuGet 패키지 추가 --> |
|||
<PackageReference Include="System.IO.Ports" Version="9.0.0" /> |
|||
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Update="Database.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Setting.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
<!-- 빌드 후 EzCad DLL 및 EasyCfg 폴더를 빌드 결과 디렉토리에 복사 (DLL은 libs 하위 폴더로 격리 복사) --> |
|||
<Target Name="CopyEzCadFiles" AfterTargets="Build"> |
|||
<ItemGroup> |
|||
<EzCadDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
<EzCadEasyCfg Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\EasyCfg\**\*.*" /> |
|||
</ItemGroup> |
|||
<MakeDir Directories="$(TargetDir)libs" Condition="!Exists('$(TargetDir)libs')" /> |
|||
<Copy SourceFiles="@(EzCadDlls)" DestinationFolder="$(TargetDir)libs\" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="@(EzCadEasyCfg)" DestinationFiles="@(EzCadEasyCfg->'$(TargetDir)EasyCfg\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> |
|||
</Target> |
|||
<!-- Publish 단계 완료 후 작동하는 EzCad 파일 복사 Target (libs 하위 폴더로 복사) --> |
|||
<Target Name="CopyEzCadFilesToPublish" AfterTargets="Publish"> |
|||
<ItemGroup> |
|||
<PublishEzCadDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
</ItemGroup> |
|||
<MakeDir Directories="$(PublishDir)libs" Condition="!Exists('$(PublishDir)libs')" /> |
|||
<Copy SourceFiles="@(PublishEzCadDlls)" DestinationFolder="$(PublishDir)libs\" SkipUnchangedFiles="true" /> |
|||
<MakeDir Directories="$(TargetDir)publish\libs" Condition="!Exists('$(TargetDir)publish\libs')" /> |
|||
<Copy SourceFiles="@(PublishEzCadDlls)" DestinationFolder="$(TargetDir)publish\libs\" SkipUnchangedFiles="true" /> |
|||
</Target> |
|||
<!-- C:\marking\ 설치 및 단일 설치 EXE(marking_setup.exe) 제작 전용 Target --> |
|||
<!-- C:\marking\ 설치 및 단일 설치 EXE(MarkingSetup.exe) 제작 전용 Target --> |
|||
<Target Name="FolderPublish" DependsOnTargets="Publish" AfterTargets="Publish"> |
|||
<PropertyGroup> |
|||
<!-- VS GUI에서 지정한 최종 게시 대상 경로 추출 (기본값은 C:\marking_setup\) --> |
|||
<TargetPublishDir Condition="'$(PublishDir)' != ''">$(PublishDir)</TargetPublishDir> |
|||
<TargetPublishDir Condition="'$(PublishDir)' == ''">C:\marking_setup\</TargetPublishDir> |
|||
<DeployTargetFolder>C:\marking\</DeployTargetFolder> |
|||
<PublishBackupDir>$(MSBuildProjectDirectory)\bin\Release\net9.0-windows\win-x86\publish_backup\</PublishBackupDir> |
|||
</PropertyGroup> |
|||
<Message Text="Deploying clean publish output to $(DeployTargetFolder)..." Importance="high" /> |
|||
<!-- 1. 기존 대상 디렉토리 클린업 및 재생성 (지저분한 기존 dll 파일들 소거, 실패 시 스킵) --> |
|||
<RemoveDir Directories="$(DeployTargetFolder)" ContinueOnError="true" /> |
|||
<MakeDir Directories="$(DeployTargetFolder)" /> |
|||
<MakeDir Directories="$(DeployTargetFolder)libs" /> |
|||
<!-- 2. 실행 파일, 구성 파일 복사 (VS 게시 출력 폴더로부터 격리 복사) --> |
|||
<Copy SourceFiles="$(PublishDir)marking_gui.exe" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(TargetDir)marking_gui.dll.config" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<!-- 설정 파일 복사 (프로젝트 소스 루트에서 직접 이관) --> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Database.ini" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Setting.ini" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<!-- 3. 모든 DLL 라이브러리는 C:\marking\libs\ 폴더로 격리 복사 --> |
|||
<ItemGroup> |
|||
<DeployLibFiles Include="$(PublishDir)libs\*.dll" /> |
|||
</ItemGroup> |
|||
<Copy SourceFiles="@(DeployLibFiles)" DestinationFolder="$(DeployTargetFolder)libs\" SkipUnchangedFiles="true" /> |
|||
<!-- 4. EasyCfg 폴더 및 도안 파일 복사 --> |
|||
<ItemGroup> |
|||
<DeployEasyCfg Include="$(TargetDir)EasyCfg\**\*.*" /> |
|||
</ItemGroup> |
|||
<Copy SourceFiles="@(DeployEasyCfg)" DestinationFiles="@(DeployEasyCfg->'$(DeployTargetFolder)EasyCfg\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> |
|||
<!-- [WiX Toolset 단일 MSI 설치 파일 자동 빌드 스텝] --> |
|||
<Message Text="Compiling single installer MSI via WiX Toolset..." Importance="high" /> |
|||
<Exec Command="wix build "$(MSBuildProjectDirectory)\..\marking_gui.Setup\Product.wxs" -o "$(DeployTargetFolder)MarkingSetup.msi"" WorkingDirectory="$(MSBuildProjectDirectory)" /> |
|||
<!-- [WiX Toolset 단일 EXE 설치 파일 자동 빌드 스텝] --> |
|||
<Message Text="Compiling single installer EXE via WiX Toolset Bundle..." Importance="high" /> |
|||
<Exec Command="wix build "$(MSBuildProjectDirectory)\..\marking_gui.Setup\Bundle.wxs" -o "$(DeployTargetFolder)MarkingSetup.exe" -ext WixToolset.BootstrapperApplications.wixext/5.0.2" WorkingDirectory="$(MSBuildProjectDirectory)" /> |
|||
<!-- 빌드 중간 산출물 .wixpdb 및 MSI 파일 정리 --> |
|||
<Delete Files="$(DeployTargetFolder)MarkingSetup.wixpdb" /> |
|||
<Delete Files="$(DeployTargetFolder)MarkingSetup.msi" /> |
|||
<!-- 비주얼 스튜디오 게시 출력 폴더(TargetPublishDir 및 PublishDir) 정화 작업 --> |
|||
<Message Text="Purging publish output directories and leaving only MarkingSetup.exe..." Importance="high" /> |
|||
<!-- 1. MarkingSetup.exe 파일을 임시 대피 경로로 복사 --> |
|||
<RemoveDir Directories="$(PublishBackupDir)" ContinueOnError="true" /> |
|||
<MakeDir Directories="$(PublishBackupDir)" /> |
|||
<Copy SourceFiles="$(DeployTargetFolder)MarkingSetup.exe" DestinationFolder="$(PublishBackupDir)" /> |
|||
<!-- 2. 게시 폴더(TargetPublishDir 및 내부 PublishDir) 하위의 모든 자원 삭제 (dll, config, json, exe, libs 폴더 등) --> |
|||
<ItemGroup> |
|||
<FilesToClean Include="$(TargetPublishDir)*.dll" /> |
|||
<FilesToClean Include="$(TargetPublishDir)marking_gui.exe" /> |
|||
<FilesToClean Include="$(TargetPublishDir)marking_gui.pdb" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.config" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.json" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.pdb" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.ini" /> |
|||
<!-- 내부 PublishDir 하위 찌꺼기 파일 클린업 (중요!) --> |
|||
<FilesToClean Include="$(PublishDir)*.dll" /> |
|||
<FilesToClean Include="$(PublishDir)marking_gui.exe" /> |
|||
<FilesToClean Include="$(PublishDir)marking_gui.pdb" /> |
|||
<FilesToClean Include="$(PublishDir)*.config" /> |
|||
<FilesToClean Include="$(PublishDir)*.json" /> |
|||
<FilesToClean Include="$(PublishDir)*.pdb" /> |
|||
<FilesToClean Include="$(PublishDir)*.ini" /> |
|||
</ItemGroup> |
|||
<Delete Files="@(FilesToClean)" ContinueOnError="true" /> |
|||
<!-- libs 및 기타 번역 리소스 디렉토리 완전 소거 (TargetPublishDir 및 PublishDir 양쪽 모두) --> |
|||
<RemoveDir Directories="$(TargetPublishDir)libs" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(TargetPublishDir)cs;$(TargetPublishDir)de;$(TargetPublishDir)es;$(TargetPublishDir)fr;$(TargetPublishDir)it;$(TargetPublishDir)ja;$(TargetPublishDir)ko;$(TargetPublishDir)pl;$(TargetPublishDir)pt-BR;$(TargetPublishDir)ru;$(TargetPublishDir)tr;$(TargetPublishDir)zh-Hans;$(TargetPublishDir)zh-Hant" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(PublishDir)libs" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(PublishDir)cs;$(PublishDir)de;$(PublishDir)es;$(PublishDir)fr;$(PublishDir)it;$(PublishDir)ja;$(PublishDir)ko;$(PublishDir)pl;$(PublishDir)pt-BR;$(PublishDir)ru;$(PublishDir)tr;$(PublishDir)zh-Hans;$(PublishDir)zh-Hant" ContinueOnError="true" /> |
|||
<!-- 3. 대피시켰던 단일 설치 EXE 파일만 다시 게시 폴더(TargetPublishDir 및 PublishDir)로 원복 이관 --> |
|||
<Copy SourceFiles="$(PublishBackupDir)MarkingSetup.exe" DestinationFolder="$(TargetPublishDir)" /> |
|||
<Copy SourceFiles="$(PublishBackupDir)MarkingSetup.exe" DestinationFolder="$(PublishDir)" /> |
|||
<!-- 4. 대피 임시 폴더 및 조립 폴더 C:\marking 삭제 정리 --> |
|||
<RemoveDir Directories="$(PublishBackupDir)" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(DeployTargetFolder)" ContinueOnError="true" /> |
|||
<Message Text="Single Installer successfully compiled at both C:\marking\MarkingSetup.exe and $(TargetPublishDir)MarkingSetup.exe" Importance="high" /> |
|||
</Target> |
|||
<ItemGroup> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\Accessibility.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.CSharp.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.VisualBasic.Core.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.VisualBasic.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.Registry.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.Registry.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.SystemEvents.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\mscorlib.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\netstandard.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationCore.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Aero.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Aero2.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.AeroLite.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Classic.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Luna.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Royale.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationUI.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\ReachFramework.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.AppContext.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Buffers.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.CodeDom.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.Concurrent.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.Immutable.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.NonGeneric.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.Specialized.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.Annotations.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.DataAnnotations.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.EventBasedAsync.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.TypeConverter.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Configuration.ConfigurationManager.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Configuration.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Console.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Core.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Data.Common.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Data.DataSetExtensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Data.dll" /> |
|||
<ReferencePath Include="C:\Users\COMPUTER1\.nuget\packages\system.data.sqlclient\4.9.0\lib\net8.0\System.Data.SqlClient.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Contracts.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Debug.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.DiagnosticSource.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.EventLog.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.FileVersionInfo.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.PerformanceCounter.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Process.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.StackTrace.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.TextWriterTraceListener.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Tools.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.TraceSource.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Tracing.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.DirectoryServices.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Drawing.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Drawing.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Dynamic.Runtime.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Formats.Asn1.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Formats.Nrbf.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Formats.Tar.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Globalization.Calendars.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Globalization.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Globalization.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.Brotli.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.FileSystem.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.ZipFile.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.DriveInfo.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.Watcher.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.IsolatedStorage.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.MemoryMappedFiles.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.IO.Packaging.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Pipelines.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Pipes.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Pipes.dll" /> |
|||
<ReferencePath Include="C:\Users\COMPUTER1\.nuget\packages\system.io.ports\9.0.0\lib\net9.0\System.IO.Ports.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.UnmanagedMemoryStream.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.Expressions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.Parallel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.Queryable.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Memory.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Http.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Http.Json.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.HttpListener.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Mail.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.NameResolution.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.NetworkInformation.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Ping.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Quic.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Requests.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Security.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.ServicePoint.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Sockets.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebClient.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebHeaderCollection.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebProxy.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebSockets.Client.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebSockets.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Numerics.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Numerics.Vectors.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ObjectModel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Printing.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.DispatchProxy.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Emit.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Emit.ILGeneration.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Emit.Lightweight.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Metadata.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.TypeExtensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Resources.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Resources.Reader.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Resources.ResourceManager.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Resources.Writer.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.CompilerServices.Unsafe.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.CompilerServices.VisualC.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Handles.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.InteropServices.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.InteropServices.JavaScript.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.InteropServices.RuntimeInformation.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Intrinsics.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Loader.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Numerics.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Formatters.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Json.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Xml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Claims.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Algorithms.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Cng.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Csp.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Encoding.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.OpenSsl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Pkcs.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.ProtectedData.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.X509Certificates.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Xml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Permissions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Principal.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Principal.Windows.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.SecureString.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ServiceModel.Web.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ServiceProcess.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encoding.CodePages.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encoding.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encoding.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encodings.Web.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Json.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.RegularExpressions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Threading.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Channels.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Overlapped.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.Dataflow.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.Parallel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Thread.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.ThreadPool.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Timer.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Transactions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Transactions.Local.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ValueTuple.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Web.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Web.HttpUtility.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Controls.Ribbon.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Windows.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Input.Manipulations.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Presentation.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Xaml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.Linq.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.ReaderWriter.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.Serialization.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XDocument.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XmlDocument.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XmlSerializer.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XPath.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XPath.XDocument.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationClient.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationClientSideProviders.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationProvider.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationTypes.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\WindowsBase.dll" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\MainWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\PortSettingsWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\SettingsWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\StartupLoginWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\App.g.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Analyzer Include="C:\Program Files\dotnet\sdk\10.0.301\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\sdk\10.0.301\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.NetAnalyzers.dll" /> |
|||
<Analyzer Include="C:\Users\COMPUTER1\.nuget\packages\microsoft.net.illink.tasks\9.0.17\analyzers\dotnet\cs\ILLink.CodeFixProvider.dll" /> |
|||
<Analyzer Include="C:\Users\COMPUTER1\.nuget\packages\microsoft.net.illink.tasks\9.0.17\analyzers\dotnet\cs\ILLink.RoslynAnalyzer.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.ComInterfaceGenerator.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.JavaScript.JSImportGenerator.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.LibraryImportGenerator.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.SourceGeneration.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/System.Text.Json.SourceGeneration.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/System.Text.RegularExpressions.Generator.dll" /> |
|||
</ItemGroup> |
|||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> |
|||
</Project> |
|||
Binary file not shown.
@ -0,0 +1,363 @@ |
|||
<Project> |
|||
<PropertyGroup> |
|||
<AssemblyName>marking_gui</AssemblyName> |
|||
<IntermediateOutputPath>obj\Debug\</IntermediateOutputPath> |
|||
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath> |
|||
<MSBuildProjectExtensionsPath>C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\</MSBuildProjectExtensionsPath> |
|||
<_TargetAssemblyProjectName>marking_gui</_TargetAssemblyProjectName> |
|||
<RootNamespace>marking_gui</RootNamespace> |
|||
</PropertyGroup> |
|||
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /> |
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>net9.0-windows</TargetFramework> |
|||
<UseWPF>true</UseWPF> |
|||
<LangVersion>10.0</LangVersion> |
|||
<Deterministic>true</Deterministic> |
|||
<!-- AssemblyInfo 중복 방지 설정 --> |
|||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> |
|||
<!-- 32비트 런타임 및 아키텍처 고정 설정 --> |
|||
<PlatformTarget>x86</PlatformTarget> |
|||
<Platforms>AnyCPU;x86</Platforms> |
|||
<!-- 단일 파일 배포 및 자립 실행(Self-Contained) 설정 --> |
|||
<PublishSingleFile>true</PublishSingleFile> |
|||
<SelfContained>true</SelfContained> |
|||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> |
|||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<!-- .NET 9.0에 필요한 시리얼 통신 및 SQL 클라이언트 NuGet 패키지 추가 --> |
|||
<PackageReference Include="System.IO.Ports" Version="9.0.0" /> |
|||
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Update="Database.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Setting.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
<!-- 빌드 후 EzCad DLL 및 EasyCfg 폴더를 빌드 결과 디렉토리에 복사 (DLL은 libs 하위 폴더로 격리 복사) --> |
|||
<Target Name="CopyEzCadFiles" AfterTargets="Build"> |
|||
<ItemGroup> |
|||
<EzCadDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
<EzCadEasyCfg Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\EasyCfg\**\*.*" /> |
|||
</ItemGroup> |
|||
<MakeDir Directories="$(TargetDir)libs" Condition="!Exists('$(TargetDir)libs')" /> |
|||
<Copy SourceFiles="@(EzCadDlls)" DestinationFolder="$(TargetDir)libs\" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="@(EzCadEasyCfg)" DestinationFiles="@(EzCadEasyCfg->'$(TargetDir)EasyCfg\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> |
|||
</Target> |
|||
<!-- Publish 단계 완료 후 작동하는 EzCad 파일 복사 Target (libs 하위 폴더로 복사) --> |
|||
<Target Name="CopyEzCadFilesToPublish" AfterTargets="Publish"> |
|||
<ItemGroup> |
|||
<PublishEzCadDlls Include="C:\Users\COMPUTER1\Desktop\mobi\marking\EzCad\*.dll" /> |
|||
</ItemGroup> |
|||
<MakeDir Directories="$(PublishDir)libs" Condition="!Exists('$(PublishDir)libs')" /> |
|||
<Copy SourceFiles="@(PublishEzCadDlls)" DestinationFolder="$(PublishDir)libs\" SkipUnchangedFiles="true" /> |
|||
<MakeDir Directories="$(TargetDir)publish\libs" Condition="!Exists('$(TargetDir)publish\libs')" /> |
|||
<Copy SourceFiles="@(PublishEzCadDlls)" DestinationFolder="$(TargetDir)publish\libs\" SkipUnchangedFiles="true" /> |
|||
</Target> |
|||
<!-- C:\marking\ 설치 및 단일 설치 EXE(marking_setup.exe) 제작 전용 Target --> |
|||
<!-- C:\marking\ 설치 및 단일 설치 EXE(MarkingSetup.exe) 제작 전용 Target --> |
|||
<Target Name="FolderPublish" DependsOnTargets="Publish" AfterTargets="Publish"> |
|||
<PropertyGroup> |
|||
<!-- VS GUI에서 지정한 최종 게시 대상 경로 추출 (기본값은 C:\marking_setup\) --> |
|||
<TargetPublishDir Condition="'$(PublishDir)' != ''">$(PublishDir)</TargetPublishDir> |
|||
<TargetPublishDir Condition="'$(PublishDir)' == ''">C:\marking_setup\</TargetPublishDir> |
|||
<DeployTargetFolder>C:\marking\</DeployTargetFolder> |
|||
<PublishBackupDir>$(MSBuildProjectDirectory)\bin\Release\net9.0-windows\win-x86\publish_backup\</PublishBackupDir> |
|||
</PropertyGroup> |
|||
<Message Text="Deploying clean publish output to $(DeployTargetFolder)..." Importance="high" /> |
|||
<!-- 1. 기존 대상 디렉토리 클린업 및 재생성 (지저분한 기존 dll 파일들 소거, 실패 시 스킵) --> |
|||
<RemoveDir Directories="$(DeployTargetFolder)" ContinueOnError="true" /> |
|||
<MakeDir Directories="$(DeployTargetFolder)" /> |
|||
<MakeDir Directories="$(DeployTargetFolder)libs" /> |
|||
<!-- 2. 실행 파일, 구성 파일 복사 (VS 게시 출력 폴더로부터 격리 복사) --> |
|||
<Copy SourceFiles="$(PublishDir)marking_gui.exe" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(TargetDir)marking_gui.dll.config" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<!-- 설정 파일 복사 (프로젝트 소스 루트에서 직접 이관) --> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Database.ini" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<Copy SourceFiles="$(MSBuildProjectDirectory)\Setting.ini" DestinationFolder="$(DeployTargetFolder)" SkipUnchangedFiles="true" /> |
|||
<!-- 3. 모든 DLL 라이브러리는 C:\marking\libs\ 폴더로 격리 복사 --> |
|||
<ItemGroup> |
|||
<DeployLibFiles Include="$(PublishDir)libs\*.dll" /> |
|||
</ItemGroup> |
|||
<Copy SourceFiles="@(DeployLibFiles)" DestinationFolder="$(DeployTargetFolder)libs\" SkipUnchangedFiles="true" /> |
|||
<!-- 4. EasyCfg 폴더 및 도안 파일 복사 --> |
|||
<ItemGroup> |
|||
<DeployEasyCfg Include="$(TargetDir)EasyCfg\**\*.*" /> |
|||
</ItemGroup> |
|||
<Copy SourceFiles="@(DeployEasyCfg)" DestinationFiles="@(DeployEasyCfg->'$(DeployTargetFolder)EasyCfg\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" /> |
|||
<!-- [WiX Toolset 단일 MSI 설치 파일 자동 빌드 스텝] --> |
|||
<Message Text="Compiling single installer MSI via WiX Toolset..." Importance="high" /> |
|||
<Exec Command="wix build "$(MSBuildProjectDirectory)\..\marking_gui.Setup\Product.wxs" -o "$(DeployTargetFolder)MarkingSetup.msi"" WorkingDirectory="$(MSBuildProjectDirectory)" /> |
|||
<!-- [WiX Toolset 단일 EXE 설치 파일 자동 빌드 스텝] --> |
|||
<Message Text="Compiling single installer EXE via WiX Toolset Bundle..." Importance="high" /> |
|||
<Exec Command="wix build "$(MSBuildProjectDirectory)\..\marking_gui.Setup\Bundle.wxs" -o "$(DeployTargetFolder)MarkingSetup.exe" -ext WixToolset.BootstrapperApplications.wixext/5.0.2" WorkingDirectory="$(MSBuildProjectDirectory)" /> |
|||
<!-- 빌드 중간 산출물 .wixpdb 및 MSI 파일 정리 --> |
|||
<Delete Files="$(DeployTargetFolder)MarkingSetup.wixpdb" /> |
|||
<Delete Files="$(DeployTargetFolder)MarkingSetup.msi" /> |
|||
<!-- 비주얼 스튜디오 게시 출력 폴더(TargetPublishDir 및 PublishDir) 정화 작업 --> |
|||
<Message Text="Purging publish output directories and leaving only MarkingSetup.exe..." Importance="high" /> |
|||
<!-- 1. MarkingSetup.exe 파일을 임시 대피 경로로 복사 --> |
|||
<RemoveDir Directories="$(PublishBackupDir)" ContinueOnError="true" /> |
|||
<MakeDir Directories="$(PublishBackupDir)" /> |
|||
<Copy SourceFiles="$(DeployTargetFolder)MarkingSetup.exe" DestinationFolder="$(PublishBackupDir)" /> |
|||
<!-- 2. 게시 폴더(TargetPublishDir 및 내부 PublishDir) 하위의 모든 자원 삭제 (dll, config, json, exe, libs 폴더 등) --> |
|||
<ItemGroup> |
|||
<FilesToClean Include="$(TargetPublishDir)*.dll" /> |
|||
<FilesToClean Include="$(TargetPublishDir)marking_gui.exe" /> |
|||
<FilesToClean Include="$(TargetPublishDir)marking_gui.pdb" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.config" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.json" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.pdb" /> |
|||
<FilesToClean Include="$(TargetPublishDir)*.ini" /> |
|||
<!-- 내부 PublishDir 하위 찌꺼기 파일 클린업 (중요!) --> |
|||
<FilesToClean Include="$(PublishDir)*.dll" /> |
|||
<FilesToClean Include="$(PublishDir)marking_gui.exe" /> |
|||
<FilesToClean Include="$(PublishDir)marking_gui.pdb" /> |
|||
<FilesToClean Include="$(PublishDir)*.config" /> |
|||
<FilesToClean Include="$(PublishDir)*.json" /> |
|||
<FilesToClean Include="$(PublishDir)*.pdb" /> |
|||
<FilesToClean Include="$(PublishDir)*.ini" /> |
|||
</ItemGroup> |
|||
<Delete Files="@(FilesToClean)" ContinueOnError="true" /> |
|||
<!-- libs 및 기타 번역 리소스 디렉토리 완전 소거 (TargetPublishDir 및 PublishDir 양쪽 모두) --> |
|||
<RemoveDir Directories="$(TargetPublishDir)libs" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(TargetPublishDir)cs;$(TargetPublishDir)de;$(TargetPublishDir)es;$(TargetPublishDir)fr;$(TargetPublishDir)it;$(TargetPublishDir)ja;$(TargetPublishDir)ko;$(TargetPublishDir)pl;$(TargetPublishDir)pt-BR;$(TargetPublishDir)ru;$(TargetPublishDir)tr;$(TargetPublishDir)zh-Hans;$(TargetPublishDir)zh-Hant" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(PublishDir)libs" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(PublishDir)cs;$(PublishDir)de;$(PublishDir)es;$(PublishDir)fr;$(PublishDir)it;$(PublishDir)ja;$(PublishDir)ko;$(PublishDir)pl;$(PublishDir)pt-BR;$(PublishDir)ru;$(PublishDir)tr;$(PublishDir)zh-Hans;$(PublishDir)zh-Hant" ContinueOnError="true" /> |
|||
<!-- 3. 대피시켰던 단일 설치 EXE 파일만 다시 게시 폴더(TargetPublishDir 및 PublishDir)로 원복 이관 --> |
|||
<Copy SourceFiles="$(PublishBackupDir)MarkingSetup.exe" DestinationFolder="$(TargetPublishDir)" /> |
|||
<Copy SourceFiles="$(PublishBackupDir)MarkingSetup.exe" DestinationFolder="$(PublishDir)" /> |
|||
<!-- 4. 대피 임시 폴더 및 조립 폴더 C:\marking 삭제 정리 --> |
|||
<RemoveDir Directories="$(PublishBackupDir)" ContinueOnError="true" /> |
|||
<RemoveDir Directories="$(DeployTargetFolder)" ContinueOnError="true" /> |
|||
<Message Text="Single Installer successfully compiled at both C:\marking\MarkingSetup.exe and $(TargetPublishDir)MarkingSetup.exe" Importance="high" /> |
|||
</Target> |
|||
<ItemGroup> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\Accessibility.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.CSharp.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.VisualBasic.Core.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.VisualBasic.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.Registry.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.Registry.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\Microsoft.Win32.SystemEvents.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\mscorlib.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\netstandard.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationCore.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Aero.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Aero2.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.AeroLite.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Classic.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Luna.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationFramework.Royale.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\PresentationUI.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\ReachFramework.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.AppContext.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Buffers.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.CodeDom.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.Concurrent.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.Immutable.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.NonGeneric.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Collections.Specialized.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.Annotations.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.DataAnnotations.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.EventBasedAsync.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ComponentModel.TypeConverter.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Configuration.ConfigurationManager.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Configuration.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Console.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Core.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Data.Common.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Data.DataSetExtensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Data.dll" /> |
|||
<ReferencePath Include="C:\Users\COMPUTER1\.nuget\packages\system.data.sqlclient\4.9.0\lib\net8.0\System.Data.SqlClient.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Contracts.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Debug.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.DiagnosticSource.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.EventLog.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.FileVersionInfo.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.PerformanceCounter.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Process.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.StackTrace.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.TextWriterTraceListener.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Tools.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.TraceSource.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Diagnostics.Tracing.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.DirectoryServices.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Drawing.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Drawing.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Dynamic.Runtime.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Formats.Asn1.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Formats.Nrbf.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Formats.Tar.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Globalization.Calendars.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Globalization.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Globalization.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.Brotli.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.FileSystem.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Compression.ZipFile.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.DriveInfo.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.FileSystem.Watcher.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.IsolatedStorage.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.MemoryMappedFiles.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.IO.Packaging.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Pipelines.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Pipes.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.Pipes.dll" /> |
|||
<ReferencePath Include="C:\Users\COMPUTER1\.nuget\packages\system.io.ports\9.0.0\lib\net9.0\System.IO.Ports.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.IO.UnmanagedMemoryStream.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.Expressions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.Parallel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Linq.Queryable.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Memory.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Http.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Http.Json.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.HttpListener.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Mail.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.NameResolution.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.NetworkInformation.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Ping.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Quic.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Requests.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Security.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.ServicePoint.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.Sockets.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebClient.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebHeaderCollection.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebProxy.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebSockets.Client.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Net.WebSockets.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Numerics.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Numerics.Vectors.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ObjectModel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Printing.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.DispatchProxy.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Emit.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Emit.ILGeneration.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Emit.Lightweight.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Metadata.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Reflection.TypeExtensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Resources.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Resources.Reader.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Resources.ResourceManager.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Resources.Writer.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.CompilerServices.Unsafe.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.CompilerServices.VisualC.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Handles.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.InteropServices.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.InteropServices.JavaScript.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.InteropServices.RuntimeInformation.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Intrinsics.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Loader.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Numerics.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Formatters.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Json.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Runtime.Serialization.Xml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Claims.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Algorithms.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Cng.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Csp.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Encoding.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.OpenSsl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Pkcs.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Primitives.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.ProtectedData.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.X509Certificates.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Cryptography.Xml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Security.Permissions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Principal.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.Principal.Windows.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Security.SecureString.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ServiceModel.Web.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ServiceProcess.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encoding.CodePages.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encoding.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encoding.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Encodings.Web.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.Json.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Text.RegularExpressions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Threading.AccessControl.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Channels.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Overlapped.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.Dataflow.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Tasks.Parallel.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Thread.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.ThreadPool.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Threading.Timer.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Transactions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Transactions.Local.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.ValueTuple.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Web.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Web.HttpUtility.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Controls.Ribbon.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Windows.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Extensions.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Input.Manipulations.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Windows.Presentation.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\System.Xaml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.Linq.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.ReaderWriter.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.Serialization.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XDocument.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XmlDocument.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XmlSerializer.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XPath.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\ref\net9.0\System.Xml.XPath.XDocument.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationClient.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationClientSideProviders.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationProvider.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\UIAutomationTypes.dll" /> |
|||
<ReferencePath Include="C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\9.0.17\ref\net9.0\WindowsBase.dll" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\MainWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\PortSettingsWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\SettingsWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\StartupLoginWindow.g.cs" /> |
|||
<Compile Include="C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\net9.0-windows\win-x86\App.g.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Analyzer Include="C:\Program Files\dotnet\sdk\10.0.301\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\sdk\10.0.301\Sdks\Microsoft.NET.Sdk\targets\..\analyzers\Microsoft.CodeAnalysis.NetAnalyzers.dll" /> |
|||
<Analyzer Include="C:\Users\COMPUTER1\.nuget\packages\microsoft.net.illink.tasks\9.0.17\analyzers\dotnet\cs\ILLink.CodeFixProvider.dll" /> |
|||
<Analyzer Include="C:\Users\COMPUTER1\.nuget\packages\microsoft.net.illink.tasks\9.0.17\analyzers\dotnet\cs\ILLink.RoslynAnalyzer.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.ComInterfaceGenerator.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.JavaScript.JSImportGenerator.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.LibraryImportGenerator.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/Microsoft.Interop.SourceGeneration.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/System.Text.Json.SourceGeneration.dll" /> |
|||
<Analyzer Include="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\9.0.17\analyzers/dotnet/cs/System.Text.RegularExpressions.Generator.dll" /> |
|||
</ItemGroup> |
|||
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /> |
|||
</Project> |
|||
@ -1,4 +0,0 @@ |
|||
// <autogenerated />
|
|||
using System; |
|||
using System.Reflection; |
|||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] |
|||
Binary file not shown.
@ -1,77 +0,0 @@ |
|||
#pragma checksum "..\..\App.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "7901E81250AFB6085C580D5F91E3114E104640F12456214E674506A1451A61E4"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
using marking_gui; |
|||
|
|||
|
|||
namespace marking_gui { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// App
|
|||
/// </summary>
|
|||
public partial class App : System.Windows.Application { |
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/app.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\App.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Application Entry Point.
|
|||
/// </summary>
|
|||
[System.STAThreadAttribute()] |
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public static void Main() { |
|||
marking_gui.App app = new marking_gui.App(); |
|||
app.InitializeComponent(); |
|||
app.Run(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,77 +0,0 @@ |
|||
#pragma checksum "..\..\App.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "7901E81250AFB6085C580D5F91E3114E104640F12456214E674506A1451A61E4"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
using marking_gui; |
|||
|
|||
|
|||
namespace marking_gui { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// App
|
|||
/// </summary>
|
|||
public partial class App : System.Windows.Application { |
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/app.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\App.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Application Entry Point.
|
|||
/// </summary>
|
|||
[System.STAThreadAttribute()] |
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public static void Main() { |
|||
marking_gui.App app = new marking_gui.App(); |
|||
app.InitializeComponent(); |
|||
app.Run(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
Binary file not shown.
Binary file not shown.
@ -1,387 +0,0 @@ |
|||
#pragma checksum "..\..\MainWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "AD4A4C06745EFEC612E5A40E8825C3B16CE481532342C19F0C009E1B56E7E5F4"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
using marking_gui; |
|||
|
|||
|
|||
namespace marking_gui { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// MainWindow
|
|||
/// </summary>
|
|||
public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { |
|||
|
|||
|
|||
#line 138 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtCurrentTime; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 139 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtSystemStatus; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 146 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtOperatorInfo; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 153 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtModelInfo; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 160 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtLineInfo; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 163 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnLogout; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 170 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnMaximize; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 171 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtMaximizeIcon; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 201 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtSerial; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 232 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtPrevHousing; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 243 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtPrevCal; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 254 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtPrevEol; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 289 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtVoltage; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 293 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtVoltageRangeGuide; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 308 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtCurrent; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 312 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtCurrentRangeGuide; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 327 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtResistance; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 331 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtResistanceRangeGuide; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 337 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Border borderFinalResult; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 346 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtFinalResult; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 347 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtFinalSerial; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 357 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnStart; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 366 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnOpenSettings; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/mainwindow.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\MainWindow.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
|||
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { |
|||
switch (connectionId) |
|||
{ |
|||
case 1: |
|||
|
|||
#line 11 "..\..\MainWindow.xaml"
|
|||
((marking_gui.MainWindow)(target)).ContentRendered += new System.EventHandler(this.Window_ContentRendered); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 2: |
|||
|
|||
#line 129 "..\..\MainWindow.xaml"
|
|||
((System.Windows.Controls.Border)(target)).MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(this.TopBar_MouseLeftButtonDown); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 3: |
|||
this.txtCurrentTime = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 4: |
|||
this.txtSystemStatus = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 5: |
|||
this.txtOperatorInfo = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 6: |
|||
this.txtModelInfo = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 7: |
|||
this.txtLineInfo = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 8: |
|||
this.btnLogout = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 163 "..\..\MainWindow.xaml"
|
|||
this.btnLogout.Click += new System.Windows.RoutedEventHandler(this.btnLogout_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 9: |
|||
|
|||
#line 167 "..\..\MainWindow.xaml"
|
|||
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.BtnMinimize_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 10: |
|||
this.btnMaximize = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 170 "..\..\MainWindow.xaml"
|
|||
this.btnMaximize.Click += new System.Windows.RoutedEventHandler(this.BtnMaximize_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 11: |
|||
this.txtMaximizeIcon = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 12: |
|||
|
|||
#line 173 "..\..\MainWindow.xaml"
|
|||
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.BtnClose_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 13: |
|||
this.txtSerial = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 14: |
|||
this.txtPrevHousing = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 15: |
|||
this.txtPrevCal = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 16: |
|||
this.txtPrevEol = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 17: |
|||
this.txtVoltage = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 18: |
|||
this.txtVoltageRangeGuide = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 19: |
|||
this.txtCurrent = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 20: |
|||
this.txtCurrentRangeGuide = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 21: |
|||
this.txtResistance = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 22: |
|||
this.txtResistanceRangeGuide = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 23: |
|||
this.borderFinalResult = ((System.Windows.Controls.Border)(target)); |
|||
return; |
|||
case 24: |
|||
this.txtFinalResult = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 25: |
|||
this.txtFinalSerial = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 26: |
|||
this.btnStart = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 358 "..\..\MainWindow.xaml"
|
|||
this.btnStart.Click += new System.Windows.RoutedEventHandler(this.btnStart_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 27: |
|||
this.btnOpenSettings = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 367 "..\..\MainWindow.xaml"
|
|||
this.btnOpenSettings.Click += new System.Windows.RoutedEventHandler(this.btnOpenSettings_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
} |
|||
this._contentLoaded = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,387 +0,0 @@ |
|||
#pragma checksum "..\..\MainWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "AD4A4C06745EFEC612E5A40E8825C3B16CE481532342C19F0C009E1B56E7E5F4"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
using marking_gui; |
|||
|
|||
|
|||
namespace marking_gui { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// MainWindow
|
|||
/// </summary>
|
|||
public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { |
|||
|
|||
|
|||
#line 138 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtCurrentTime; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 139 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtSystemStatus; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 146 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtOperatorInfo; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 153 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtModelInfo; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 160 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtLineInfo; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 163 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnLogout; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 170 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnMaximize; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 171 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtMaximizeIcon; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 201 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtSerial; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 232 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtPrevHousing; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 243 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtPrevCal; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 254 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtPrevEol; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 289 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtVoltage; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 293 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtVoltageRangeGuide; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 308 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtCurrent; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 312 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtCurrentRangeGuide; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 327 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtResistance; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 331 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtResistanceRangeGuide; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 337 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Border borderFinalResult; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 346 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtFinalResult; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 347 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBlock txtFinalSerial; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 357 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnStart; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 366 "..\..\MainWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnOpenSettings; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/mainwindow.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\MainWindow.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
|||
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { |
|||
switch (connectionId) |
|||
{ |
|||
case 1: |
|||
|
|||
#line 11 "..\..\MainWindow.xaml"
|
|||
((marking_gui.MainWindow)(target)).ContentRendered += new System.EventHandler(this.Window_ContentRendered); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 2: |
|||
|
|||
#line 129 "..\..\MainWindow.xaml"
|
|||
((System.Windows.Controls.Border)(target)).MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(this.TopBar_MouseLeftButtonDown); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 3: |
|||
this.txtCurrentTime = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 4: |
|||
this.txtSystemStatus = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 5: |
|||
this.txtOperatorInfo = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 6: |
|||
this.txtModelInfo = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 7: |
|||
this.txtLineInfo = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 8: |
|||
this.btnLogout = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 163 "..\..\MainWindow.xaml"
|
|||
this.btnLogout.Click += new System.Windows.RoutedEventHandler(this.btnLogout_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 9: |
|||
|
|||
#line 167 "..\..\MainWindow.xaml"
|
|||
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.BtnMinimize_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 10: |
|||
this.btnMaximize = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 170 "..\..\MainWindow.xaml"
|
|||
this.btnMaximize.Click += new System.Windows.RoutedEventHandler(this.BtnMaximize_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 11: |
|||
this.txtMaximizeIcon = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 12: |
|||
|
|||
#line 173 "..\..\MainWindow.xaml"
|
|||
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.BtnClose_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 13: |
|||
this.txtSerial = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 14: |
|||
this.txtPrevHousing = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 15: |
|||
this.txtPrevCal = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 16: |
|||
this.txtPrevEol = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 17: |
|||
this.txtVoltage = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 18: |
|||
this.txtVoltageRangeGuide = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 19: |
|||
this.txtCurrent = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 20: |
|||
this.txtCurrentRangeGuide = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 21: |
|||
this.txtResistance = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 22: |
|||
this.txtResistanceRangeGuide = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 23: |
|||
this.borderFinalResult = ((System.Windows.Controls.Border)(target)); |
|||
return; |
|||
case 24: |
|||
this.txtFinalResult = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 25: |
|||
this.txtFinalSerial = ((System.Windows.Controls.TextBlock)(target)); |
|||
return; |
|||
case 26: |
|||
this.btnStart = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 358 "..\..\MainWindow.xaml"
|
|||
this.btnStart.Click += new System.Windows.RoutedEventHandler(this.btnStart_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 27: |
|||
this.btnOpenSettings = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 367 "..\..\MainWindow.xaml"
|
|||
this.btnOpenSettings.Click += new System.Windows.RoutedEventHandler(this.btnOpenSettings_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
} |
|||
this._contentLoaded = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
Binary file not shown.
@ -1,177 +0,0 @@ |
|||
#pragma checksum "..\..\SettingsWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "3B54A611CD6FF472DF4AA312133DE53F7310470DDD5247B79B8465A5C8B8AF60"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
|
|||
|
|||
namespace marking_gui { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// SettingsWindow
|
|||
/// </summary>
|
|||
public partial class SettingsWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { |
|||
|
|||
|
|||
#line 67 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMinVoltage; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 69 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMaxVoltage; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 73 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMinCurrent; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 75 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMaxCurrent; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 79 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMinResistance; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 81 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMaxResistance; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 85 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnSave; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 86 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnCancel; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/settingswindow.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\SettingsWindow.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
|||
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { |
|||
switch (connectionId) |
|||
{ |
|||
case 1: |
|||
this.txtMinVoltage = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 2: |
|||
this.txtMaxVoltage = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 3: |
|||
this.txtMinCurrent = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 4: |
|||
this.txtMaxCurrent = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 5: |
|||
this.txtMinResistance = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 6: |
|||
this.txtMaxResistance = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 7: |
|||
this.btnSave = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 85 "..\..\SettingsWindow.xaml"
|
|||
this.btnSave.Click += new System.Windows.RoutedEventHandler(this.btnSave_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 8: |
|||
this.btnCancel = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 86 "..\..\SettingsWindow.xaml"
|
|||
this.btnCancel.Click += new System.Windows.RoutedEventHandler(this.btnCancel_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
} |
|||
this._contentLoaded = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,177 +0,0 @@ |
|||
#pragma checksum "..\..\SettingsWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "3B54A611CD6FF472DF4AA312133DE53F7310470DDD5247B79B8465A5C8B8AF60"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
|
|||
|
|||
namespace marking_gui { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// SettingsWindow
|
|||
/// </summary>
|
|||
public partial class SettingsWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { |
|||
|
|||
|
|||
#line 67 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMinVoltage; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 69 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMaxVoltage; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 73 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMinCurrent; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 75 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMaxCurrent; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 79 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMinResistance; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 81 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox txtMaxResistance; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 85 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnSave; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 86 "..\..\SettingsWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button btnCancel; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/settingswindow.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\SettingsWindow.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
|||
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { |
|||
switch (connectionId) |
|||
{ |
|||
case 1: |
|||
this.txtMinVoltage = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 2: |
|||
this.txtMaxVoltage = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 3: |
|||
this.txtMinCurrent = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 4: |
|||
this.txtMaxCurrent = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 5: |
|||
this.txtMinResistance = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 6: |
|||
this.txtMaxResistance = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 7: |
|||
this.btnSave = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 85 "..\..\SettingsWindow.xaml"
|
|||
this.btnSave.Click += new System.Windows.RoutedEventHandler(this.btnSave_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
case 8: |
|||
this.btnCancel = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 86 "..\..\SettingsWindow.xaml"
|
|||
this.btnCancel.Click += new System.Windows.RoutedEventHandler(this.btnCancel_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
} |
|||
this._contentLoaded = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
Binary file not shown.
@ -1,193 +0,0 @@ |
|||
#pragma checksum "..\..\StartupLoginWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "722E0887EE8192805D77793F6780CDB03B22E7B72F70E2D394ECFCEBCA0B9C94"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
|
|||
|
|||
namespace Housing.Login { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// StartupLoginWindow
|
|||
/// </summary>
|
|||
public partial class StartupLoginWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { |
|||
|
|||
|
|||
#line 346 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox MakerTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 364 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox ModelTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 382 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox Variant1TextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 400 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox Variant2TextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 429 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox OperatorTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 446 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.PasswordBox PasswordBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 476 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox LineNoTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 493 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox LotNoTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 510 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox JigNoTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 518 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button LoginButton; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/startuploginwindow.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\StartupLoginWindow.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
|||
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { |
|||
switch (connectionId) |
|||
{ |
|||
case 1: |
|||
this.MakerTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 2: |
|||
this.ModelTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 3: |
|||
this.Variant1TextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 4: |
|||
this.Variant2TextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 5: |
|||
this.OperatorTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 6: |
|||
this.PasswordBox = ((System.Windows.Controls.PasswordBox)(target)); |
|||
return; |
|||
case 7: |
|||
this.LineNoTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 8: |
|||
this.LotNoTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 9: |
|||
this.JigNoTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 10: |
|||
this.LoginButton = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 522 "..\..\StartupLoginWindow.xaml"
|
|||
this.LoginButton.Click += new System.Windows.RoutedEventHandler(this.LogInButton_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
} |
|||
this._contentLoaded = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,193 +0,0 @@ |
|||
#pragma checksum "..\..\StartupLoginWindow.xaml" "{8829d00f-11b8-4213-878b-770e8597ac16}" "722E0887EE8192805D77793F6780CDB03B22E7B72F70E2D394ECFCEBCA0B9C94"
|
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 이 코드는 도구를 사용하여 생성되었습니다.
|
|||
// 런타임 버전:4.0.30319.42000
|
|||
//
|
|||
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
|
|||
// 이러한 변경 내용이 손실됩니다.
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Windows; |
|||
using System.Windows.Automation; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Controls.Primitives; |
|||
using System.Windows.Data; |
|||
using System.Windows.Documents; |
|||
using System.Windows.Ink; |
|||
using System.Windows.Input; |
|||
using System.Windows.Markup; |
|||
using System.Windows.Media; |
|||
using System.Windows.Media.Animation; |
|||
using System.Windows.Media.Effects; |
|||
using System.Windows.Media.Imaging; |
|||
using System.Windows.Media.Media3D; |
|||
using System.Windows.Media.TextFormatting; |
|||
using System.Windows.Navigation; |
|||
using System.Windows.Shapes; |
|||
using System.Windows.Shell; |
|||
|
|||
|
|||
namespace Housing.Login { |
|||
|
|||
|
|||
/// <summary>
|
|||
/// StartupLoginWindow
|
|||
/// </summary>
|
|||
public partial class StartupLoginWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector { |
|||
|
|||
|
|||
#line 346 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox MakerTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 364 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox ModelTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 382 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox Variant1TextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 400 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox Variant2TextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 429 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox OperatorTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 446 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.PasswordBox PasswordBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 476 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox LineNoTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 493 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox LotNoTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 510 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.TextBox JigNoTextBox; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
|
|||
#line 518 "..\..\StartupLoginWindow.xaml"
|
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] |
|||
internal System.Windows.Controls.Button LoginButton; |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
|
|||
private bool _contentLoaded; |
|||
|
|||
/// <summary>
|
|||
/// InitializeComponent
|
|||
/// </summary>
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
public void InitializeComponent() { |
|||
if (_contentLoaded) { |
|||
return; |
|||
} |
|||
_contentLoaded = true; |
|||
System.Uri resourceLocater = new System.Uri("/marking_gui;component/startuploginwindow.xaml", System.UriKind.Relative); |
|||
|
|||
#line 1 "..\..\StartupLoginWindow.xaml"
|
|||
System.Windows.Application.LoadComponent(this, resourceLocater); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
} |
|||
|
|||
[System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] |
|||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] |
|||
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] |
|||
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { |
|||
switch (connectionId) |
|||
{ |
|||
case 1: |
|||
this.MakerTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 2: |
|||
this.ModelTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 3: |
|||
this.Variant1TextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 4: |
|||
this.Variant2TextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 5: |
|||
this.OperatorTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 6: |
|||
this.PasswordBox = ((System.Windows.Controls.PasswordBox)(target)); |
|||
return; |
|||
case 7: |
|||
this.LineNoTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 8: |
|||
this.LotNoTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 9: |
|||
this.JigNoTextBox = ((System.Windows.Controls.TextBox)(target)); |
|||
return; |
|||
case 10: |
|||
this.LoginButton = ((System.Windows.Controls.Button)(target)); |
|||
|
|||
#line 522 "..\..\StartupLoginWindow.xaml"
|
|||
this.LoginButton.Click += new System.Windows.RoutedEventHandler(this.LogInButton_Click); |
|||
|
|||
#line default
|
|||
#line hidden
|
|||
return; |
|||
} |
|||
this._contentLoaded = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@ |
|||
786424e28f57daf62f6180d8da5730790c336df832876ad7e4dec61838b897e5 |
|||
@ -1,41 +0,0 @@ |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\bin\Debug\marking_gui.exe.config |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\bin\Debug\marking_gui.exe |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\bin\Debug\marking_gui.pdb |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.csproj.AssemblyReference.cache |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\SettingsWindow.baml |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\StartupLoginWindow.baml |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\MainWindow.g.cs |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\SettingsWindow.g.cs |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\StartupLoginWindow.g.cs |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\App.g.cs |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui_MarkupCompile.cache |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui_MarkupCompile.lref |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\MainWindow.baml |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.g.resources |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.Properties.Resources.resources |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.csproj.GenerateResource.cache |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.csproj.CoreCompileInputs.cache |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.exe |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\marking_gui.pdb |
|||
C:\Users\wjddn\Desktop\amosense\marking_gui\marking_gui\obj\Debug\App.baml |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.csproj.AssemblyReference.cache |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.Properties.Resources.resources |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.csproj.GenerateResource.cache |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.csproj.CoreCompileInputs.cache |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\bin\Debug\marking_gui.exe.config |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\bin\Debug\marking_gui.exe |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\bin\Debug\marking_gui.pdb |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\SettingsWindow.baml |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\StartupLoginWindow.baml |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\MainWindow.g.cs |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\SettingsWindow.g.cs |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\StartupLoginWindow.g.cs |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\App.g.cs |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui_MarkupCompile.cache |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui_MarkupCompile.lref |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\App.baml |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\MainWindow.baml |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.g.resources |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.exe |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\marking_gui.pdb |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\bin\Debug\Database.ini |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,20 +0,0 @@ |
|||
marking_gui |
|||
|
|||
|
|||
winexe |
|||
C# |
|||
.cs |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\ |
|||
marking_gui |
|||
none |
|||
false |
|||
DEBUG;TRACE |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\App.xaml |
|||
31238780151 |
|||
|
|||
13495465398 |
|||
141066371409 |
|||
MainWindow.xaml;SettingsWindow.xaml;StartupLoginWindow.xaml; |
|||
|
|||
False |
|||
|
|||
@ -1,20 +0,0 @@ |
|||
marking_gui |
|||
|
|||
|
|||
winexe |
|||
C# |
|||
.cs |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\obj\Debug\ |
|||
marking_gui |
|||
none |
|||
false |
|||
DEBUG;TRACE |
|||
C:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\App.xaml |
|||
3-1210742192 |
|||
|
|||
141215079075 |
|||
14-207034072 |
|||
MainWindow.xaml;SettingsWindow.xaml;StartupLoginWindow.xaml; |
|||
|
|||
True |
|||
|
|||
@ -1,4 +0,0 @@ |
|||
|
|||
|
|||
FC:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\MainWindow.xaml;; |
|||
|
|||
@ -1,4 +0,0 @@ |
|||
|
|||
FC:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\App.xaml;; |
|||
FC:\Users\COMPUTER1\Desktop\mobi\marking_gui\marking_gui\MainWindow.xaml;; |
|||
|
|||
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<root> |
|||
<resheader name="resmimetype"> |
|||
<value>text/microsoft-resx</value> |
|||
</resheader> |
|||
<resheader name="version"> |
|||
<value>2.0</value> |
|||
</resheader> |
|||
<resheader name="reader"> |
|||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
|||
</resheader> |
|||
<resheader name="writer"> |
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
|||
</resheader> |
|||
</root> |
|||
@ -0,0 +1,161 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.IO.Compression; |
|||
using System.Reflection; |
|||
using System.Windows.Forms; |
|||
using System.Drawing; |
|||
|
|||
namespace MarkingInstaller |
|||
{ |
|||
public class Program |
|||
{ |
|||
[STAThread] |
|||
public static void Main() |
|||
{ |
|||
Application.EnableVisualStyles(); |
|||
Application.SetCompatibleTextRenderingDefault(false); |
|||
|
|||
string targetDir = @"C:\marking"; |
|||
|
|||
// 설치 의사 확인
|
|||
var confirm = MessageBox.Show( |
|||
"Marking 시스템을 컴퓨터에 설치하시겠습니까?\n\n" + |
|||
"설치 경로: " + targetDir + "\n" + |
|||
"바탕화면에 실행 바로가기 아이콘이 생성됩니다.", |
|||
"Marking 설치 관리자", |
|||
MessageBoxButtons.YesNo, |
|||
MessageBoxIcon.Question); |
|||
|
|||
if (confirm != DialogResult.Yes) return; |
|||
|
|||
// 설치 상태 진행 폼
|
|||
Form installForm = new Form |
|||
{ |
|||
Text = "Marking 설치 진행 중...", |
|||
Size = new Size(400, 150), |
|||
StartPosition = FormStartPosition.CenterScreen, |
|||
FormBorderStyle = FormBorderStyle.FixedDialog, |
|||
MaximizeBox = false, |
|||
MinimizeBox = false, |
|||
BackColor = Color.FromArgb(240, 243, 244) |
|||
}; |
|||
|
|||
Label lblStatus = new Label |
|||
{ |
|||
Text = "설치 파일 압축을 푸는 중입니다...", |
|||
Location = new Point(20, 20), |
|||
Size = new Size(360, 25), |
|||
Font = new Font("Malgun Gothic", 10, FontStyle.Bold) |
|||
}; |
|||
|
|||
ProgressBar pb = new ProgressBar |
|||
{ |
|||
Location = new Point(20, 55), |
|||
Size = new Size(345, 23), |
|||
Style = ProgressBarStyle.Marquee |
|||
}; |
|||
|
|||
installForm.Controls.Add(lblStatus); |
|||
installForm.Controls.Add(pb); |
|||
|
|||
installForm.Shown += async (s, ev) => |
|||
{ |
|||
try |
|||
{ |
|||
await System.Threading.Tasks.Task.Run(() => |
|||
{ |
|||
// 1. 기존 디렉토리 안전 클린업
|
|||
if (Directory.Exists(targetDir)) |
|||
{ |
|||
try |
|||
{ |
|||
Directory.Delete(targetDir, true); |
|||
} |
|||
catch |
|||
{ |
|||
// 프로세스가 잠긴 경우 대비하여 모든 파일 삭제 시도
|
|||
foreach (var file in Directory.GetFiles(targetDir, "*.*", SearchOption.AllDirectories)) |
|||
{ |
|||
try { File.Delete(file); } catch { } |
|||
} |
|||
} |
|||
} |
|||
Directory.CreateDirectory(targetDir); |
|||
|
|||
// 2. 리소스에서 payload.zip 추출 및 압축 해제
|
|||
var assembly = Assembly.GetExecutingAssembly(); |
|||
using (Stream resourceStream = assembly.GetManifestResourceStream("payload.zip")) |
|||
{ |
|||
if (resourceStream == null) |
|||
{ |
|||
throw new Exception("설치 리소스를 찾을 수 없습니다. (payload.zip)"); |
|||
} |
|||
|
|||
string tempZip = Path.Combine(Path.GetTempPath(), "marking_payload.zip"); |
|||
using (FileStream fs = new FileStream(tempZip, FileMode.Create, FileAccess.Write)) |
|||
{ |
|||
resourceStream.CopyTo(fs); |
|||
} |
|||
|
|||
ZipFile.ExtractToDirectory(tempZip, targetDir); |
|||
try { File.Delete(tempZip); } catch { } |
|||
} |
|||
|
|||
// 3. 바탕화면에 프로그램 바로가기 단축 아이콘 생성
|
|||
CreateShortcut(targetDir); |
|||
}); |
|||
|
|||
installForm.Close(); |
|||
|
|||
MessageBox.Show( |
|||
"설치가 성공적으로 완료되었습니다!\n" + |
|||
"바탕화면의 [Marking System] 아이콘을 클릭하여 앱을 사용하십시오.", |
|||
"설치 완료", |
|||
MessageBoxButtons.OK, |
|||
MessageBoxIcon.Information); |
|||
|
|||
// 설치 완료 후 즉시 프로그램 실행
|
|||
try |
|||
{ |
|||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo |
|||
{ |
|||
FileName = Path.Combine(targetDir, "marking_gui.exe"), |
|||
WorkingDirectory = targetDir |
|||
}); |
|||
} |
|||
catch { } |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
installForm.Close(); |
|||
MessageBox.Show("설치 중 예기치 못한 오류가 발생했습니다:\n" + ex.Message, "설치 실패", MessageBoxButtons.OK, MessageBoxIcon.Error); |
|||
} |
|||
}; |
|||
|
|||
Application.Run(installForm); |
|||
} |
|||
|
|||
private static void CreateShortcut(string targetDir) |
|||
{ |
|||
try |
|||
{ |
|||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); |
|||
string shortcutPath = Path.Combine(desktopPath, "Marking System.lnk"); |
|||
|
|||
// Windows Script Host 리플렉션을 활용해 무참조 단축 바로가기 아이콘 생성
|
|||
Type shellType = Type.GetTypeFromProgID("WScript.Shell"); |
|||
object shell = Activator.CreateInstance(shellType); |
|||
object shortcut = shellType.InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shell, new object[] { shortcutPath }); |
|||
|
|||
shellType.InvokeMember("TargetPath", BindingFlags.SetProperty, null, shortcut, new object[] { Path.Combine(targetDir, "marking_gui.exe") }); |
|||
shellType.InvokeMember("WorkingDirectory", BindingFlags.SetProperty, null, shortcut, new object[] { targetDir }); |
|||
shellType.InvokeMember("Description", BindingFlags.SetProperty, null, shortcut, new object[] { "Marking System Application" }); |
|||
shellType.InvokeMember("Save", BindingFlags.InvokeMethod, null, shortcut, null); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine("바탕화면 바로가기 등록 실패: " + ex.Message); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<assemblyIdentity version="1.0.0.0" name="MarkingInstaller.app"/> |
|||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> |
|||
<security> |
|||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> |
|||
<!-- 관리자 권한 요구 속성 설정 (C드라이브 설치를 위해 필수) --> |
|||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> |
|||
</requestedPrivileges> |
|||
</security> |
|||
</trustInfo> |
|||
</assembly> |
|||
@ -0,0 +1,38 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>net9.0-windows</TargetFramework> |
|||
<UseWindowsForms>true</UseWindowsForms> |
|||
<LangVersion>10.0</LangVersion> |
|||
<ApplicationManifest>app.manifest</ApplicationManifest> |
|||
|
|||
<!-- 와일드카드 소스 및 리소스 자동 수집 완전 차단 --> |
|||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems> |
|||
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems> |
|||
<EnableDefaultItems>false</EnableDefaultItems> |
|||
|
|||
<!-- 단일 파일 설치 바이너리(Setup EXE) 출력 설정 --> |
|||
<PublishSingleFile>true</PublishSingleFile> |
|||
<SelfContained>true</SelfContained> |
|||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<!-- 명시적으로 소스 파일 등록하여 와일드카드 매치 오류 해결 --> |
|||
<Compile Include="Program.cs" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<!-- 구체적인 리소스만 수동 명시하여 MSB3552 에러 원천 차단 --> |
|||
<EmbeddedResource Include="Empty.resx"> |
|||
<LogicalName>Empty.resx</LogicalName> |
|||
</EmbeddedResource> |
|||
|
|||
<!-- payload.zip 파일이 빌드 타임에 동적 생성되어 포함됨 --> |
|||
<EmbeddedResource Include="payload.zip" Condition="Exists('payload.zip')"> |
|||
<LogicalName>payload.zip</LogicalName> |
|||
</EmbeddedResource> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
Loading…
Reference in new issue