I'm on your side, when times get rough.

2009-02-10

MSI Package, ProductCode, UpgradeCode, Registry

Filed under: Programming — Peter_KIM @ 01:03

가끔 우리는 새롭게 작성한 응용 프로그램을 보다 쉽게 배포하기 위하여, “Visual Studio 2005(2008)”에서 생성한 “Windows Installer” 프로젝트를 만들어 MSI 설치 패키지를 생성하는 경우가 있습니다. 물론, MSI 설치 패키지 말고도, “Click Once”, 압축 파일 등의 방법을 이용하시는 분들도 있고, MSI 설치 패키지를 “Visual Studio 2005(2008)”이 아닌 다른 툴을 이용하시는 분들도 계실 것입니다.

 

지금부터 이야기하려는 것은 MSI 설치 패키지를 사용하여, 프로그램을 설치하고, 설치된 프로그램의 정보를 프로그램 언어를 이용하여 확인하는 방법입니다. 예전의 기억들을 떠올려보면, 현재 패키지를 구성하는 정보가, MSI 패키지를 어떤 툴을 이용하여 작성하느냐에 따라서 조금씩 달랐습니다. 물론, “Windows Installer”의 버전이 바뀌면서 추가되거나 개선된 사항들이 있어서 그럴 수도 있습니다. 그래서, “Visual Studio 2005(2008)”을 이용하지 않으시는 분들께서는 여기에 기술된 내용이 맞지 않을 수도 있습니다.

 

그럼, 먼저 “Visual Studio 2008“에서 “Windows Installer” 패키지를 살펴보겠습니다.

 설치 프로젝트를 만들고 나서, 솔루션 탐색기에서 프로젝트 항목을 선택하고, 속성을 보면 위의 그림처럼 프로젝트의 정보가 나타납니다.

먼저 “RemovePreviousVersions”항목을 “True” 값으로 설정합니다. (나중에 설치 패키지를 버전을 변경하여 재설치할 때 편의를 위해…)

여기서 주의 깊게 보아야 할 것이 있는데, “Version”, “ProductCode”, “UpgradeCode” 입니다.

버전 정보와 두 개의 GUID 값은 앞으로 우리가 살펴볼 내용의 중요한 요소가 됩니다.

주의: 사용자에 따라서, GUID 값은 당연히 달라질 것입니다. 설정된 값(“{01234567-ABCD-1234-5678-ABCDEF012345}”)을 보면 알겠지만, 설명을 돕기 위하여, “UpgradeCode” 값을 “GUIDGEN.EXE”와 같은 프로그램을 이용하지 않고, 수동으로 생성했습니다.

 

이 프로젝트를 빌드하면, 출력 디렉터리에 “Setup1.msi”와 같은 파일이 생성됩니다. 그럼 이 패키지를 설치하여, 시스템에 설치된 정보를 살펴 보겠습니다.

시스템에 설치된 정보는 제어판의 프로그램 추가/삭제”(“Vista”에서는 프로그램 및 기능이라고 합니다.)를 이용하는 하거나 레지스트리를 뒤져서 볼 수 있습니다.

 먼저 프로그램 추가/삭제를 이용하면, 아래와 같이 Setup.MSI 패키지가 설치된 것을 볼 수 있다.

 윈도우에서 설치된 패지의 정보는 시스템의 레지스트리의 아래 주소에 저장되어 있습니다.

[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall]

레지스트리 편집기를 이용하여 우리가 설치한 “Setup.MSI” 패키지 정보를 찾아보겠습니다.

위에 설명한 레지스트리 경로에서 설치 패키지에서 생성된 “ProductCode” 값을 갖는 항목을 찾으면, 아래의 그림과 같은 정보를 확인 할 수 있습니다.

 여기까지가 설치 패키지를 만들고, 설치된 패키지의 정보를 확인하는 기본 방법입니다. (다 아는건데 왜 떠들까…?)

이미 많은 사람들에게 배포된 응용 프로그램이 수정되고, 응용 프로그램의 수정에 필요했던 몇몇 파일을 수정된 프로그램 파일과 함께 다시 배포해야 하는 상황이 종종 발생합니다.

그래서 “Visual Studio”에서 설치 패키지를 수정했습니다. 이전에 배포된 설치 패키지와 다시 배포할 설치 패키지를 구별하기 위하여, 프로젝트의 속성에 있는 “Version” 항목의 값을 변경합니다.

주의: 이 값을 수정하면서, 이전 버전보다 아래 값으로 변경하는 이상 행동을 보이시는 분들이 가끔 있습니다. 가령 이전에 배포된 패키지의 버전이 “1.0.1”이라고 할 때, 현재 수정된 버전을 “1.0.0”으로 만드시는 분들…… 어떤 사람처럼 시대를 거꾸로 돌리는 이런 증상은 좀 자제하시길 바랍니다. , 절대로 “UpgradeCode” 값을 변경하지 마십시오.

 

버전을 증가시키면, “Visual Studio”는 이런 메시지를 보여 줍니다. 이럴 때, 우리는 긍정적인 마음 자세를 가지고, “를 선택합니다.

참고로, “Visual Studio”에서 추천하는 것을 거부하는 부정적인 마음으로 아니요를 선택하신 분들은 더 이상 이 글을 읽지 말아주세요.

아니요를 선택하고, 생성한 설치 패키지는, 이전에 설치한 패키지와 호환되지 않기 때문에, 새로 생성한 패키지로 응용 프로그램을 업데이트 하려면, 제어판의 프로그램 추가/제거에서 이전에 설치한 응용 프로그램을 제거하고, 새로 만든 패키지로 다시 새로 설치해야 하는 불편을 겪게 됩니다.

를 누르는 순간 “ProductCode” 값이 변경됩니다. 다시, 변경된 프로젝트를 빌드하고, 시스템에 설치합니다.

그럼, 이번에도 설치한 패키지의 “ProductCode” 값을 이용하여, 패키지의 정보를 알아야 하는 것일까요?

패키지가 업데이트 될 때마다, “ProductCode” 값의 변경이 발생하는 상황에서, 설치된 응용 프로그램의 정보를 얻기 위해 “UpgradeCode” 값은 유용하게 사용될 수 있습니다.

 

[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionInstallerUpgradeCodes]

 

레지스트리경로에서 방금전에 생성한 패키지의 “UpgradeCode”를 찾을 수 있습니다.

여기에서 약간의 알고리즘과 코드가 필요합니다. GUID 값을 눈으로 봐서는 도저히 찾을 수 없을 것입니다. 그래서 처음부터 “UpgradeCode “ 값을 수동으로 만든 것입니다.(눈에 보기 쉽게 하려고..) 설치 패키지에 설정된 “UpgradeCode” 값이 레지스트리에 저장될 때, 다음과 같이 값의 변경이 발생합니다.

예를 들면, 설치 패키지에서 사용한 "{01234567-ABCD-1234-5678-ABCDEF012345}" 값은 76543210DCBA43216587BADCFE103254으로 변경되어 레지스트리에 기록됩니다.

여기에 아주 간단한 규칙이 있습니다.

1.     xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 형식의 레지스트리에서 하이픈을 제거한다.

2.     첫 번째 8자리 문자열을 처음부터 끝까지 순서를 뒤집는다.

3.     두 번째 4자리 문자열을 처음부터 끝까지 순서를 뒤집는다.

4.     세 번째 4자리 문자열을 처음부터 끝까지 순서를 뒤집는다.

5.     네 번째 4자리 문자열의 홀수 번째와 짝수 번째의 값을 서로 바꾼다.

6.     다섯 번째 12 자리 문자열의 홀수 번째와 짝수 번째의 값을 서로 바꾼다.

 

간단히 코드로 표현하면 다음과 같습니다.

String sGuid = "01234567-ABCD-1234-5678-ABCDEF012345";

String sRetVal = "";

Char[] chArr = null;

 

sGuid = sGuid.Replace("-", "");

 

// 첫 번째 8자리 문자열을 처음부터 끝까지 순서를 뒤집는다.

chArr = sGuid.ToCharArray(0, 8);

for (int i = chArr.Length – 1; i >= 0; –i)

sRetVal += chArr[i];

 

// 두 번째 4자리 문자열을 처음부터 끝까지 순서를 뒤집는다.

chArr = sGuid.ToCharArray(8, 4);

for (int i = chArr.Length – 1; i >= 0; –i)

sRetVal += chArr[i];

 

// 세 번째 4자리 문자열을 처음부터 끝까지 순서를 뒤집는다.

chArr = sGuid.ToCharArray(12, 4);

for (int i = chArr.Length – 1; i >= 0; –i)

sRetVal += chArr[i];

 

// 네 번째 4자리 문자열의 홀수 번째와 짝수 번째의 값을 서로 바꾼다.

chArr = sGuid.ToCharArray(16, 4);

for (int i = 0; i < chArr.Length; i += 2)

{

sRetVal += chArr[i + 1];

sRetVal += chArr[i];

}

 

// 다섯 번째 12 자리 문자열의 홀수 번째와 짝수 번째의 값을 서로 바꾼다.

chArr = sGuid.ToCharArray(20, 12);

for (int i = 0; i < chArr.Length; i += 2)

{

sRetVal += chArr[i + 1];

sRetVal += chArr[i];

}

이렇게 변환한 값을 이용하여, “레지스트리를 살펴보면, 다음과 같은 정보를 확인 할 수 있습니다.

문자열 항목의 이름에 나타나는 “537D0DF551FA4F746A7BEEDBC347D587” 값을 자세히 보면, 이 값 역시 바로 “ProductCode” 값을 변형하여 만든 값이라는 것을 알 수 있습니다.

537D0DF551FA4F746A7BEEDBC347D587 {5FD0D735-AF15-47F4-A6B7-EEBD3C745D78}

그렇다면, 이 값을 위에서 설명한 변환 규칙을 거꾸로 적용하여, 원래의 코드 값을 구하고, 구해진 코드 값을 이용하면, 설치된 패키지의 정보를 획득할 수 있습니다.

그럼, 도대체 “PackageCode”는 무엇일까요? “Visual Studio”에 표시되지도 않는 이 값은, 다음 경로의 레지스트리에서 찾아볼 수 있습니다.

[HKEY_CLASSES_ROOTInstallerProducts]

[HKEY_LOCAL_MACHINESOFTWAREClassesInstallerProducts]

이 경로에서, 위에서 구한 “537D0DF551FA4F746A7BEEDBC347D587” 값을 갖는 키를 찾으면 다음과 같은 정보를 볼 수 있습니다.

더 깊숙히 들어가려니 지식의 한계와 시간적 제한으로 중단합니다.

 

모두 행복하십시오.

이글은 무제한 배포와 수정 허용합니다. 수정사항 있으면, 댓글 달아주세요…댓글이 되는지 모르겠군요.

블로그에 첫글…

Filed under: Programming — Peter_KIM @ 00:35
처음으로 블로그에 글을 써 봅니다.
인터넷을 사용한지도 어언 15년 이상이 되어가고, 프로그래머라는 직업을 갖고
먹고 산지도 꽤 되어가지만, 남아 있는건…
 
그래서, 여기에 조금이나마 무엇인가를 남기려고 합니다.
누구를 위해서도 아니고, 단지
나의 흔적을 그냥 끄적끄적…
 
2009.02.09 아침에.

Create a free website or blog at WordPress.com.