WPF 프로젝트를 진행 중 해당 앱의 설치 파일 요청이 들어왔습니다. 먼저, 오프라인에서의 설치가 필요하므로 간편하게 배포할 수 있는 ClickOnce는 배제하였습니다.
간략하게 계획은 다음과 같았습니다.
1. Microsoft Visual Studio Installer Project는 제약이 많으므로 스크립트로 구성할 수 있는(친숙하고 잘아는) NSIS로 선택하자.
2. VisualStudio에서 Release로 빌드 시 설치 파일까지 자동으로 만들어지도록 하자.
3. 닷넷 프레임워크 버전 확인하여 버전이 낮은 경우 자동으로 설치하자.
4. 앱에서 사용되는 자체 파일(확장자)의 아이콘을 표시하자.
위의 계획을 토대로 아래와 같은 프로세스로 진행되어 집니다.
※ 64비트 윈도우 10 환경에서 개발되었습니다.
1. 폴더 구조
먼저 프로젝트의 폴더 구조를 살피면 최상위 폴더는 install, src, doc로 구성되어 있습니다.
- install: 설치본을 만들기 위한 실행파일, 설치 스크립트 등이 존재합니다.
- doc: 화면 정의서, 회의록 등 문서가 들어있으며 해당 글과는 무관합니다.
- src: C# 솔루션이 있습니다.
- input(폴더): 설치본에 들어갈 파일들을 해당 폴더에 위치합니다. 빌드 후 나오는 바이너리들은 해당 폴더로 위치한다고 보면 됩니다.
- output(폴더): input폴더의 바이너리를 말아서 나온 설치 파일이 위치합니다.
- ChangeFileIcon.bat: 특정 확장자에 대한 파일 아이콘을 설정하기 위한 레지스트리 등록 명령어가 들어있습니다.
- Icon.ico: 특정 확장자에 표시되는 파일 아이콘입니다.
- Install.bat: 설치본을 만들기 위한 'MakeNSIS' 프로그램 실행 명령어들이 있습니다.
- InstallScript.nsi: 'MakeNSIS' 프로그램에서 해당 NSIS 스크립트를 컴파일합니다.
- NDP472-KB4054530-x86-x64-AllOS-ENU.exe: 닷넷 프레임워크 4.7.2 버전의 오프라인 설치 파일입니다. 앱 설치 시 4.7.2 버전이 설치되어 있지 않다면 설치를 진행하는데 쓰입니다.
- WelcomeFinishPage.bmp: 설치 파일 실행 시 처음 나오는 이미지입니다.
2. 빌드 이벤트(PostBuildEvent.bat)
Visual Studio에서 프로젝트 속성을 보면 빌드 이벤트가 있습니다.
여기서는 빌드 후 이벤트 명령줄에 명령어를 입력하여 Release로 빌드 시 바이너리를 install\input 폴더로 위치하도록 하였습니다.
- Release로 빌드하였을 때만 진행되도록 하였습니다.
- install\input폴더에는 직전 버전의 파일을 가지고 있을 수 있으므로 강제 폴더 삭제 및 생성하였습니다.
- Release폴더에 위치한 config, exe, dll파일만 이동하도록 하였습니다.
- install폴더에 위치한 설치본 만들기 배치파일을(Install.bat) 실행합니다.
3. 설치본 만들기 배치파일(Install.bat)
빌드 및 바이너리 파일들이 다 옮겨지면 해당 배치파일이 실행됩니다.
makensis.exe를 실행하며 설치 스크립트(InstallScript.nsi)를 컴파일하여 설치본이 생성됩니다.
앱의 버전을 전달해 주기 위하여 PowerShell 명령어를 통하여 버전을 알아와 'MakeNSIS' 프로그램 실행 시 옵션에 파라미터로 넣어주었습니다.
4. 설치 스크립트(InstallScript.nsi)
스크립트가 길므로 주요 포인트만 설명합니다. 개발 능력이 있으신 분들이라면 NSIS를 자세히 몰라도 바로 파악이 될 것입니다.
- !define PRODUCT_VERSION ${VERSION}
makensis.exe 옵션 파라미터로 들어간 /DVERSION값이 들어옵니다. - !define MUI_WELCOMEFINISHPAGE_BITMAP "WelcomeFinishPage.bmp"
설치본 시작페이지에 해당 이미지가 좌측에 표시된다. 비트맵이어야 하며 164x314 픽셀 사이즈이어야 합니다. - OutFile "output\${PRODUCT_ENGLISH_NAME}_${PRODUCT_VERSION}_Install.exe"
output폴더에 app_v1.0.0.0_Install.exe로 설치본이 생성됩니다. - Call CheckAndInstallDotNet
CheckAndInstallDotNet 함수를 호출하며 해당 함수에는 레지스트리의 값을 통한 닷넷 프레임워크 버전을 확인하여 버전이 낮다면 설치를 하라는 메시지 박스가 나오게 됩니다. YES 시 설치본에 들어가 있는 닷넷 프레임워크 4.7.2 오프라인 설치본을 실행합니다. - ExecWait '"$INSTDIR\Setup\ChangeFileIcon.bat" "$INSTDIR\Icon.ico"'
설치가 마무리될 때 파일 확장자 아이콘 설정 배치파일을 실행하게 됩니다. 파라미터로 아이콘 위치를 같이 보냅니다.
5. 파일 확장자 아이콘 설정(ChangeFileIcon.bat)
설치 스크립트에 넣어도 되었지만 그 당시에 급했는지 배치파일을 만들었고 설치 스크립트에서 실행되도록 하였습니다.
앱에서. app1이라는 확장자를 사용한다고 가정하였습니다.
레지스트리 등록 후 ie4uinit.exe를 실행하면 아이콘 캐시 초기화 작업을 하게 되는데 NSIS가 32비트여서 배치파일 실행 시 64비트인 ie4uinit.exe를 찾지 못하고 에러를 뱉는 경우가 발생하게 됩니다. 절대 경로로 작성을 해도 찾지 못하므로 다음과 같이 %SystemRoot%sysnative를 통해서 실행되도록 하였습니다. File System Redirector글에 충분한 설명이 적혀있으니 참고 바랍니다.
이상입니다.
'개발 > C#' 카테고리의 다른 글
파일 작성 시 원자성 유지방법 (0) | 2020.10.23 |
---|---|
Immutable type: Shallow Copy한 복사개체에서 문자열 변수 값을 변경하였지만 원본개체에서는 변경되지 않은 이유는? (0) | 2018.01.10 |
c#에서 오피스(워드, 엑셀등) 접근 방법 - COM object관련 (0) | 2016.02.26 |
접근 제한자(Access Modifier) (0) | 2015.03.04 |
string.IsNullOrEmpty 와 string.IsNullOrWhiteSpace 비교 (0) | 2014.11.19 |