헬마입니다.

매우 매우 오랜만에 NSIS 관련한 글을 포스팅하게 되었네요.

NSIS 의 SearchParse 와 SearchReplace

NSIS 에 새로 컴파일 타임 명령어로 SearchParse 와 SearchReplace 라는 명령이 추가되었습니다.

사실 추가된지는 꽤 되었습니다. 하지만, 의외로 쓰시는 분이 별로 없는듯하여 이번에 간단한 글을 작성해보려 합니다.

이 명령들은 사실 일반적으로는 별로 쓰일일이 드문편입니다. 주로 이 명령들이 쓰이는 곳은 다른 언어의 설정파일과 설정내용을 동기화할 때 쓰이지요.

예를 들어, C++ 로 윈도 응용 프로그램을 작성하면 보통 제품의 버전번호는 소스코드의 rc 확장자를 가진 리소스 파일에 저장되고 관리됩니다.

하지만, NSIS로 설치관리자를 만들때 VIAddVersionKey 라던가 VIProductVersion 이라는 속성을 사용해서 설치관리자에도 버전을 설정할 수 있지만, 이 둘을 언제나 일치시키는 것은 역시나 귀찮은 일이지요.

이럴때 위의 두가지 컴파일 타임 명령어를 사용하면 자동으로 동기화를 시킬 수 있어요. ^^

간단한 예제를 통해서 그 방법을 적어보겠습니다. ^^

사실, 저도 한동안 NSIS 작성할 일이 없어서 손을 안대고 있다가 최근에 회사 프로젝트의 설치관리자를 수정하다가 적용해보고 적는 것 입니다 ^^

준비물 :
NSIS - 사용하는 버전이 2.45 버전이라면 http://nsis.sf.net 에서 일일빌드를 받아서 설치하세요. 공식배포 2.45버전에는 !searchparse 명령에 버그가 있습니다
동기화할 파일

먼저, 도움말을 살펴보죠.

	!searchparse

		[/ignorecase] [/noerrors] [/file] source_string_or_file substring_start OUTPUTSYMBOL1 [substring [OUTPUTSYMBOL2 [substring ...]]]
source_string_or_file 을( /file 을 설정하면 파일이름으로, 설정하지 않으면 문자열로 취급 ) 분석하여 substring_start 을 검색합니다.
substring_start 가 검색되면 OUTPUTSYMBOL1 이 문자열의 나머지 부분( substring 을 설정했고 이 문자열이 검색되면 이 문자열은 제외됨 ) 이 선언됩니다. 몇 개의 OUTPUTSYMBOLx 라도 설정될 수 있으며 마지막의 substring 은 선택적입니다.
/noerrors 가 설정되면, 모든 문자열이 일치하지 않아도 되며 ( 모든 OUTPUTSYMBOLx ) 후에 검색되지 않은 하위문자열은 무시됩니다.
/file 가 설정되면, 파일은 줄의 모음으로 취급됩니다. 파일은 모든 하위문자열이 일치할 때 까지 검색됩니다. /noerrors 가 설정되고 모든 문자열이 일치하지 않았다면 가장 많은 기호가 일치한 첫 행이 사용됩니다.
	!searchreplace

		[/ignorecase] symbol_out source_string searchfor replacewith 
source_string 을 검색하여 이 문자열에서 searchfor 를 모두 replacewith 로 치환합니다. !define 과는 다르게 !searchreplace 는 여러분이 경고 또는 오류없이 symbol_out 을 재정의할 수 있도록합니다.
음, 솔직히 제가봐도 알쏭달쏭합니다. 어떻게 쓰라는 건지 영 감이 안오죠.

예제로 사용할 파일 소스
- 첨부파일로 들어있는 rc 파일을 사용하시면 됩니다.

이제 첫 단계로, 어느 부분을 동기화 시킬지 결정해야죠. 저는 rc 파일에서 제품 버전정보를 가져와서 이를 언제나 설치관리자의 버전 정보로 사용하고 싶어요.
그래서 rc 파일을 살펴보니 PRODUCTVERSION 1,0,0,1 이라는 부분이 보입니다. 이 부분을 가져다가 요리저리 가공하면 어찌될 것 같네요.

아래는 예제 코드에요.
간단한 주석을 실었습니다.

Name 'NSIS_EX'
OutFile 'NSIS_EX.EXE'

!include MUI.nsh
!insertmacro MUI_LANGUAGE "Korean"

; Calc_test.rc 파일에서 PRODUCTVERSION 이라는 문자열을 찾은 후 그 줄의 그 다음 부분을 VERSION_NAME 이라는 이름으로 선언. ( 변수가 아니라 !define 으로 선언한 것과 같은 효과 입니다 )
!searchparse /ignorecase /file '.\Calc_Test.rc' 'PRODUCTVERSION' 'VERSION_NAME' ''
; rc 파일을 보시면 버전 번호를 지정할 때는 쉼표를 사용하게 되어있습니다. 하지만, VIAddProductVersion 을 사용할때는 마침표로 변경해야합니다. 
; 하지만, !define 으로 선언한 것은 일반적인 방법으로는 쉽게 변경할 수 없습니다. 이를 해결하기위해 !searchreplace 가 추가되었습니다. 
; VERSION_NAME 이라는 기호에서 "," 를 찾아 "." 으로 변경합니다. 처음에 기호 이름을 지정할 때 ${} 로 둘러싸지 않은 점을 눈여겨보세요.
!searchreplace /ignorecase VERSION_NAME ${VERSION_NAME} "," "."

VIAddVersionKey /LANG=${LANG_KOREAN} 'ProductVersion' '${VERSION_NAME}'
VIAddVersionKey /LANG=${LANG_KOREAN} "ProductName" "NSIS_EX"
VIAddVersionKey /LANG=${LANG_KOREAN} "Comments" "NSIS_EX Setup"
VIAddVersionKey /LANG=${LANG_KOREAN} "CompanyName" "초짜 플머 헬마"
VIAddVersionKey /LANG=${LANG_KOREAN} "LegalTrademarks" ""
VIAddVersionKey /LANG=${LANG_KOREAN} "LegalCopyright" ""
VIAddVersionKey /LANG=${LANG_KOREAN} "FileDescription" "NSIS_EX"
VIAddVersionKey /LANG=${LANG_KOREAN} "FileVersion" "${VERSION_NAME}"
VIProductVersion '${VERSION_NAME}'

Function .onInit
	SetSilent silent
	
	MessageBox MB_OK ${VERSION_NAME}
FunctionEnd

Section -
SectionEnd

댓글을 달아 주세요