***.exe.mui 는 단일 파일로 존재하는 것이 아니라 메인이 되는 exe 가 존재하고 그 하위에 각 언어별로 폴더가 만들어져 있고 해당 폴더마다 해당 언어로 스트링테이블이 저장된 PE 파일, 즉 ***.exe.mui 파일이 존재한다.

간단히 말해 아래와 같은 형태로 존재한다.


SetupICC.exe

│  

├─ar-SA

│      setupicc.exe.mui

│      

├─cs-CZ

│      setupicc.exe.mui

│      

├─da-DK

│      setupicc.exe.mui

│      

├─de-DE

│      setupicc.exe.mui

│      

├─el-GR

│      setupicc.exe.mui

│      

├─en-US

│      setupicc.exe.mui

│      

├─es-ES

│      setupicc.exe.mui

│      

├─fi-FI

│      setupicc.exe.mui

│      

├─fr-FR

│      setupicc.exe.mui

│      

├─he-IL

│      setupicc.exe.mui

│      

├─hu-HU

│      setupicc.exe.mui

│      

├─it-IT

│      setupicc.exe.mui

│      

├─ja-JP

│      setupicc.exe.mui

│      

├─ko-KR

│      setupicc.exe.mui

│      

├─nb-NO

│      setupicc.exe.mui

│      

├─nl-NL

│      setupicc.exe.mui

│      

├─pl-PL

│      setupicc.exe.mui

│      

├─pt-BR

│      setupicc.exe.mui

│      

├─pt-PT

│      setupicc.exe.mui

│      

├─ru-RU

│      setupicc.exe.mui

│      

├─sk-SK

│      setupicc.exe.mui

│      

├─sl-SI

│      setupicc.exe.mui

│      

├─sv-SE

│      setupicc.exe.mui

│      

├─th-TH

│      setupicc.exe.mui

│      

├─tr-TR

│      setupicc.exe.mui

│      

├─zh-CN

│      setupicc.exe.mui

│      

└─zh-TW

        setupicc.exe.mui


exe.mui 파일은 결국 PE 파일이긴 하나 직접 다루는 것보다 윈도우에서 제공해주는 API를 이용하여 간편하게 추출할 수 있다.


일단, 레지스트리에 아래와 같은 키, 값이 있다고 가정하자.


DisplayName = Intel(R) Control Center

DisplayName_Localized = @C:\Program Files (x86)\Intel\Intel Control Center\Uninstaller\SetupICC.exe,-100


이럴 경우에는 DisplayName 에 있는 문자열을 그대로 사용해도 상관은 없으나 국제화(Localized)가 되어 있는 값이 있다는 뜻이므로 이왕이면 한글로 표기되어 있는 문자열을 뽑아내는 게 사용자 친화적이다.


이때에 사용할 수 있는 API 가 다음과 같다.


API 

 제약조건

 RegLoadMUIString

 Windows Vista 이상 ( 6.0 )

 SHLoadIndirectString 

 Windows XP 이상 ( 5.1 )

 LoadMUILibrary

 Windows NT 이상 ( 3.1 )


세가지 API 가 있는데, 클라이언트 윈도우 버전에 따라 선택하여 사용하면 된다.

당연하게, 상위버전의 API 일수록 사용하기 더 편하다.


간단한 예를 보자.


1) RegLoadMUIString : 로컬라이징된 값이 있는 레지스트리 핸들과 해당 키를 던져 주면 결과를 돌려준다.


DWORD size;
TCHAR szLocalized[MAX_PATH];
RegLoadMUIString( hKey, _T("DisplayName_Localized"), szLocalized, MAX_PATH, &size, NULL, NULL );



결과 : szLocalized = "인텔® 관리 엔진 구성 요소"


2) SHLoadIndirectString : DisplayName_Localized 값을 일단 추출한 후 해당 값을 넣어 주면된다.


SHLoadIndirectString( _T("@C:\Program Files (x86)\Intel\Intel Control Center\Uninstaller\SetupICC.exe,-100") , szLocalized, MAX_PATH, NULL );


결과 : szLocalized = "인텔® 관리 엔진 구성 요소"


3) LoadMUILibrary : DisplayName_Localized 값을 파싱하고 해당 EXE 혹은 DLL 을 로드해서 직접 스트링테이블의 값을 추출해야 한다.



#include "stdafx.h"
#include 
#include 
#pragma comment(lib, "muiload.lib")

BOOL LoadMUIString( LPCTSTR pszFormString, LPTSTR pszBuffer, int cchBufferMax)
{
	int iResIdx;
	TCHAR szModule[MAX_PATH];

	if ( _stscanf(pszFormString, _T("@%[^,],-%d"), szModule, &iResIdx) == 2 )
	{
		HINSTANCE hInst = LoadMUILibrary( szModule, MUI_LANGUAGE_NAME, NULL );
		if ( hInst )
		{
			LoadString(hInst, iResIdx, pszBuffer, cchBufferMax );
			FreeMUILibrary(hInst);
			return TRUE;
		}
	}
	else
		return FALSE;
}

void main()
{
	TCHAR szLocalizedString[MAX_PATH];
	LPCTSTR DisplayName_Localized = _T("@C:\\Program Files (x86)\\Intel\\Intel Control Center\\Uninstaller\\SetupICC.exe,-100");
	
	LoadMUIString(DisplayName_Localized, szLocalizedString, MAX_PATH);
	
	printf("%S", szLocalizedString);
}

살펴본 3개의 방법 중에 클라이언트의 상황에 맞는 방법으로 구현하면 된다.


  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기