헬마입니다.

이번에는 NSIS 에서 윈도 OS 정보를 얻어내는 플러그인입니다.

NSIS 로 OS 버전 알아내기

이 플러그인은 매우 간단합니다. 덜렁 함수 2개로 구성되어 있으며 필요에 따라 하나씩 호출하고 반환되는 값을 보고 판단하면 됩니다.

OS 버전을 알고 싶을 때
1) Call osversion ; OS 버전을 알려주는 함수를 호출합니다.
2) OS의 주요 버전은 $0 에 부가 버전은 $1 에 반환됩니다.

OS 플랫폼을 알고 싶을 때
1) Call osplatform ; OS 플랫폼을 알려주는 함수를 호출합니다.
2) $0 에 들어온 값을 분석합니다.
  $0 에는 'win31', 'win9x', 'winnt', 와 'unknown' 중의 하나가 들어갑니다.

버전 넘버 판별
--------------------------------
주요 버전:
  Windows 95   4
  Windows 98   4
  Windows Me   4
  Windows NT 3.51  3
  Windows NT 4.0  4
  Windows 2000   5
  Windows XP   5
  Windows .NET Server  5

부가 버전
  Windows 95   0
  Windows 98   10
  Windows Me   90
  Windows NT 3.51  51
  Windows NT 4.0  0
  Windows 2000   0
  Windows XP   1
  Windows .NET Server  1

예제
-------

; Copyright (C) 2001 Robert Rainwater

Name "NSIS OS Extension Example" ; 이름
OutFile "example.exe" ; 작성 파일

InstallDir $TEMP\nsisos
DirShow hide

ShowInstDetails show
AutoCloseWindow false

Function .onInit
SetSilent silent
FunctionEnd

Section -
; nsisos.dll 파일이 플러그인 폴더가 아닌 스크립트와 같은 폴더에 있어야 합니다.
File /oname=$TEMP\nsisos.dll nsisos.dll ;플러그인을 임시 디렉토리에 압축을 해제합니다.
CallInstDLL $TEMP\nsisos.dll osversion ; 플러그인을 호출합니다. osversion 함수를 호출합니다.
StrCpy $R0 $0 ; $0 과 $1 에는 숫자가 들어있습니다.
StrCpy $R1 $1
CallInstDLL $TEMP\nsisos.dll osplatform ; osplatform 함수를 호출합니다.
StrCpy $R2 $0
MessageBox MB_OK "Major Version: $R0 $\nMinor Version: $R1 $\nPlatform: $R2" ; 반환 받은 정보를 출력합니다.
Delete $TEMP\nsisos.dll
SectionEnd

또는 nsisos.dll 파일을 NSIS의 플러그인 디렉토리에 넣었다면
nsisos::osversion ; osversion 함수 호출
nsisos::osplatform ; osplatform 함수 호출
위와 같은 형식으로 호출할 수 있습니다.

댓글을 달아 주세요

헬마입니다.

오랜만에 글을 쓰는군요.

이번에는 NSIS에서 플러그인을 사용해 CPU 정보를 얻어내 볼까 합니다.

코덱팩에서 유용하게 쓰인 플러그인입니다.

주로 CPU 종류별로 프로그램을 설치하거나 할 때 쓰입니다.

준비물 : NSIS, Cpudesc 플러그인

이 플러그인은 호출하면 변수에 특정형식으로 된 긴 문자열을 반환합니다. 그러면 사용자는 이 문자열에서 지정된 위치를 문자를 읽어보고 정보를 얻어내는 형태입니다.

이 플러그인을 호출하고 $0 값을 스택에서 꺼내어 보면 아래와 같은 형식으로 정보가 저장되어 있습니다.

<도움말에서...>

INTELP=d AMD=add PPRO=b MMX=d SSE=b SSE2=b 3DNOW=d ARCH=dd LEVEL=dd NCPU=dd MHZ=ddddd RAM=dddd

d -> 숫자를 나타냅니다. d가 2개면 두자리 숫자라는 뜻이지요.
a -> 문자를 나타냅니다. 알파벳 A-Z 까지입니다.
b -> 논리값을 나타내기 위한 숫자값입니다. 0 또는 1입니다.

INTELP: 값 범위 [0..4].
  0:    인텔 CPU가 아니거나 매우 매우 오래된 인텔 CPU
  1:    Pentium 또는 Pentium MMX. 즉, MMX 지원여부는 MMX 를 다시한번 확인해봐야합니다.
  2:    Pentium Pro, II 또는 Celeron.
       펜티엄 프로는 MMX가 없기때문에 역시 MMX 지원여부는 따로 확인해야합니다.
  3:    Pentium III 또는 P3 (구형) Xeon.   MMX 와 SSE 를 지원합니다.
  4:    Pentium IV 또는 (신형) Xeon.   MMX, SSE, SSE2 를 지원합니다.
AMD:    좀 복잡합니다....
  000:  AMD CPU가 아니거나 매우 매우 오래된 AMD CPU
  Kdd:  구형 K 시리즈..   "dd" 값은 K5의 05 또는 K6의 06
       펜티엄 호환. K5는 MMX나 3dnow 지원안함. k6 는 표준 MMX 를 지원하며 후기 모델은 표준 3d now 지원
  Add:  애슬론 또는 듀론.   "dd" 는 모델넘버로 01 부터 10까지. 모든 모델은 확장 MMX와 확장 3D NOW 지원.
       SSE는 지원하지 않음. 펜티엄 2 호환.
  Odd:  옵테론.   "dd" 는 모델 넘버
       펜티엄 4 호환.
PPRO:   값 범위 [0..1]
  0:    인텔 펜티엄 프로와 호환성 없음
  1:    인텔 펜티엄 프로와 호환
MMX:    Values range [0..2].
  0:    MMX 지원 안 함
  1:    표준 인텔 MMX
  2:    표준 MMX 와 AMD MMX
SSE:    Values range [0..1].
  0:    SSE 지원 안 함
  1:    SSE 지원 함
SSE2:   Values range [0..1].
  0:    SSE2 지원 안 함
  1:    SSE2 지원
3DNOW:  Values range [0..2].
  0:    3D NOW 지원 안 함
  1:    표준 3D NOW
  2:    표준, 확장 3D NOW
ARCH:   Values range [00..10].
  00:   32-bit 인텔 또는 그 호환
  01:   MIPS (NT 3.5용)
  02:   DEC Alpha.  
  03:   PowerPC
  04:   SHX (?)
  05:   ARM (Acorn Risc Machine, 윈도가 돌아가던가??)
  06:   64-bit Intel.
  07:   64-bit Alpha
  08:   MSIL (?)
  09:   64-bit AMD
  10:   32-bit Intel doing Win64 (?)
LEVEL:  "Processor level", like what you see in the main processor environment
       variable.   Sort-of useless for Intel architecture.
NCPU:   프로세서 숫자(아마도 하이퍼 스레딩이 영향을 미치리라 예상함)
MHZ:    The CPU's internal clock speed in MHz (Approx).
RAM:    반올림한 물리 메모리 용량 (메가바이트 단위)


INTELP=d AMD=add PPRO=b MMX=d SSE=b SSE2=b 3DNOW=d ARCH=dd LEVEL=dd NCPU=dd MHZ=ddddd RAM=dddd

간단한 예제
  cpudesc::tell  ; cpudesc 플러그인을 호출합니다.
  Pop $0                     ; 스택에 저장된 $0 를 꺼냅니다
  StrCpy $1 $0 1, 22         ; $0 문자열의 22번째 위치에서 한 글자를 읽어 $1에 저장. 'PPRO=' 다음 글자
  IntFmt $2 "%u" $1          ; 읽어온 글자인 $1를 숫자형식으로 변환하여 $2에 저장
  IntCmpU $2 1 +1 +3 +3      ; $2와 1을 비교하여 같으면(펜티엄 프로이면) 바로 진행하고 같지 않으면(펜티엄 프로가 아니면) 3번째 명령 위치로 이동하여 그 명령을 실행
  File /oname=blog.exe "blog_source_directory\blog_pro.exe"  ; 프로용 파일 설치
  Goto +2 ; 일반 적인 파일 설치 부분을 건너뛰기 위해 실행 위치를 +2 만큼 이동
  File /oname=blog.exe "blog_source_directory\blog_gen.exe" ; 일반적인 파일 설치
... 나머지 명령...


댓글을 달아 주세요

헬마입니다.

이번엔 섹션들을 다루는데 상당히 필수적으로 포함시키는 Sections.nsh 파일에 대해 한번 몇가지 적어볼까 합니다.

일단 이 파일에는 그저 섹션과 인스톨타입에 대해 정의되어 있는 것이 전부는 아닙니다. 에를 들면 섹션이 선택되어 있는지 이런 것들을 확인할 때 이 파일에 포함된 매크로를 사용할 수 있습니다.

;--------------------------------
이파일이 포함되어 있는지 확인하기 위한 것 입니다.
!ifndef SECTIONS_INCLUDED
!define SECTIONS_INCLUDED
;--------------------------------

SectionGetFlags 등의 함수에서 사용하는 플래그 값들입니다. 이 값들은 IntOp 등의 명령을 이용해 조합해서 사용할 수 있습니다.

# section or section group is selected
!define SF_SELECTED   1  ; 선택됨
# section group
!define SF_SECGRP     2 ; 그룹의 시작
!define SF_SUBSEC     2  # deprecated
# section group end marker
!define SF_SECGRPEND  4 ; 그룹의 끝
!define SF_SUBSECEND  4  # deprecated
# bold text (Section !blah)
!define SF_BOLD       8 ; 섹션 이름이 굵은 글씨
# read only (SectionIn RO)
!define SF_RO         16 ; 읽기 전용
# expanded section group (SectionGroup /e blah)
!define SF_EXPAND     32 ; 섹션 그룹이 펼쳐져 있음
# section group is partially selected
!define SF_PSELECTED  64  # internal ; 그룹 안에 섹션들이 일부만 선택되어 있음
# internal
!define SF_TOGGLED    128 # internal
!define SF_NAMECHG    256 # internal

# mask to toggle off the selected flag
!define SECTION_OFF   0xFFFFFFFE ; 모든 플래그를 끕니다.

모든 플래그를 끄는 이 값이 존재하는 이유는 NSIS의 파일 속성 변경할 때 모든 플래그를 끄는 값이 있는 것과 마찬가지 이유입니다. 즉, NSIS는 특정 플래그만 끄는 것은 불가능합니다.
  따라서 그런 조작을 하려면 일단 모든 플래그를 끄고 특정 플래그만 껏을때의 플래그로 설정하는 방법을 사용해야합니다.

;--------------------------------

; Select / unselect / reserve section

!macro SelectSection SECTION

  Push $0
  SectionGetFlags "${SECTION}" $0
  IntOp $0 $0 | ${SF_SELECTED}
  SectionSetFlags "${SECTION}" $0
  Pop $0

!macroend

지정한 섹션(섹션을 설정할 때 사용한 섹션 인덱스를 넣어줍니다.) 을 선택 상태로 변경합니다.

!macro UnselectSection SECTION

  Push $0
  SectionGetFlags "${SECTION}" $0
  IntOp $0 $0 & ${SECTION_OFF}
  SectionSetFlags "${SECTION}" $0
  Pop $0

!macroend

지정한 섹션(섹션을 설정할 때 사용한 섹션 인덱스를 넣어줍니다.) 을 선택해제 상태로 변경합니다.

; If section selected, will unselect, if unselected, will select

!macro ReverseSection SECTION

  Push $0
  SectionGetFlags "${SECTION}" $0
  IntOp $0 $0 ^ ${SF_SELECTED}
  SectionSetFlags "${SECTION}" $0
  Pop $0

!macroend

지정한 섹션(섹션을 설정할 때 사용한 섹션 인덱스를 넣어줍니다.) 을 선택되었다면 해제로, 해제되었다면 선택상태로 바꿉니다.

예)
Section 'aaa' bbb
SectionEnd

bbb -> 이게 섹션 인덱스 입니다.
!insertmacro ReverseSection bbb
이런식으로 사용하면 됩니다.

;--------------------------------
여기는 라디오 버튼처럼 섹션들을 묶어주는 기능을 하는 매크로입니다.
이에 대한 글은 이미 에전에 올린적이 있으니 따로 적지 않겠습니다.

; Macros for mutually exclusive section selection
; Written by Tim Gallagher
;
; See one-section.nsi for an example of usage

; Starts the Radio Button Block
; You should pass a variable that keeps the selected section
; as the first parameter for this macro. This variable should
; be initialized to the default section's index.
;
; As this macro uses $R0 and $R1 you can't use those two as the
; varible which will keep the selected section.

!macro StartRadioButtons var

  !define StartRadioButtons_Var "${var}"

  Push $R0
 
  SectionGetFlags "${StartRadioButtons_Var}" $R0
  IntOp $R0 $R0 & ${SECTION_OFF}
  SectionSetFlags "${StartRadioButtons_Var}" $R0
 
  Push $R1
 
  StrCpy $R1 "${StartRadioButtons_Var}"
 
!macroend

; A radio button

!macro RadioButton SECTION_NAME

  SectionGetFlags ${SECTION_NAME} $R0
  IntOp $R0 $R0 & ${SF_SELECTED}
  IntCmp $R0 ${SF_SELECTED} 0 +2 +2
  StrCpy "${StartRadioButtons_Var}" ${SECTION_NAME}

!macroend

; Ends the radio button block

!macro EndRadioButtons
 
  StrCmp $R1 "${StartRadioButtons_Var}" 0 +4 ; selection hasn't changed
  SectionGetFlags "${StartRadioButtons_Var}" $R0
  IntOp $R0 $R0 | ${SF_SELECTED}
  SectionSetFlags "${StartRadioButtons_Var}" $R0

  Pop $R1
  Pop $R0
 
  !undef StartRadioButtons_Var

!macroend

;--------------------------------

; These are two macros you can use to set a Section in an InstType
; or clear it from an InstType.
;
; Written by Robert Kehl
;
; For details, see http://nsis.sourceforge.net/wiki/SetSectionInInstType%2C_ClearSectionInInstType
;
; Use the defines below for the WANTED_INSTTYPE paramter.

!define INSTTYPE_1 1
!define INSTTYPE_2 2
!define INSTTYPE_3 4
!define INSTTYPE_4 8
!define INSTTYPE_5 16
!define INSTTYPE_6 32
!define INSTTYPE_7 64
!define INSTTYPE_8 128
!define INSTTYPE_9 256
!define INSTTYPE_10 512
!define INSTTYPE_11 1024
!define INSTTYPE_12 2048
!define INSTTYPE_13 4096
!define INSTTYPE_14 8192
!define INSTTYPE_15 16384
!define INSTTYPE_16 32768
!define INSTTYPE_17 65536
!define INSTTYPE_18 131072
!define INSTTYPE_19 262144
!define INSTTYPE_20 524288
!define INSTTYPE_21 1048576
!define INSTTYPE_22 2097152
!define INSTTYPE_23 4194304
!define INSTTYPE_24 8388608
!define INSTTYPE_25 16777216
!define INSTTYPE_26 33554432
!define INSTTYPE_27 67108864
!define INSTTYPE_28 134217728
!define INSTTYPE_29 268435456
!define INSTTYPE_30 536870912
!define INSTTYPE_31 1073741824
!define INSTTYPE_32 2147483648

!macro SetSectionInInstType SECTION_NAME WANTED_INSTTYPE

  Push $0
  SectionGetInstTypes "${SECTION_NAME}" $0
  IntOp $0 $0 | ${WANTED_INSTTYPE}
  SectionSetInstTypes "${SECTION_NAME}" $0
  Pop $0

!macroend

!macro ClearSectionInInstType SECTION_NAME WANTED_INSTTYPE

  Push $0
  Push $1
  SectionGetInstTypes "${SECTION_NAME}" $0
  StrCpy $1 ${WANTED_INSTTYPE}
  IntOp $1 $1 ~
  IntOp $0 $0 & $1
  SectionSetInstTypes "${SECTION_NAME}" $0
  Pop $1
  Pop $0

!macroend

위 두 매크로는 원하는 인스톨 타입에 섹션을 넣어줍니다. 즉, SectionIn 명령과 같다고 할 수 있습니다.
그 명령과 이 매크로의 차이점은 그 함수는 컴파일때 한번 정해지면 끝이지만 이 매크로는 실행되는 도중에 섹션의
포함관게등을 변경할 수 있습니다. WANTED_INSTTYPE에는 위에 정의된 INSTTYPE_1 등과 같은 값을 넣으면 됩니다.

;--------------------------------

; Set / clear / check bits in a section's flags
; Written by derekrprice

; Set one or more bits in a sections's flags

!macro SetSectionFlag SECTION BITS

  Push $R0
  SectionGetFlags "${SECTION}" $R0
  IntOp $R0 $R0 | "${BITS}"
  SectionSetFlags "${SECTION}" $R0
  Pop $R0

!macroend

; Clear one or more bits in section's flags

!macro ClearSectionFlag SECTION BITS

  Push $R0
  Push $R1
  SectionGetFlags "${SECTION}" $R0
  IntOp $R1 "${BITS}" ~
  IntOp $R0 $R0 & $R1
  SectionSetFlags "${SECTION}" $R0
  Pop $R1
  Pop $R0

!macroend

위의 두 매크로는 섹션의 비트 설정을 설정하거나 지웁니다.

; Check if one or more bits in section's flags are set
; If they are, jump to JUMPIFSET
; If not, jump to JUMPIFNOTSET

!macro SectionFlagIsSet SECTION BITS JUMPIFSET JUMPIFNOTSET
Push $R0
SectionGetFlags "${SECTION}" $R0
IntOp $R0 $R0 & "${BITS}"
IntCmp $R0 "${BITS}" +3
Pop $R0
StrCmp "" "${JUMPIFNOTSET}" +3 "${JUMPIFNOTSET}"
Pop $R0
Goto "${JUMPIFSET}"
!macroend

위 매크로는 지정한 섹션에서 지정한 플래그들이 설정되어 있는지 조사합니다. 그리고 같으면 JUMPIFSET 으로 같지 않으면 JUMPIFNOTSET 으로 이동합니다.
JUMPIFSET과 JUMPIFNOTSET에는 숫자값을 이용한 절대 주소이동방법을 사용하면 매크로로 인한 주소값에 혼돈이 생겨 제대로 작동되지 않습니다. 물론, 이미
매크로의 주소값까지 계산해서 넣으면 상관없습니다만... 라벨을 만들어서 사용할 것을 적극 권장합니다.

;--------------------------------

!endif

파일 맨 위에 있던 SECTIONS_INCLUDE값에 따라 내용이 포함될 지 여부를 가릅니다.
if문으로 설정되어 있어 한번이라도 포함되면 인스톨러에 SECTIONS_INCLUDE라는 상수가 생성됩니다.
그러면 그담에 다시 포함시킬때 이 상수를 보고 포함시키지 않습니다.

!ifndef SECTIONS_INCLUDED
!define SECTIONS_INCLUDED

댓글을 달아 주세요

헬마입니다.


이번엔 CAB 파일을 풀어주는 DLL 플러그인입니다.

특별히 설명서 없이 예제만 덜렁 제공하네요

머 예제가 쉽긴합니다만..

기본 함수가


CabInfo 변수이름

CabView 변수이름

CabExtractAll 변수이름 변수이름

정도가 있습니다.

CabInfo 함수는 cab파일의 정보를 넘겨줍니다. 변수이름에 파일이름을 경로명포함해서 넣어주면 됩니다.

반환값 - $R0 - 0 이면 정상적인 CAB파일이고 다른 값이면 에러입니다.

정상파일인 경우

$0 CAB 파일의 총 파일길이

$1 CAB 파일에 있는 총 폴더 수

$2 CAB 파일에 있는 총 파일 수

$3 CAB ID

$4 CAB SET No

$5 CAB 에 예약 영역 존재 여부

$6 이전에 연결된 CAB 파일이 있는지 여부

$7 다음에 연결된 CAB 파일이 있는지 여부


$6, $7 을 설명하자면 분할 파일로 1,2,3 파일 3개가 있고 3을 보면 $7은 0 이고 $6은 1 이 반환되겠죠


이런 방법으로 찾으면 됩니다.


CabExtractAll 함수는 첫 번째 변수에 담긴 파일을 두번째 변수에 담긴 폴더에 풀어줍니다.


그냥 무작정 전부 다 풀어버립니다.


음 이정도면 예제보시면 쉽게 쓰실 수 있을 듯 하네요


댓글을 달아 주세요