RJV
asked on
Application's version, copyright, etc
Is it possible to use the version resources in VC++ to insert the likes of the application's version, copyright, name, etc into a string? Or, must one declare that elsewhere? The goal is to display that and keep only one version control.
If it is possible, how?
Thanks for your input in advance!
RJV
If it is possible, how?
Thanks for your input in advance!
RJV
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Thats precisely what I described. I want the version number to be updated in the RC file.
but I dont want to do it manually. This is very the console application comes in. It parses
.RC file as a regular text file, and increments the necessary digits in the .RC file.
Compiler than recompiles it, causing updated versioninfo to be stamped into your project.
I used to update it everytime, but you could easily make it dependant on some key file
of your project.
Unfortunately I cannot give you the source of console app, because I lost the code,
(I still have executable which adds my companys name, my name and several such trivia)
I can however send you the CVersion class that wraps around the VERSIONINFO
structure. You can use this class in aboutbox, splash screen or even in your other part of
application that may be version dependant.
send me your email address if you need it.
but I dont want to do it manually. This is very the console application comes in. It parses
.RC file as a regular text file, and increments the necessary digits in the .RC file.
Compiler than recompiles it, causing updated versioninfo to be stamped into your project.
I used to update it everytime, but you could easily make it dependant on some key file
of your project.
Unfortunately I cannot give you the source of console app, because I lost the code,
(I still have executable which adds my companys name, my name and several such trivia)
I can however send you the CVersion class that wraps around the VERSIONINFO
structure. You can use this class in aboutbox, splash screen or even in your other part of
application that may be version dependant.
send me your email address if you need it.
ASKER
Hi,
Yes, I'd be interested in your CVersion class as this is my goal. Namely, take info from one place, where it already exists, rather than having to keep extra headers just for this purpose. The extra header concept doesn't seem very efficient, particularly as the information already exists.
You can email me at rjv@dispro.com.br.
RJV
Yes, I'd be interested in your CVersion class as this is my goal. Namely, take info from one place, where it already exists, rather than having to keep extra headers just for this purpose. The extra header concept doesn't seem very efficient, particularly as the information already exists.
You can email me at rjv@dispro.com.br.
RJV
I was about to offer my code for access to resources as well.
What the heck .. this is the sort of thing I do...
What the heck .. this is the sort of thing I do...
class CMyWinApp : public CWinApp {
// ...
private:
CString m_ProgramPathAndName;
int m_fv[4]; // file version
int m_pv[4]; // product version
CString m_Comments;
CString m_CompanyName;
CString m_CompanyName;
CString m_FileDescription;
CString m_InternalName;
CString m_LegalCopyright;
CString m_LegalTrademarks;
CString m_OriginalFilename;
CString m_PrivateBuild;
CString m_ProductName;
CString m_SpecialBuild;
};
const CString& CMyWinApp::ProgramPathAndN ame() {
if (m_ProgramPathAndName.IsEm pty()) {
char *buffer = m_ProgramPathAndName.GetBu ffer(_MAX_ PATH);
bool ok = ::GetModuleFileName(0,buff er,_MAX_PA TH) != 0;
m_ProgramPathAndName.Relea seBuffer() ;
}
return m_ProgramPathAndName;
}
CString CMyWinApp::GetVersionInfoF ield (LPCTSTR name, void* bufVersionInfo, WORD* pLanguage) {
CString key;
key.Format("\\StringFileIn fo\\%04X%0 4x\\%s",*( (WORD*)pLa nguage),*( ((WORD*)pL anguage)+1 ),name);
UINT ulen;
char* bufString;
if (! ::VerQueryValue(bufVersion Info, const_cast<char*>(LPCTSTR( key)), reinterpret_cast<LPVOID*>( &bufString ), &ulen)) return CString();
return CString(bufString, ulen+1);
}
void CMyWinApp::GetVersionInfo () {
char* path = const_cast<char*>(LPCTSTR( ProgramPat hAndName() ));
DWORD hVerDummy;
DWORD dwVersionInfoSize = ::GetFileVersionInfoSize(p ath,&hVerD ummy);
if (dwVersionInfoSize == 0L) return;
void* bufVersionInfo = malloc(dwVersionInfoSize);
if (! bufVersionInfo) return;
if (::GetFileVersionInfo(path ,hVerDummy ,dwVersion InfoSize,b ufVersionI nfo)) {
UINT ulen;
// Get Version Info
VS_FIXEDFILEINFO *bufFixedFileInfo;
if (::VerQueryValue(bufVersio nInfo,"\\" ,reinterpr et_cast<LP VOID*>(&bu fFixedFile Info), &ulen)){
m_fv[0] = HIWORD(bufFixedFileInfo->d wFileVersi onMS);
m_fv[1] = LOWORD(bufFixedFileInfo->d wFileVersi onMS);
m_fv[2] = HIWORD(bufFixedFileInfo->d wFileVersi onLS);
m_fv[3] = LOWORD(bufFixedFileInfo->d wFileVersi onLS);
m_pv[0] = HIWORD(bufFixedFileInfo->d wProductVe rsionMS);
m_pv[1] = LOWORD(bufFixedFileInfo->d wProductVe rsionMS);
m_pv[2] = HIWORD(bufFixedFileInfo->d wProductVe rsionLS);
m_pv[3] = LOWORD(bufFixedFileInfo->d wProductVe rsionLS);
}
WORD* pLanguage;
if(::VerQueryValue(bufVers ionInfo, "\\VarFileInfo\\Translatio n", reinterpret_cast<LPVOID*>( &pLanguage ), &ulen) && ulen != 0) {
m_Comments = GetVersionInfoField ("Comments",bufVersionInfo ,pLanguage );
m_CompanyName = GetVersionInfoField ("CompanyName",bufVersionI nfo,pLangu age);
m_FileDescription = GetVersionInfoField ("FileDescription",bufVers ionInfo,pL anguage);
m_InternalName = GetVersionInfoField ("InternalName",bufVersion Info,pLang uage);
m_LegalCopyright = GetVersionInfoField ("LegalCopyright",bufVersi onInfo,pLa nguage);
m_LegalTrademarks = GetVersionInfoField ("LegalTrademarks",bufVers ionInfo,pL anguage);
m_OriginalFilename = GetVersionInfoField ("OriginalFilename",bufVer sionInfo,p Language);
m_PrivateBuild = GetVersionInfoField ("PrivateBuild",bufVersion Info,pLang uage);
m_ProductName = GetVersionInfoField ("ProductName",bufVersionI nfo,pLangu age);
m_SpecialBuild = GetVersionInfoField ("SpecialBuild",bufVersion Info,pLang uage);
}
}
free(bufVersionInfo);
}
const int* CMyWinApp::FileVersion () {
if (m_fv[0] < 0) GetVersionInfo();
return m_fv;
}
const int* CMyWinApp::ProductVersion () {
if (m_pv[0] < 0) GetVersionInfo();
return m_pv;
}
const CString& CMyWinApp::Comments () {
if (m_Comments.IsEmpty()) GetVersionInfo();
return m_Comments;
}
const CString& CMyWinApp::CompanyName () {
if (m_CompanyName.IsEmpty()) GetVersionInfo();
return m_CompanyName;
}
const CString& CMyWinApp::FileDescription () {
if (m_FileDescription.IsEmpty ()) GetVersionInfo();
return m_FileDescription;
}
const CString& CMyWinApp::InternalName () {
if (m_InternalName.IsEmpty()) GetVersionInfo();
return m_InternalName;
}
const CString& CMyWinApp::LegalCopyright () {
if (m_LegalCopyright.IsEmpty( )) GetVersionInfo();
return m_LegalCopyright;
}
const CString& CMyWinApp::LegalTrademarks () {
if (m_LegalTrademarks.IsEmpty ()) GetVersionInfo();
return m_LegalTrademarks;
}
const CString& CMyWinApp::OriginalFilenam e () {
if (m_OriginalFilename.IsEmpt y()) GetVersionInfo();
return m_OriginalFilename;
}
const CString& CMyWinApp::PrivateBuild () {
if (m_PrivateBuild.IsEmpty()) GetVersionInfo();
return m_PrivateBuild;
}
const CString& CMyWinApp::ProductName () {
if (m_ProductName.IsEmpty()) GetVersionInfo();
return m_ProductName;
}
const CString& CMyWinApp::SpecialBuild () {
if (m_SpecialBuild.IsEmpty()) GetVersionInfo();
return m_SpecialBuild;
}
// ...
private:
CString m_ProgramPathAndName;
int m_fv[4]; // file version
int m_pv[4]; // product version
CString m_Comments;
CString m_CompanyName;
CString m_CompanyName;
CString m_FileDescription;
CString m_InternalName;
CString m_LegalCopyright;
CString m_LegalTrademarks;
CString m_OriginalFilename;
CString m_PrivateBuild;
CString m_ProductName;
CString m_SpecialBuild;
};
const CString& CMyWinApp::ProgramPathAndN
if (m_ProgramPathAndName.IsEm
char *buffer = m_ProgramPathAndName.GetBu
bool ok = ::GetModuleFileName(0,buff
m_ProgramPathAndName.Relea
}
return m_ProgramPathAndName;
}
CString CMyWinApp::GetVersionInfoF
CString key;
key.Format("\\StringFileIn
UINT ulen;
char* bufString;
if (! ::VerQueryValue(bufVersion
return CString(bufString, ulen+1);
}
void CMyWinApp::GetVersionInfo () {
char* path = const_cast<char*>(LPCTSTR(
DWORD hVerDummy;
DWORD dwVersionInfoSize = ::GetFileVersionInfoSize(p
if (dwVersionInfoSize == 0L) return;
void* bufVersionInfo = malloc(dwVersionInfoSize);
if (! bufVersionInfo) return;
if (::GetFileVersionInfo(path
UINT ulen;
// Get Version Info
VS_FIXEDFILEINFO *bufFixedFileInfo;
if (::VerQueryValue(bufVersio
m_fv[0] = HIWORD(bufFixedFileInfo->d
m_fv[1] = LOWORD(bufFixedFileInfo->d
m_fv[2] = HIWORD(bufFixedFileInfo->d
m_fv[3] = LOWORD(bufFixedFileInfo->d
m_pv[0] = HIWORD(bufFixedFileInfo->d
m_pv[1] = LOWORD(bufFixedFileInfo->d
m_pv[2] = HIWORD(bufFixedFileInfo->d
m_pv[3] = LOWORD(bufFixedFileInfo->d
}
WORD* pLanguage;
if(::VerQueryValue(bufVers
m_Comments = GetVersionInfoField ("Comments",bufVersionInfo
m_CompanyName = GetVersionInfoField ("CompanyName",bufVersionI
m_FileDescription = GetVersionInfoField ("FileDescription",bufVers
m_InternalName = GetVersionInfoField ("InternalName",bufVersion
m_LegalCopyright = GetVersionInfoField ("LegalCopyright",bufVersi
m_LegalTrademarks = GetVersionInfoField ("LegalTrademarks",bufVers
m_OriginalFilename = GetVersionInfoField ("OriginalFilename",bufVer
m_PrivateBuild = GetVersionInfoField ("PrivateBuild",bufVersion
m_ProductName = GetVersionInfoField ("ProductName",bufVersionI
m_SpecialBuild = GetVersionInfoField ("SpecialBuild",bufVersion
}
}
free(bufVersionInfo);
}
const int* CMyWinApp::FileVersion () {
if (m_fv[0] < 0) GetVersionInfo();
return m_fv;
}
const int* CMyWinApp::ProductVersion () {
if (m_pv[0] < 0) GetVersionInfo();
return m_pv;
}
const CString& CMyWinApp::Comments () {
if (m_Comments.IsEmpty()) GetVersionInfo();
return m_Comments;
}
const CString& CMyWinApp::CompanyName () {
if (m_CompanyName.IsEmpty()) GetVersionInfo();
return m_CompanyName;
}
const CString& CMyWinApp::FileDescription
if (m_FileDescription.IsEmpty
return m_FileDescription;
}
const CString& CMyWinApp::InternalName () {
if (m_InternalName.IsEmpty())
return m_InternalName;
}
const CString& CMyWinApp::LegalCopyright () {
if (m_LegalCopyright.IsEmpty(
return m_LegalCopyright;
}
const CString& CMyWinApp::LegalTrademarks
if (m_LegalTrademarks.IsEmpty
return m_LegalTrademarks;
}
const CString& CMyWinApp::OriginalFilenam
if (m_OriginalFilename.IsEmpt
return m_OriginalFilename;
}
const CString& CMyWinApp::PrivateBuild () {
if (m_PrivateBuild.IsEmpty())
return m_PrivateBuild;
}
const CString& CMyWinApp::ProductName () {
if (m_ProductName.IsEmpty()) GetVersionInfo();
return m_ProductName;
}
const CString& CMyWinApp::SpecialBuild () {
if (m_SpecialBuild.IsEmpty())
return m_SpecialBuild;
}
ASKER
Hi ROnslow,
I had a feeling there wasn't any straight forward solution, though that doesn't make much sense. After all, to keep things organized means more code size than simply keeping the same information in two different places. That's why I refused to believe there wouldn't be a simpler solution and came here for help.
I'll check it out and get back here. It looks like both of you deserve the credits (though I haven't received the email).
RJV
I had a feeling there wasn't any straight forward solution, though that doesn't make much sense. After all, to keep things organized means more code size than simply keeping the same information in two different places. That's why I refused to believe there wouldn't be a simpler solution and came here for help.
I'll check it out and get back here. It looks like both of you deserve the credits (though I haven't received the email).
RJV
ASKER
Hi ROnslow,
Arghhh! This one is indeed a first! I've never had a link error with a Win32 function. Unbelievably, this one struck 'gold', with these unresolved externals:
_VerQueryValueA@16
_GetFileVersionInfoA@16
_GetFileVersionInfoSizeA@8
What did you do on the #include 'front' to overcome this?
Thanks again!
RJV
Arghhh! This one is indeed a first! I've never had a link error with a Win32 function. Unbelievably, this one struck 'gold', with these unresolved externals:
_VerQueryValueA@16
_GetFileVersionInfoA@16
_GetFileVersionInfoSizeA@8
What did you do on the #include 'front' to overcome this?
Thanks again!
RJV
It's not a #include that is missing .. otherwise it would be a compile time error instead.
You need to add "version.lib" to your link Object Modules/Libraries line (don't forget to do it for both debug and release).
You need to add "version.lib" to your link Object Modules/Libraries line (don't forget to do it for both debug and release).
ASKER
I'll check it out and let you know.
RJV
RJV, I believe, my CVersion class is lot better than implementing it in CWinApp class.
However, Since Iam accessing the web right now from a client site, I will get someone to
send me an attachment tommorow and I will send it over.
Send me your email address, (one that can accept attachments) if you can.
RJV, I believe, my CVersion class is lot better than implementing it in CWinApp class.
However, Since Iam accessing the web right now from a client site, I will get someone to
send me an attachment tommorow and I will send it over.
Send me your email address, (one that can accept attachments) if you can.
Hold on a minute,
I talked to a colleague and he mentioned that there is some code in site
called www.codeguru.com
sure enough there is (it was made by Robert Rocco)
His design is preety much same as mine, (function name and class name are different)
But hey it should work.
This is the URL.
http://www.codeguru.com/misc/version_info_from_resource.shtml
If you get lost in that site, go to homepage, jump to link called "misc" and scroll down
till you see phrase like "VersionInfo from ... Resource file"
I will send my version of CVersion (pun intended) as soon as I can.
Ciao
I talked to a colleague and he mentioned that there is some code in site
called www.codeguru.com
sure enough there is (it was made by Robert Rocco)
His design is preety much same as mine, (function name and class name are different)
But hey it should work.
This is the URL.
http://www.codeguru.com/misc/version_info_from_resource.shtml
If you get lost in that site, go to homepage, jump to link called "misc" and scroll down
till you see phrase like "VersionInfo from ... Resource file"
I will send my version of CVersion (pun intended) as soon as I can.
Ciao
Sorry for Information overload.
There is one more version of the same class at that site by Manual Laflamme (spelling not
sure)
There is one more version of the same class at that site by Manual Laflamme (spelling not
sure)
You'll have plenty of alternatives to choose from.
I agree that a separate class is probably better than adding a class to CWinApp. However, that is just what MFC do for registry access (put GetProfileString etc to CWinApp). So either solution will work.
Perhaps the compromise is to add access to CVersion (or whatever) into your CWinApp class. That way the CWinApp class can wrap the calls to CVersion so that CVersion will know to look in the current application's resources. (That is assuming CVersion is a class that can read from any exe/dll).
I agree that a separate class is probably better than adding a class to CWinApp. However, that is just what MFC do for registry access (put GetProfileString etc to CWinApp). So either solution will work.
Perhaps the compromise is to add access to CVersion (or whatever) into your CWinApp class. That way the CWinApp class can wrap the calls to CVersion so that CVersion will know to look in the current application's resources. (That is assuming CVersion is a class that can read from any exe/dll).
RONSLOW
Actually, I see the problem you are hinting at.
This is what I have done.
I have two constructors in CVersion object.
In first constructor, you can specify the filename you want to look into with full path
I did this with intention that I could see versions of my other dependat files (Application that i developed is spread over
4 executables and 3 dlls) on the same about box.
Somehow my boss rejected the idea, so I never actually did it.
In second constructor, I look for the resource in current executable.
This I accomplish by use of global MFC function
AfxGetApp and then get the module handle and ultimately
the executable name.
(preety much the same functions that you posted in code earlier)
{ God I wish MFC had simple thing like App.Path like Visual basic :---( }
Motive behind this is :
Since I don't really need the precise App class. I do not need to cast it to current application derived CWinApp.
I hope I have made myself clear.
Actually, I see the problem you are hinting at.
This is what I have done.
I have two constructors in CVersion object.
In first constructor, you can specify the filename you want to look into with full path
I did this with intention that I could see versions of my other dependat files (Application that i developed is spread over
4 executables and 3 dlls) on the same about box.
Somehow my boss rejected the idea, so I never actually did it.
In second constructor, I look for the resource in current executable.
This I accomplish by use of global MFC function
AfxGetApp and then get the module handle and ultimately
the executable name.
(preety much the same functions that you posted in code earlier)
{ God I wish MFC had simple thing like App.Path like Visual basic :---( }
Motive behind this is :
Since I don't really need the precise App class. I do not need to cast it to current application derived CWinApp.
I hope I have made myself clear.
Here is my source code. I have not delved too deep into different language issues,
but you can go ahead and add it.
CVersion.h
>>>>>>>
#include "winver.h"
/*
This class works as follows
Whenever you need version information, create a cversion object either on stack or
by new
After creation, call Init member function and check the return value.
If value is true, use the version object, else dont use it
To obtain fileversion and productversion, use respective functions
To obtain any other information, use getvariableinfo function,
supply the key value and place holder for return value.
All functions return true on success, false on failure
*/
class CVersion
{
public:
CVersion();
CVersion(LPCSTR strFileName);
~CVersion();
BOOL Init();
BOOL GetFileVersion(CString &strVer);
BOOL GetProductVersion(CString &strVer);
BOOL GetVariableInfo(LPCSTR strKey, CString &strValue);
private:
VS_FIXEDFILEINFO m_FixedInfo;
char *m_lpData; // contains the entire Structure
BOOL m_bValid;
BOOL m_bLangFound;
DWORD m_structSize;
CString m_strLanguage;
CString m_strFileName;
void GetLanguageID(CString &strLangID) {strLangID = m_strLanguage;};
};
<<<<<<
CVersion.cpp
>>>>>>
#include "stdafx.h"
#include "cversion.h"
// Link Library add Version.lib
CVersion::CVersion()
{
m_lpData = NULL;
m_bValid = FALSE;
m_bLangFound = FALSE;
}
CVersion::CVersion(LPCSTR strFileName)
: m_strFileName(strFileName)
{
m_lpData = NULL;
m_bValid = FALSE;
m_bLangFound = FALSE;
}
#define SUFFICIENTLY_LARGE_BUFFER 500
BOOL CVersion::Init()
{
CString strName;
char *szName;
DWORD temp;
if (m_strFileName.IsEmpty())
{
szName = strName.GetBuffer(SUFFICIE NTLY_LARGE _BUFFER);
/////////////////////////
// Get the executable name
if (GetModuleFileName(AfxGetA pp()->m_hI nstance, szName, SUFFICIENTLY_LARGE_BUFFER) == 0)
{
strName.ReleaseBuffer();
return FALSE;
}
strName.ReleaseBuffer();
} else
{
strName = m_strFileName;
}
// We still need a char *
szName = strName.GetBuffer();
/////////////////////////
// Get the Version Information of the executable
m_structSize = ::GetFileVersionInfoSize(s zName, &temp);
if (m_structSize == 0)
{
strName.ReleaseBuffer();
return FALSE;
}
m_lpData = new char [m_structSize];
if (!GetFileVersionInfo(szNam e, 0, m_structSize, m_lpData))
{
delete [] m_lpData;
m_lpData = NULL;
strName.ReleaseBuffer();
return FALSE;
}
/////////////////////////
// Now retrieve the fixedinfo structure from the version info
LPVOID lplpBuff;
UINT nLen;
VerQueryValue(m_lpData, "\\", &lplpBuff, &nLen);
memcpy(&m_FixedInfo, lplpBuff, sizeof(VS_FIXEDFILEINFO));
/////////////////////////
// Now Determine the language id
char *szLangugeID;
if (VerQueryValue(m_lpData,"\ \VarFileIn fo\\Transl ation",
&lplpBuff, &nLen))
{
UINT nLangMajor = 0;
UINT nLangMinor = 0;
szLangugeID = (char *)lplpBuff;
// pick up the first language
// for the more ambitious move, create an array and capture
// all the language values
memcpy(&nLangMajor, szLangugeID, 2);
memcpy(&nLangMinor, szLangugeID + 2, 2);
m_strLanguage.Format("%04X %04X",nLan gMajor, nLangMinor);
m_bLangFound = TRUE;
} else
{
// Default to English
m_strLanguage = "04090000";
}
// Init done successful
m_bValid = TRUE;
strName.ReleaseBuffer();
return TRUE;
}
CVersion::~CVersion()
{
if (m_lpData != NULL)
{
delete [] m_lpData;
}
}
BOOL CVersion::GetFileVersion(C String &strVer)
{
if (!m_bValid)
return FALSE;
UINT hMS = HIWORD(m_FixedInfo.dwFileV ersionMS);
UINT lMS = LOWORD(m_FixedInfo.dwFileV ersionMS);
UINT hLS = HIWORD(m_FixedInfo.dwFileV ersionLS);
UINT lLS = LOWORD(m_FixedInfo.dwFileV ersionLS);
strVer.Format("%d.%d.%d.%d ",hMS, lMS, hLS, lLS);
return TRUE;
}
BOOL CVersion::GetProductVersio n(CString &strVer)
{
if (!m_bValid)
return FALSE;
UINT hMS = HIWORD(m_FixedInfo.dwProdu ctVersionM S);
UINT lMS = LOWORD(m_FixedInfo.dwProdu ctVersionM S);
UINT hLS = HIWORD(m_FixedInfo.dwProdu ctVersionL S);
UINT lLS = LOWORD(m_FixedInfo.dwProdu ctVersionL S);
strVer.Format("%d.%d.%d.%d ",hMS, lMS, hLS, lLS);
return TRUE;
}
BOOL CVersion::GetVariableInfo( LPCSTR strKey, CString &strValue)
{
LPVOID lplpBuff;
UINT nLen;
CString strActualKey;
char *szKey;
// If one of them is false, return false
if (!(m_bValid && m_bLangFound))
return FALSE;
strActualKey.Format("\\Str ingFileInf o\\%s\\%s" ,m_strLang uage, strKey);
szKey = strActualKey.GetBuffer(str ActualKey. GetLength( ));
if (VerQueryValue(m_lpData, szKey, &lplpBuff, &nLen))
{
strActualKey.ReleaseBuffer ();
strValue = (char *)lplpBuff;
} else
{
strActualKey.ReleaseBuffer ();
return FALSE;
}
return TRUE;
}
<<<<<<<
but you can go ahead and add it.
CVersion.h
>>>>>>>
#include "winver.h"
/*
This class works as follows
Whenever you need version information, create a cversion object either on stack or
by new
After creation, call Init member function and check the return value.
If value is true, use the version object, else dont use it
To obtain fileversion and productversion, use respective functions
To obtain any other information, use getvariableinfo function,
supply the key value and place holder for return value.
All functions return true on success, false on failure
*/
class CVersion
{
public:
CVersion();
CVersion(LPCSTR strFileName);
~CVersion();
BOOL Init();
BOOL GetFileVersion(CString &strVer);
BOOL GetProductVersion(CString &strVer);
BOOL GetVariableInfo(LPCSTR strKey, CString &strValue);
private:
VS_FIXEDFILEINFO m_FixedInfo;
char *m_lpData; // contains the entire Structure
BOOL m_bValid;
BOOL m_bLangFound;
DWORD m_structSize;
CString m_strLanguage;
CString m_strFileName;
void GetLanguageID(CString &strLangID) {strLangID = m_strLanguage;};
};
<<<<<<
CVersion.cpp
>>>>>>
#include "stdafx.h"
#include "cversion.h"
// Link Library add Version.lib
CVersion::CVersion()
{
m_lpData = NULL;
m_bValid = FALSE;
m_bLangFound = FALSE;
}
CVersion::CVersion(LPCSTR strFileName)
: m_strFileName(strFileName)
{
m_lpData = NULL;
m_bValid = FALSE;
m_bLangFound = FALSE;
}
#define SUFFICIENTLY_LARGE_BUFFER 500
BOOL CVersion::Init()
{
CString strName;
char *szName;
DWORD temp;
if (m_strFileName.IsEmpty())
{
szName = strName.GetBuffer(SUFFICIE
/////////////////////////
// Get the executable name
if (GetModuleFileName(AfxGetA
{
strName.ReleaseBuffer();
return FALSE;
}
strName.ReleaseBuffer();
} else
{
strName = m_strFileName;
}
// We still need a char *
szName = strName.GetBuffer();
/////////////////////////
// Get the Version Information of the executable
m_structSize = ::GetFileVersionInfoSize(s
if (m_structSize == 0)
{
strName.ReleaseBuffer();
return FALSE;
}
m_lpData = new char [m_structSize];
if (!GetFileVersionInfo(szNam
{
delete [] m_lpData;
m_lpData = NULL;
strName.ReleaseBuffer();
return FALSE;
}
/////////////////////////
// Now retrieve the fixedinfo structure from the version info
LPVOID lplpBuff;
UINT nLen;
VerQueryValue(m_lpData, "\\", &lplpBuff, &nLen);
memcpy(&m_FixedInfo, lplpBuff, sizeof(VS_FIXEDFILEINFO));
/////////////////////////
// Now Determine the language id
char *szLangugeID;
if (VerQueryValue(m_lpData,"\
&lplpBuff, &nLen))
{
UINT nLangMajor = 0;
UINT nLangMinor = 0;
szLangugeID = (char *)lplpBuff;
// pick up the first language
// for the more ambitious move, create an array and capture
// all the language values
memcpy(&nLangMajor, szLangugeID, 2);
memcpy(&nLangMinor, szLangugeID + 2, 2);
m_strLanguage.Format("%04X
m_bLangFound = TRUE;
} else
{
// Default to English
m_strLanguage = "04090000";
}
// Init done successful
m_bValid = TRUE;
strName.ReleaseBuffer();
return TRUE;
}
CVersion::~CVersion()
{
if (m_lpData != NULL)
{
delete [] m_lpData;
}
}
BOOL CVersion::GetFileVersion(C
{
if (!m_bValid)
return FALSE;
UINT hMS = HIWORD(m_FixedInfo.dwFileV
UINT lMS = LOWORD(m_FixedInfo.dwFileV
UINT hLS = HIWORD(m_FixedInfo.dwFileV
UINT lLS = LOWORD(m_FixedInfo.dwFileV
strVer.Format("%d.%d.%d.%d
return TRUE;
}
BOOL CVersion::GetProductVersio
{
if (!m_bValid)
return FALSE;
UINT hMS = HIWORD(m_FixedInfo.dwProdu
UINT lMS = LOWORD(m_FixedInfo.dwProdu
UINT hLS = HIWORD(m_FixedInfo.dwProdu
UINT lLS = LOWORD(m_FixedInfo.dwProdu
strVer.Format("%d.%d.%d.%d
return TRUE;
}
BOOL CVersion::GetVariableInfo(
{
LPVOID lplpBuff;
UINT nLen;
CString strActualKey;
char *szKey;
// If one of them is false, return false
if (!(m_bValid && m_bLangFound))
return FALSE;
strActualKey.Format("\\Str
szKey = strActualKey.GetBuffer(str
if (VerQueryValue(m_lpData, szKey, &lplpBuff, &nLen))
{
strActualKey.ReleaseBuffer
strValue = (char *)lplpBuff;
} else
{
strActualKey.ReleaseBuffer
return FALSE;
}
return TRUE;
}
<<<<<<<
ASKER
I gather from your explanation that you update the version info according to the build, or else the build. What I'd like to do is ideally use what is in the resource file in the likes of the splash screen, the about screen. Thus I needn't think of updating more than one location.
How to do that -- unless, that is, I didn't understand your explanation.
RJV