rubrapack 매뉴얼←↑→

29 Windows 폴더와 환경 변수

패키지는 만든 사람이 본 적 없는 PC 의 자리를 가리킨다: "프로그램 폴더", "이 사용자의 설정 폴더", "Windows 폴더". 어떤 PC 에서는 프로그램 폴더가 C:\Program Files 이고 다른 PC 에서는 D:\Program Files 다. 사용자 이름도 PC 마다 다르다. 이 장은 Windows 가 그런 자리를 어떻게 부르는지 - 환경 변수, 알려진 폴더(known folder), Windows Installer 의 폴더 속성 - 그리고 각 이름이 언제 실제 경로로 바뀌는지 설명한다.

29.1 환경 변수란#

실행 중인 프로그램은 저마다 환경 변수라는 작은 목록을 지닌다: TEMP=C:\Users\<이름>\AppData\Local\Temp 처럼 이름과 글 값의 짝이다. 프로그램은 자기를 실행한 프로그램에게서 이 목록의 사본을 받는다. 자기 사본을 바꿔도 다른 프로그램에게는 아무것도 바뀌지 않는다. 이름은 대소문자를 가리지 않는다: %TEMP%, %Temp%, %temp% 는 같은 변수다.

도구마다 쓰는 방식이 다르다:

어디서변수를 쓰는 방식
명령 프롬프트(cmd.exe), 배치 파일%TEMP%
PowerShell$env:TEMP
REG_EXPAND_SZ 형식의 레지스트리 값, 바로 가기의 대상%TEMP%, 값을 읽을 때 바뀐다
Windows Installer 의 서식 문자열[%TEMP], 설치하는 동안 바뀐다

목록이 어디서 오는가: 사용자가 로그온하면 Windows 가 다음으로 목록을 만든다.

저장된 변수를 바꾸면 그 뒤에 시작한 프로그램에만 닿는다. 그래서 변수를 정하는 패키지([env.*], 튜토리얼 11장)를 설치한 뒤에는 명령 프롬프트를 새로 열어야 보인다.

29.2 흔히 쓰는 변수#

Windows 10·11 에서 드라이브가 C: 일 때의 흔한 값이다. <이름> 은 사용자의 계정 이름이다.

폴더#

변수흔한 값참고
SystemDriveC:Windows 가 시작한 드라이브. 백슬래시가 없다
SystemRootC:\WindowsWindows 폴더
windirC:\Windows같은 폴더의 옛 이름
ProgramFilesC:\Program Files64비트 Windows 의 32비트 프로그램에서는 C:\Program Files (x86)
ProgramFiles(x86)C:\Program Files (x86)64비트 Windows 에만 있다
ProgramW6432C:\Program Files64비트 Windows 에만 있다. 32비트 프로그램에서도 64비트 폴더
CommonProgramFilesC:\Program Files\Common Files여러 프로그램이 함께 쓰는 부품. (x86), W6432 형태는 위와 같다
ProgramDataC:\ProgramData모든 사용자가 함께 쓰는 데이터
ALLUSERSPROFILEC:\ProgramData같은 폴더의 옛 이름
PUBLICC:\Users\Public모든 사용자가 볼 수 있는 파일
USERPROFILEC:\Users\<이름>사용자의 프로필 폴더
HOMEDRIVE, HOMEPATHC:, \Users\<이름>사용자의 홈을 둘로 나눈 것. 도메인에서는 네트워크 공유(HOMESHARE)일 수 있다
APPDATAC:\Users\<이름>\AppData\Roaming로밍 프로필과 함께 옮겨 다니는 설정
LOCALAPPDATAC:\Users\<이름>\AppData\Local이 PC 에만 있는 설정과 캐시
TEMP, TMPC:\Users\<이름>\AppData\Local\Temp임시 파일. 서비스에서는 C:\Windows\Temp

오래된 안내서에 나오는 C:\Documents and Settings\<이름>\Application Data 같은 경로는 Windows XP 의 것이다. Windows Vista 부터 프로필은 C:\Users 아래에 있고, ALLUSERSPROFILE 은 C:\ProgramData 가 되었다.

Program Files 폴더가 둘이라서 32비트 프로그램이 %ProgramFiles% 를 물으면 C:\Program Files (x86) 을 받는다: Windows 는 프로그램마다 자기 종류의 폴더를 준다.

폴더가 아닌 것#

변수흔한 값참고
USERNAME<이름>계정 이름
USERDOMAINOFFICE, 또는 PC 이름계정의 도메인. 로컬 계정이면 컴퓨터 이름
LOGONSERVER\\DC01, 또는 \\ 와 PC 이름비밀번호를 확인한 컴퓨터
COMPUTERNAMEDESKTOP-1A2B3C이 PC 의 이름
ComSpecC:\Windows\system32\cmd.exe명령 해석기
PathC:\Windows\system32;C:\Windows;...폴더 없이 입력한 프로그램을 찾는 폴더들, ; 로 나눈다
PATHEXT.COM;.EXE;.BAT;.CMD;...확장자 없이 입력한 프로그램에 붙여 보는 확장자
OSWindows_NT
PROCESSOR_ARCHITECTUREAMD64, ARM64 또는 x8632비트 프로그램에서는 x86 이고, 실제 값은 PROCESSOR_ARCHITEW6432 에 있다
NUMBER_OF_PROCESSORS8

명령 프롬프트는 %CD%, %DATE%, %TIME%, %RANDOM%, %ERRORLEVEL% 에도 답하지만, 물을 때 지어내는 값이다. 환경에 들어 있지 않으므로 다른 프로그램은 보지 못한다.

29.3 변수가 없는 폴더#

바탕 화면, 시작 메뉴와 그 안의 프로그램 폴더, 시작 프로그램 폴더, 글꼴 폴더, 문서 폴더에는 환경 변수가 없다. Windows 는 이것들을 알려진 폴더로 부르고, 프로그램은 SHGetKnownFolderPath 로 묻는다. 변수가 있는 폴더도 이쪽이 믿을 만하다: 프로그램을 실행하는 쪽이 환경을 마음대로 줄 수 있고, 사용자가 문서나 바탕 화면을 다른 곳(예를 들어 OneDrive 안)으로 옮겼을 수 있는데, 그것은 알려진 폴더에만 반영된다.

29.4 세 시점#

이름은 세 시점 가운데 하나에서 경로가 되고, 그 시점이 누구의 경로인지를 정한다.

  1. 빌드할 때, rubrapack build 를 실행하는 기계에서. 대상 PC 에 대해서는 아직 아무것도 모른다. rubrapack 의 $(NAME) 변수가 여기서 바뀐다. 빌드 기계의 환경 변수는 읽지 않는다(값은 -D NAME=value 로 넘긴다).
  2. 설치할 때, 대상 PC 에서. Windows Installer 가 폴더 속성과 서식 문자열의 [%NAME] 부분을 설치하는 사용자의 것으로 알아낸다. 관리자가 설치하는 컴퓨터 전체용 패키지에서 "로컬 응용 프로그램 데이터" 폴더는 관리자의 것이다.
  3. 실행할 때, 프로그램이 값을 읽을 때마다. %LOCALAPPDATA%\Hello\log 를 담은 REG_EXPAND_SZ 값은 사용자마다 자기 폴더를 준다. 각 사용자의 프로그램이 그 사용자의 환경으로 풀기 때문이다.

그래서 사용자마다의 로그 폴더는 실행할 때를 위해 쓴다:

[registry.LogDir]
root = "HKLM"
key = 'SOFTWARE\Example Software\Hello'
name = "LogDir"
type = "expand"
value = '%LOCALAPPDATA%\Hello\log'        # 사용자마다 프로그램이 푼다

value = '[LocalAppDataFolder]Hello\log' 라고 쓰면 설치한 사용자의 폴더가 모든 사용자에게 저장된다.

29.5 Windows Installer 의 이름#

Windows Installer 에는 대부분의 폴더에 자기 속성이 있고, 설치할 때 값이 정해진다:

변수Windows Installer 속성
ProgramFiles64비트 패키지에서 ProgramFiles64Folder, 32비트 패키지에서 ProgramFilesFolder
ProgramFiles(x86)ProgramFilesFolder
CommonProgramFilesCommonFiles64Folder / CommonFilesFolder
ProgramData, ALLUSERSPROFILECommonAppDataFolder
APPDATAAppDataFolder
LOCALAPPDATALocalAppDataFolder
TEMPTempFolder
SystemRoot, windirWindowsFolder
SystemDriveWindowsVolume(백슬래시까지: C:\)
(System32)64비트 패키지에서 System64Folder. SystemFolder 는 32비트 시스템 폴더다
USERNAMELogonUser
COMPUTERNAMEComputerName

폴더 속성은 모두 백슬래시로 끝나므로 [ProgramFiles64Folder]Hello 사이에 백슬래시를 넣지 않는다. USERNAME 을 조심한다: Windows Installer 의 같은 이름 속성은 등록할 때 입력한 이름이지 계정이 아니다. 계정은 LogonUser 다. 속성이 없는 변수는 [%NAME] 으로 쓴다.

29.6 rubrapack 에서#

rubrapack 은 이 이름들을 모두 한 가지로 쓴다: Windows 의 철자로 쓴 $(NAME)(대소문자는 가리지 않는다). $$ 는 $ 한 글자다. 이름이 언제 바뀌는지는 놓인 자리가 정한다:

그래서 위의 사용자마다의 로그 폴더는 이렇게 쓴다:

[registry.LogDir]
root = "HKLM"
key = 'SOFTWARE\Example Software\Hello'
name = "LogDir"
type = "expand"
value = '$(LOCALAPPDATA)\Hello\log'       # %LOCALAPPDATA%\Hello\log 로 저장된다

type = "expand" 가 없으면 같은 값이 설치한 사용자의 폴더를 저장한다. 모든 이름과 그것이 무엇이 되는지는 참조 부의 Windows 이름에 표로 있다. MSIX 에는 설치할 때가 없다: 그것이 필요한 값은 거기서 거부하고(RP1612), 실행할 때의 형태는 프로그램이 풀므로 쓸 수 있다.

29.7 쓰이는 곳#