본문으로 바로가기

[NSIS] 언인스톨 섹션

category 유틸리티/NSIS 2016. 4. 1. 18:47

본 포스팅에서는 NSIS의 언인스톨러 생성을 간단하게 알아 본다.



NSIS를 통해 생성한 인스톨 프로그램의 설치는 비교적 쉽게 이해할 수 있다. 설치하고자 하는 파일을 SectionSectionEnd 사이 File 명령을 통해 패키징하고 지정된 디렉터리에 설치하면 된다.

(역시나 자세하진 않지만 간략한 내용으로 '[NSIS] 꼭 필요한 스크립트와 기본적인 MUI 적용' 글에서 언급한 바 있다.)


본 포스팅에서 알아보고자 하는 삭제(언인스톨)는 쉽게 접근하자면 설치 과정을 통해 설치한 파일들을 찾아서 삭제해주면 된다.

언인스톨 섹션 이름은 "Uninstall" or "un."

NSIS의 인스톨 과정과 언인스톨 과정은 SectionSectionEnd 사이의 명령대로 수행 한다.

Section ... SectionEnd

먼저 Section의 명령어 라인은 다음과 같다.

Section [/o] [([!]|[-])section_name] [section_index_output]
...
SectionEnd

간략히 내용을 살펴보면 ..


Section + [옵션] + [섹션 이름] + [섹션 ID]로 구성되고, 각각 Space 공란으로 구분되며 [..]의 내용은 필수 사항은 아니다.

  • Section은 해당 섹션의 시작을 의미 한다.
  • /o는 Optional을 의미 한다.
  • section_name은 설치항목 페이지에서 보여지기 위한 이름이다.
  • 설치항목 페이지(MUI_PAGE_COMPONENTS)에서 표현되는 방식으로 섹션 이름 앞에 !를 붙이면 굵게 표현 되며, -를 붙이면 숨김 속성 즉, 사용자는 해당 항목이 보이지 않게 된다.
  • section_index_output은 특별한 목적을 위해 해당 섹션에 고유 ID를 설정하는 것이다.
  • 마지막으로 SectionEnd는 해당 섹션 부분을 종료하는 의미이다.
Section의 이름에 대하여 ..

인스톨과 언인스톨 과정을 구분하는 것은 바로 Section 다음에 오는 이름에 있다. 다음과 같은 경우 해당 Section은 언인스톨 섹션으로 받아 들이고, 언인스톨을 실행하면 해당 섹션의 내용으로 삭제 과정을 진행 한다.

Section "Uninstall"
...
SectionEnd

or

Section "un.섹션이름"
...
SectionEnd

언인스톨러 구성하기

언인스톨 프로그램 생성

위에서 얘기한 "Uninstall" or "un." 이름을 가진 언인스톨러의 섹션은 언인스톨 과정에만 관여를 한다.


결국 언인스톨을 위한 "Uninstall.exe" 파일은 인스톨(설치) 과정에서 사용자에게 만들어 주어야 한다.
(언인스톨 섹션만 있다고 전부가 아니다. 언인스톨 섹션을 실행하기 위한 파일을 만들어 주자!)

Section "인스톨 섹션"
  WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd

언인스톨 섹션의 내용 부분

서두에도 잠시 언급했지만 NSIS의 언인스톨을 쉽게 생각하면, 설치한 파일을 삭제해 주는 것이다.

기본적으로 인스톨 섹션에서 설치(복사)한 파일과 언인스톨 섹션에서 삭제할 파일을 1:1 매칭 시켜 주면 된다.

Section "인스톨 섹션"
  SetOutPath "$INSTDIR"

  File "file_01"
  File "file_02"
  File "file_03"
  ...
  WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd

Section "un.언인스톨 섹션"
  Delete "$INSTDIR\file_01"
  Delete "$INSTDIR\file_02"
  Delete "$INSTDIR\file_03"
  ...
  Delete "$INSTDIR\Uninstall.exe"

  RMDir "$INSTDIR"
SectionEnd

"언인스톨 섹션" 부분을 간략히 살펴보면 ..

  • Delete라는 명령을 통해 설치된 파일들(file_01, file_02, file_03,.. 뿐만 아니라 Uninstall.exe를 포함하여)을 삭제 한다.
  • RMDir 명령을 통해 설치를 위해 생성한 디렉터리를 삭제 한다. (이때 해당 디렉터리에 설치한 파일 이외에 다른 파일이 있다면 해당 디렉터리는 삭제되지 않을 것이다.)
RMDir 옵션으로 간략화

디렉터리를 삭제하는 RMDir 명령은 기본적으로 해당 디렉터리에 (사용자가 새로 생성한 파일이든 배포자의 실수이든) 파일이 남아 있으면 해당 디렉터리는 삭제되지 않는다.


그러한 이유로 상기 예시에서 Delete 명령으로 배포자가 알고 있는 설치된 파일을 모두 삭제한 이후에 디렉터리를 삭제하는 것이다. (또한 상기 예시에서는 하나의 설치 디렉터리만 있었지만, 다수의 서브 디렉터리가 있다면 가장 깊숙한 디렉터리 부터 차근차근 삭제해 주어야 한다.)


한가지 문제는 설치되는 파일이 많지 않으면 상관이 없지만, 몇 백 ~ 몇 천이라면 얘기가 달라진다.


결국 설치한 파일을 일일이 다 삭제하느라 스크립트는 무수히 길어질 것이다. 주구장창 나열하는 것은 문제가 아니나 배포자도 사람인지라 한두개 빼먹는 오류가 발생할 수도 있다.


여기서 RMDir의 옵션을 통해 획기적으로 간략화 할 수도 있다.

RMDir [/r] [/REBOOTOK] directory_name
  • 바로 /r 옵션으로 해당 디렉터리 아래 무엇이 있든 내가 책임질테니 삭제하라는 무시무시한 명령이다.
  • 필요에 따라 해당 디렉터리를 삭제할 수 없을 때는 /REBOOTOK 옵션을 통해 재부팅 후 삭제할 수도 있다.

결과적으로 해당 디렉터리를 무조건 삭제해도 된다고 판단된다면 언인스톨 섹션 부분은 다음과 같이 간략화 될 수 있다.

Section "un.언인스톨 섹션"
  RMDir /r "$INSTDIR"
SectionEnd


배포자가 고민해야 할 것은 '과연 해당 디렉터리를 묻지도 따지지도 않고 싸그리 다 삭제해도 되는가?'일 것이다. 단순히 손가락 관절이 쑤셔 입력하기 귀찮다고 '/r' 옵션으로 삭제한다면 참으로 무책임한 배포자가 될 것이다.
최소한 사용자의 파일은 보존해 주고 설치된 파일이 몇개가 되었건 그것은 배포자가 책임지고 삭제해 주는 것이 배려일 것이다.

'RMDir /r'은 참으로 무시무시한 명령이며, 항상 사용에 있어 주의를 요하는 명령이다.