Files
networkSetup/docs/changes/2026-11-12-exe-prerequisites.md
T
jychoi4andClaude Opus 5.5 4964f2ced4 feat: add prerequisites, offline prerequisite setup and version tabs
- EXE versions: prerequisite list with the built-in catalog, custom
  installers, download link checks and install file analysis; entries
  are added by the user (no automatic adding), one "추가" dialog with
  기본 목록 / 직접 추가 tabs
- offline prerequisite setup: single exe made from PrerequisiteSetup.exe
  (Windows task dialog, no prerequisites) plus every installer, hash
  checked before, while and after appending; optional WebView2 Runtime
  chosen in the save dialog; replaces an existing file only after the
  user agrees (CLI --replace)
- desktop: progress popup with 생성위치 열기, save dialog fix for
  verbatim paths, EXE 서명 and 설치파일 생성 as version tabs, start
  screen 도구 › 서명하기 placeholder
- CLAUDE.md: results are overwritten only with the user's consent
- test kit and scripts for Windows Sandbox and Hyper-V checks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 16:26:24 +09:00

53 lines
7.8 KiB
Markdown

# EXE 버전의 선행 설치 프로그램
2026-11-12. EXE 버전에 제품보다 먼저 설치할 프로그램 목록(`prerequisites`)을 추가하고, 설치 구성에 **선행 설치** 탭을 만들었다. 제작기가 제공하는 기본 목록에서 고르거나 이 PC의 설치 프로그램 파일을 직접 등록한다. 화면·모델·입력 검사까지이며, 대상 PC에서의 감지·다운로드·설치와 EXE 빌드는 범위 밖이다.
## 사용
1. 설치 구성에서 버전을 열고 **선행 설치** 탭을 연다.
2. **기본 목록에서 추가**를 눌러 필요한 런타임을 고른다. 처음에는 설치 중 다운로드 방식으로 추가된다.
3. 인터넷이 없는 PC에도 설치해야 하면 방식을 **설치 파일에 포함**으로 바꾸고 **파일 지정**으로 같은 설치 프로그램 파일을 고른다.
4. 기본 목록 항목은 대화상자 아래 **추가 방식**에서 **설치 파일에 포함**을 고르면 제작기의 `SetupPrerequisites` 폴더에 있는 설치 프로그램을 그대로 쓴다. 이 폴더에 파일이 있는 항목에는 **오프라인** 표시가 붙는다.
5. 기본 목록에 없는 프로그램은 **개별 설치 추가**로 `.exe`·`.msi`·`.msu`를 골라 등록하고, 화면 없이 설치하는 실행 인수를 적는다.
## 결정
- 지원 대상은 Windows 10 이상이다. InstallShield 2016의 선행 설치 정의 297개 중 Windows 10에서 의미 있는 항목만 추려 기본 목록 16개로 시작한다.
- 기본은 설치 중 다운로드이고, 제작자가 설치 프로그램을 설치 파일에 미리 넣을 수 있다.
- 오프라인 설치를 위해 기본 목록의 설치 프로그램을 리소스 폴더 `SetupPrerequisites`에 보관하고, 제작기 배포본에도 실행 파일 옆 `SetupPrerequisites` 폴더로 함께 배포한다. 파일은 Git에 넣지 않고 `scripts/Get-Prerequisites.ps1`로 목록의 주소에서 받아 SHA-256을 확인한다.
- 버튼은 **기본 목록에서 추가**, **개별 설치 추가** 순서다.
## 모델과 실행
- 버전 파일: `prerequisites = [{id, name, architecture, delivery, url, file, sha256, bytes, arguments, detect, rebootCodes}]`. 필드가 없는 기존 `.isver`는 빈 목록으로 연다. `schemaVersion`은 그대로다.
- `architecture = x64 | x86 | any`, `delivery = download | bundled`. `bytes`는 10진 문자열, `sha256`은 소문자 64자.
- `file = {source, path}`는 파일 규칙처럼 소스 alias와 그 안의 `/` 경로다. 절대 경로는 로컬 설정의 소스 연결에만 남는다.
- `detect = {kind, view, path, name, minimum}`. `registryValue`는 `view`(32/64)의 `HKLM\` 또는 `HKCU\` 키에 값이 있고 `minimum`이 있으면 그 이상일 때, `fileVersion`은 파일 버전이 `minimum` 이상일 때 설치된 것으로 본다. 버전은 숫자 단위로 비교하고 앞의 `v`는 무시한다. `detect`가 없으면 항상 실행한다.
- 기본 목록: `package-domain`의 `prerequisites.json`(Visual C++ 2010 SP1·2012 Update 4·2013·2015-2022, .NET 8·9·10 Desktop Runtime, .NET Framework 4.8·4.8.1). 고른 항목은 버전 파일에 복사되므로 이후 목록이 바뀌어도 저장된 버전은 변하지 않는다. 주소는 버전이 고정된 주소를 쓴다.
- 입력 검사(도메인): `DuplicatePrerequisiteId`, `InvalidPrerequisiteName`, `UnsupportedPrerequisiteArchitecture`, `UnsupportedPrerequisiteDelivery`, `InvalidPrerequisiteUrl`(HTTPS, `.exe`·`.msi`·`.msu`), `MissingPrerequisiteFile`, `InvalidPrerequisiteFile`, `MissingPrerequisiteHash`, `InvalidPrerequisiteArguments`, `InvalidPrerequisiteDetection`, `InvalidPrerequisiteRebootCodes`.
- 입력 검사(인프라): 포함 방식의 파일이 없으면 `MissingPrerequisiteFile`, 기록된 SHA-256·크기와 다르면 `PrerequisiteChanged`. `file`이 없는 포함 항목은 `SetupPrerequisites/<id>/<주소의 파일 이름>`을 쓴다. 다운로드 방식은 이 PC에서 아무것도 확인하지 않는다.
- 리소스 폴더: 제작기는 실행 파일 폴더부터 위로 세 단계까지 `SetupPrerequisites`를 찾는다. 개발 빌드(`src/target/debug`)는 `src/SetupPrerequisites`, 배포본은 실행 파일 옆 폴더를 쓴다. `prerequisite_catalog` 명령은 기본 목록과 함께 이 폴더에 파일이 있는 ID(`builtin`)를 돌려준다. 내용 해시는 입력 검사 때 확인한다.
- 스크립트: `Get-Prerequisites.ps1`(받기, 이미 있는 일치 파일은 건너뜀, 다른 내용의 파일이 있으면 멈춤, 알 수 없는 ID 거부), `Publish-Desktop.ps1 -Output <새 폴더>`(release 빌드, 설치 프로그램 16개의 해시를 확인한 뒤 실행 파일과 함께 복사, 기존 폴더 거부).
- 화면: 다운로드 주소가 있는 항목에 SHA-256이 다른 파일을 지정하면 `PrerequisiteHashMismatch`, 기본 목록에 없는 ID는 `UnknownPrerequisite`, 리소스 폴더에 없는 항목을 포함 방식으로 추가하면 `MissingBuiltinPrerequisite`.
- Tauri 명령: `prerequisite_catalog`(기본 목록), `choose_prerequisite_file`(파일 대화상자로 고른 파일의 소스 내 경로·SHA-256·크기). CLI 명령은 추가하지 않았다.
- 범위 밖: 대상 PC에서의 감지·다운로드·실행·재부팅 처리, 다운로드 주소의 생존 확인, 항목 순서 변경, 감지 조건 편집 화면, 패치 버전에서의 선행 설치 제약, VBA 7.1처럼 공개 주소가 없는 프로그램의 기본 목록 제공.
## 확인 결과
- Rust 테스트 87개 통과(무시 1개: SDK 통합). 기본 목록 16개가 검증을 통과하는지, 주소·해시·파일·감지 조건 거부, 필드 없는 기존 버전 파일 열기와 왕복 저장, 알 수 없는 필드 거부, 포함 파일의 변경·누락 탐지, 리소스 폴더의 파일 위치·해시 확인과 이름이 아닌 ID·주소 거부를 검사한다.
- 프런트엔드 테스트 118개 통과; TypeScript/Vite 빌드와 `cargo build -p msix-studio --features custom-protocol` 통과. 목록 복사, 파일 등록, 해시 불일치 거부, 리소스 폴더에 없는 항목의 포함 추가 거부와 오프라인 표시, 버튼 순서, 그리드·대화상자 렌더링과 이스케이프, 잠금·MSIX 상태를 검사한다.
- 기본 목록의 설치 프로그램 18개(목록 16개와 VS 2026 계열 Visual C++ 2개)를 2026-11-12에 Microsoft 주소에서 내려받아 디지털 서명이 유효함을 확인하고 SHA-256과 크기를 기록했다. .NET 6개는 Microsoft 공개 SHA-512와도 일치했다.
- 감지 조건의 레지스트리 키는 개발 PC(Windows 11)의 32비트 보기에 존재함을 확인했다. 설치되지 않은 항목(Visual C++ 2012 x86 등)의 키는 같은 규칙으로 추정했다.
- `Get-Prerequisites.ps1`: 리소스 폴더 16개 모두 건너뜀, 빈 폴더에 `vc2012-x86`을 실제로 받아 해시 확인, 변조한 파일과 알 수 없는 ID 거부를 확인했다.
- `Publish-Desktop.ps1`: release 빌드 후 실행 파일과 설치 프로그램 16개를 복사했고, 같은 출력 폴더로 다시 실행하면 거부됨을 확인했다. 시험 출력은 지웠다.
- 배포본 실행 파일이 옆의 `SetupPrerequisites`를 찾는지는 앱을 띄워 확인하지 않았다.
- 실제 앱에서 탭을 조작하는 GUI 시험, 설치 프로그램 실행, 대상 PC 설치 시험은 수행하지 않았다.
증빙: [시험 결과 JSON](../../src/tests/verification-2026-11-12-exe-prerequisites.json)
## 근거
- [Microsoft Learn: Latest supported Visual C++ Redistributable downloads](https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist)
- [.NET release metadata](https://builds.dotnet.microsoft.com/dotnet/release-metadata/releases-index.json)
- [Microsoft Learn: Determine which .NET Framework versions are installed](https://learn.microsoft.com/dotnet/framework/install/how-to-determine-which-versions-are-installed)