리소스에 저장된 버전 정보 얻기
프로그래밍 :
2005/09/17 00:41
| VC++을 이용해서 프로그램을 작성하면 리소스에 프로그램의 파일정보, 제품정보, 버전정보 등을 입력 하는 부분을 보았을 것이다. 바로 이렇게 생겼다. more.. 여기서 보이듯이 해당 프로그램에 대한 많은 정보를 저장 할 수 있다. 버전과 같은 것을 따로 저장해서 관리 하는 것 보다 이곳에 저장하면 편집도 쉽고 관리도 쉽다. 그렇지만 버전 정보가 크리티컬한 의미를 갖는 프로그램이라면 이곳에 저장을 하면 탐색기에서도 바로 보이고 쉽게 편집도 가능하기 때문에 이곳에 버전을 저장하여 관리 하는 것 보다 자체적으로 관리 하는 편이 좋다. 그렇지만 그런건 재껴두고.. 이곳의 정보를 적극 활용 하는 방법을 알아보자. 우선 이곳의 정보를 사용하기 위해서는 아래와 같은 함수들을 이용하여 얻어온다. DWORD GetFileVersionInfoSize( LPTSTR lptstrFilename, LPDWORD lpdwHandle ); BOOL GetFileVersionInfo( LPTSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData ); BOOL VerQueryValue( const LPVOID pBlock, LPTSTR lpSubBlock, PUINT lplpBuffer, PUINT puLen ); 위 함수들의 리턴 값과 인자에 대한 설명은 MSDN을 찾아보도록 하자. 그럼 예제를 보자. more.. 버전 정보를 얻어 오기 위해서는 우선 파일에 있는 버전정보 블럭의 크기를 알아와야 한다. 그러기 위해서는 GetFileVersionInfoSize함수를 사용한다. 그리고 GetFileVersionInfoSize 함수가 넘겨준 크기 만큼 메모리를 할당 한 후 이를 이용해서 버전블럭을 얻어온다. 그러기 위해서 GetFileVersionInfo함수를 이용해서 얻어온다. 여기에 들어가는 lpData는 void* 이므로 실제 사용하기 위해서는 캐스팅이 필요하다. 그것에 대해서는 아래에서 알아보자. 여기까지 오면 파일의 버전블럭에 저장된 정보를 얻어오게 된다. 그렇지만 이런 정보는 단순한 스트링 정보나 정수정보가 아닌 일종의 linked-list와 비슷한 구조를 가진다. 따라서 이러한 정보를 쉽게 얻기 위해서는 VerQueryValue함수를 이용한다. VerQueryValue 함수의 두번째 인자로 들어가는 lpSubBlock은 첫번째 인자로 주어지는 pBlock에서 어떤 서브블럭을 얻어올 것인가를 지정한다. 서브블럭은 아래와 같은 것이 있다. \ \VarFileInfo\Translation \StringFileInfo\lang-codepage\string-name 여기서 크게 \영역과 \VarFileInfo\Translation \StringFileInfo\lang-codepage\string-name영역으로 나눌 수 있다. \ 영역은 root 영역을 의미하며 아래 그림에 빨간색으로 표시된 영역의 정보를 나타낸다. more.. 우선 \영역의 포인터를 얻어보자 VerQueryValue(pByte, "\\", (LPVOID*)&pVersion, &nLen); 위의 코드를 실행하면 pVersion이라는 포인터는 \영역을 가르킨다. 이 곳에 들어있는 정보는 단순한 구조체이며 pVersion을 이 구조체의 포인터로 캐스팅만 하면 바로 사용 할 수 있다. VS_FIXEDFILEINFO *pvs = (VS_FIXEDFILEINFO *)pVersion; 위의 pvs를 열어보면 각종 정보가 들어있다. 구조체의 각 필드에 대한 자세한 설명은 MSDN을 찾아보면 된다. 그리고 위의 그림에 표기된 빨간 부분을 제외한 부분의 정보를 얻기 위해서는 \VarFileInfo\Translation와 \StringFileInfo\lang-codepage\string-name 를 이용하여 필요한 정보의 영역을 조합해야 한다. 우선 해야 할일은 파일의 버전정보의 언어와 코드페이지를 얻어와야 한다. 그렇기 위해서는 아래와 같이 하면 된다 VerQueryValue(pByte, "\\VarFileInfo\\Translation", (LPVOID*)&pVersion, &nLen); 위의 코드를 실행하면 pVersion라는 포인터는 언어와 코드페이지가 저장되어있는 DWORD 크기의 메모리를 가르키게 된다. 따라서 언어와 코드페이지를 읽기 위해서는 포인터가 가르키는 곳에서 32비트 만큼을 읽으면 된다. 이제 이 언어와 코드페이지를 이용해서 \StringFileInfo\lang-codepage\string-name 영역에서 lang-codepage를 조합하면 된다. 이 조합은 그냥 위에서 읽은 32비트에서 하위 16비트와 상위 16비트를 16진수형태의 스트링으로 만들면 된다 간단히 말하면 아래와 같다. char szTmp[256]; sprintf(szTmp, "%04x%04x", LOWORD(*pVersion), HIWORD(*pVersion) ); 그리고 나서 할 일은 실제 얻어올 정보를 의미하는 string-name를 지정하는 것이다. 얻어올 수 있는 string-name의 종류는 아래와 같다. more.. 각각의 의미는 아래의 그림에 빨간색으로 그려진 부분과 같다. more.. 만약에 FileVersion에 저장된 값을 얻고 싶으면 string-name에 FileVersion이라고 넣고 VerQueryValue 함수를 다시 호출하면 된다. 아래는 위에서 설명한 것에 대한 예제이다 UINT *pVersion; UINT nLen; char szTmp[256]; char *pBuf; VerQueryValue(pByte, "\\VarFileInfo\\Translation", (LPVOID *)&pVersion, (UINT*)&nLen)); // 버전 정보 sprintf(pByte, "\\StringFileInfo\\%04x%04x\\FileVersion", LOWORD(*pVersion), HIWORD(*pVersion)); VerQueryValue(pByte, szTmp, (LPVOID*)&pBuf, (UINT*)nLen)); CString strInfo; strInfo = (LPCTSTR)buffer; 위의 코드를 실행하면 strInfo에 그림에 나와있는 1.0.0.4가 잘 들어가 있을 것이다. 마지막으로 이러한 정보를 얻기 위해서 할당한 pByte를 delete[]하는 것을 잊지 말자. 각종 정보를 얻기 위해서 사용한 pByte를 제외한 포인터들은 pByte가 가르키는 메모리중에서 필요한 곳을 가르키는 포인터이므로 삭제 하지 않아도 된다(삭제하면 안된다! 반드시 pByte만 삭제해야 한다.) ps. 좀 더 자세한 사항을 알고 싶으면 아래로 가면 자세히 설명되어 있다. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/versioninformation.asp --written by chadr |








댓글을 달아 주세요