재배포 가능한 파일의 버전 확인
업데이트: 2007년 11월
항상 최신 버전의 파일만 설치되도록 하는 것이 중요합니다. 거의 모든 경우 새 버전의 DLL이나 구성 요소 위에 이전 버전을 설치하는 것이 아니라 이전 버전의 DLL이나 구성 요소 위에 새 버전을 설치해야 합니다. Kernel32.dll, User32.dll, Ole32.dll, ShDocVW.dll 등과 같은 시스템 DLL은 재배포할 수 없습니다. 파일을 재배포해야 하는 경우에는 반드시 관련 사용권 계약서를 읽고 파일을 해당 운영 체제 버전 및 설치 위치에 재배포할 수 있는지 확인해야 합니다. 대개 버전 확인 작업은 설치 프로그램에서 수행합니다.
사용자 지정 설치 프로그램을 작성하는 경우에는 재배포 가능한 파일을 설치할 때 수동으로 버전 정보를 확인해야 합니다. 이 항목에는 파일의 버전 번호를 확인하고 버전 번호가 없으면 타임스탬프를 확인하는 샘플 프로그램이 들어 있습니다.
예제
설명
다음 예제에서는 두 동적 라이브러리 또는 실행 파일 사이에 버전을 확인하는 방법을 보여 줍니다.
코드
// checkversion.cpp
// compile with: /link version.lib
#include <windows.h>
#include <stdio.h>
void EmitErrorMsg (HRESULT hr);
HRESULT GetFileVersion (char *filename, VS_FIXEDFILEINFO *vsf);
HRESULT GetFileDate (char *filename, FILETIME *pft);
HRESULT LastError();
int WhichIsNewer (char *fname1, char *fname2);
void printtime (FILETIME *t)
{
FILETIME lft;
FILETIME *ft = &lft;
FileTimeToLocalFileTime(t,ft);
printf_s("%08x %08x",ft->dwHighDateTime,ft->dwLowDateTime);
{
SYSTEMTIME stCreate;
BOOL bret = FileTimeToSystemTime(ft,&stCreate);
printf_s(" %02d/%02d/%d %02d:%02d:%02d\n",
stCreate.wMonth, stCreate.wDay, stCreate.wYear,
stCreate.wHour, stCreate.wMinute,
stCreate.wSecond);
}
}
int main(int argc, char* argv[])
{
printf_s("usage: checkversion file1 file2\n"
"\tReports which file is newer, first by checking "
"the file version in "
"\tthe version resource, then by checking the date\n\n" );
if (argc != 3)
return 1;
int newer = WhichIsNewer(argv[1],argv[2]);
switch(newer)
{
case 1:
case 2:
printf_s("%s is newer\n",argv[newer]);
break;
case 3:
printf_s("they are the same version\n");
break;
case 0:
default:
printf_s("there was an error\n");
break;
}
return !newer;
}
int WhichIsNewer (char *fname1, char *fname2)
{
// 1 if argv[1] is newer
// 2 if argv[2] is newer
// 3 if they are the same version
// 0 if there is an error
int ndxNewerFile;
HRESULT ret;
VS_FIXEDFILEINFO vsf1,vsf2;
if ( SUCCEEDED((ret=GetFileVersion(fname1,&vsf1))) &&
SUCCEEDED((ret=GetFileVersion(fname2,&vsf2))))
{
// both files have a file version resource
// compare by file version resource
if (vsf1.dwFileVersionMS > vsf2.dwFileVersionMS)
{
ndxNewerFile = 1;
}
else
if (vsf1.dwFileVersionMS < vsf2.dwFileVersionMS)
{
ndxNewerFile = 2;
}
else {
// if (vsf1.dwFileVersionMS == vsf2.dwFileVersionMS)
if (vsf1.dwFileVersionLS > vsf2.dwFileVersionLS) {
ndxNewerFile = 1;
}
else
if (vsf1.dwFileVersionLS < vsf2.dwFileVersionLS) {
ndxNewerFile = 2;
}
else
{
// if (vsf1.dwFileVersionLS == vsf2.dwFileVersionLS)
ndxNewerFile = 3;
}
}
}
else
{
// compare by date
FILETIME ft1,ft2;
if (SUCCEEDED((ret=GetFileDate(fname1,&ft1))) &&
SUCCEEDED((ret=GetFileDate(fname2,&ft2))))
{
LONG x = CompareFileTime(&ft1,&ft2);
if (x == -1)
ndxNewerFile = 2;
else
if (x == 0)
ndxNewerFile = 3;
else
if (x == 1)
ndxNewerFile = 1;
else
{
EmitErrorMsg(E_FAIL);
return 0;
}
}
else
{
EmitErrorMsg(ret);
return 0;
}
}
return ndxNewerFile;
}
HRESULT GetFileDate (char *filename, FILETIME *pft)
{
// we are interested only in the create time
// this is the equiv of "modified time" in the
// Windows Explorer properties dialog
FILETIME ct,lat;
HANDLE hFile = CreateFile(filename, GENERIC_READ,FILE_SHARE_READ |
FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
if (hFile == INVALID_HANDLE_VALUE)
return LastError();
BOOL bret = GetFileTime(hFile,&ct,&lat,pft);
if (bret == 0)
return LastError();
return S_OK;
}
// This function gets the file version info structure
HRESULT GetFileVersion (char *filename, VS_FIXEDFILEINFO *pvsf)
{
DWORD dwHandle;
DWORD cchver = GetFileVersionInfoSize(filename,&dwHandle);
if (cchver == 0)
return LastError();
char* pver = new char[cchver];
BOOL bret = GetFileVersionInfo(filename,dwHandle,cchver,pver);
if (!bret)
return LastError();
UINT uLen;
void *pbuf;
bret = VerQueryValue(pver,"\\",&pbuf,&uLen);
if (!bret)
return LastError();
memcpy(pvsf,pbuf,sizeof(VS_FIXEDFILEINFO));
delete[] pver;
return S_OK;
}
HRESULT LastError ()
{
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
if (SUCCEEDED(hr))
return E_FAIL;
return hr;
}
// This little function emits an error message
// based on WIN32 error messages
void EmitErrorMsg (HRESULT hr)
{
char szMsg[1024];
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
szMsg,
1024,
NULL
);
printf_s("%s\n",szMsg);
}