고수닷넷 - 데미소다오렌지님
1. GetFileVersion
PE 파일 포맷의 버전을 구하는 함수로 윈도우에서는 GetFileVersionInfo 함수를 지원해 줍니다. 하지만 해당 함수의 사용을 위해서는 다소 복잡한 과정을 거쳐야 합니다. 또한 GetFileVersionInfo의 경우 버전 넘버가 아닌 버전에 관한 모든 정보를 구하는 함수이므로 단순히 버전을 구할때 사용하려면 불편하기도 합니다. 이러한 불편한 점을 한방에 해결해 주는 함수 GetFileVersion 함수를 만들어 보도록 합시다.
우리가 만들 함수는 단순하게 지정된 패스의 버전만 구해내면 됩니다. 따라서 입력 파라미터로는 파일의 패스와 함께 버전 정보가 리턴될 구조체를 사용할 것 입니다. 리턴값으로는 함수의 성공 여부를 BOOL 형태로 리턴하는 것이 좋을 것 같습니다. 이렇게 생각해 낸 함수 원형은 아래와 같습니다.
BOOL GetFileVersion(LPCTSTR lpszFilePath, VS_FIXEDFILEINFO *pvffi);
VS_FIXEDFILEINFO에 관해서 잠시 알아보도록 합시다. VS_FIXEDFILEINFO는 아래와 같이 정의된 구조체입니다.
DWORD dwSignature;
DWORD dwStrucVersion;
DWORD dwFileVersionMS;
DWORD dwFileVersionLS;
DWORD dwProductVersionMS;
DWORD dwProductVersionLS;
DWORD dwFileFlagsMask;
DWORD dwFileFlags;
DWORD dwFileOS;
DWORD dwFileType;
DWORD dwFileSubtype;
DWORD dwFileDateMS;
DWORD dwFileDateLS;
};
여기서 버전 넘버와 관련된 값은 dwFileVersionMS와 dwFileVersionLS입니다. 각각, 64비트 파일 버전의 상위 32비트와 하위 32비트를 구성하는 값 입니다.
이젠 실제 함수 구현을 한번 살펴보도록 합시다. GetFileVersionInfoSize, GetFileVersionInfo API를 사용하기 위해서는 version.h를 포함시켜야 하며, version.lib를 링크시에 같이 링크시켜 줘야 합니다. GetFileVersionInfoSize는 버전 정보의 크기를 구하는 함수이며, GetFileVersion은 실제 버전 정보를 구하는 함수 입니다. VerQueryValue는 구해진 버전 정보내에서 원하는 부분을 구해내는 함수입니다.
중요한 두가지 부분을 살펴보도록 하겠습니다.
위 라인은 파일의 버전 정보를 구해서 pByte 영역으로 복사해 주는 역할을 합니다.
위 라인은 구해진 pByte 내에서 위에서 언급한 VS_FIXEDFILEVERSION 부분을 가리키는 영역을 구하는 함수입니다. 여기서 pvffi0는 pByte의 특정 영역을 가리키는 포인터를 리턴합니다. 따라서 pvffi0로는 단순한 포인터의 포인터를 넘기면 됩니다.
#include "version.h"
#pragma comment(lib, "version.lib")
BOOL GetFileVersion(LPCTSTR lpszFilePath, VS_FIXEDFILEINFO *pvffi)
{
BOOL bRet = FALSE;
DWORD dwSize;
BYTE *pByte;
VS_FIXEDFILEINFO *pvffi0;
UINT nLen = sizeof *pvffi0;
dwSize = GetFileVersionInfoSize(lpszFilePath, NULL);
if(dwSize > 0)
{
pByte = new BYTE[dwSize];
if(GetFileVersionInfo(lpszFilePath, NULL, dwSize, pByte) == TRUE &&
VerQueryValue(pByte, "\\", (LPVOID*) &pvffi0, &nLen) == TRUE)
{
memcpy(pvffi, pvffi0, sizeof *pvffi);
bRet = TRUE;
}
delete [] pByte;
}
return bRet;
}
2. CompareVersion
이제 위에서 구한 버전 정보를 실제로 비교하는 함수를 만들어 봅시다. 두개의 버전 정보를 받아서 int형을 리턴하는 함수로 만들어 보겠습니다.
위는 이 함수의 원형입니다. a0, a1을 입력 버전으로 받습니다. 리턴값은 0일 경우 두개의 버전이 동일한 것이며, 0보다 크면 a0가 큰것이고, 0보다 작다면 a0가 작은 것 입니다.
실제 구현을 한번 살펴봅시다. 별로 어려운 코드도 아니며, 특수한 내용이 있는 코드도 아닙니다. 단지 살펴볼만한 부분은 실제 버전 정보가 64비트이기 때문에, 32비트씩 나눠서 비교한다는 것 입니다. 아래와 같이 32비트의 뺄셈을 통해서 비교를 하는 것은 자주 사용되기 때문에 한번쯤 살펴보는 것도 좋겠네요.
int CompareVersion(VS_FIXEDFILEINFO *a0, VS_FIXEDFILEINFO *a1)
{
int nRet = 0;
int diffMS, diffLS;
diffMS = a1->dwFileVersionMS - a0->dwFileVersionMS;
diffLS = a1->dwFileVersionLS - a0->dwFileVersionLS;
if(diffMS == 0)
nRet = diffLS;
else
nRet = diffMS;
return nRet;
}
3. 테스트
이제껏 디자인한 함수를 사용해 보도록 하겠습니다. 아래는 system32에 있는 kernel32.dll과 gdi32.dll의 버전 정보를 비교하는 방법을 보여줍니다.
VS_FIXEDFILEINFO a1;
GetFileVersion("c:\\winnt\\system32\\kernel32.dll", &a0);
GetFileVersion("c:\\winnt\\system32\\gdi32.dll", &a1);
if(CompareVersion(&a0, &a1) > 0)
AfxMessageBox("new");
else
AfxMessageBox("older or same");
- 시스템 트레이 사용하기 (0)2006/12/29
- 메모리 오류 (0)2006/12/27
- 파일 버전 구해서 비교하기... (0)2006/12/08
- 재밌는 시스템 강제로 다운시키기 (0)2006/12/08
- CDROM Insertion/Removal 감지하기 (0)2006/12/05

수안이의 컴퓨터 연구실



Leave your greetings.