Sorry, I'm not familiar with RTFM.
I made the change using CByteArray. That's a big help and your rigth... the
code looks cleaner. Plus I was able to delete the "delete[]"
Thanks so far.
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
The version library is not included by default in the link. If you get
any kind of linker
error, it is ESSENTIAL that you RTFM, which tells you which library needs
to be linked in.
Link in that library.
joe
****
On Tue, 15 Jun 2010 18:14:48 -0500, "JCO" <someone@somewhere.com> wrote:
This is another issue that fits in this thread.
I've been messing with the GetFileVersionInfo() but when it's in my cpp, I
get link errors. I can't seem to find a header file that might be missing
so I don't understand it. The code snip is shown below. I have some
extra
code because I'm experimenting a bit but the issue is the
GetFileVersionInfo() linker Issue.
*********************************************************
//get filename, add .exe, then get handle to this filename
****
Start throwing code away here
****
CString strFileName( _T("") );
strFileName = AfxGetApp()->m_pszExeName;
strFileName.Append( _T(".exe") );
HMODULE hmod = GetModuleHandle( strFileName );
//use GetModuleFileName() to obtain full path of file
CString strFullPath( _T("") );
LPTSTR pstr = strFullPath.GetBufferSetLength(MAX_PATH+1);
DWORD pathLen = ::GetModuleFileName( hmod, pstr, MAX_PATH);
strFullPath.ReleaseBuffer( pathLen ); //Note: ReleaseBuffer doesn't
need
a +1 for the null byte
****
Throw away all the above code. As far as I can tell, it does nothing that
can't be done
in the four simple lines below.
CString filename;
LPTSTR p = fliename.GetBuffer(MAX_PATH);
GetModuleFileName(NULL, p, MAX_PATH);
filename.ReleaseBuffer();
It is not at all clear why you have to use GetModuleHandle here at all.
The module handle
is not needed for anything. RTFM; using NULL as the module handle gives
you the filename
of the running executable!
****
//Use GetFileVersionInfo() to get file information
TCHAR szExePath[MAX_PATH];
****
This variable is not needed; eliminate it entirely!
*****
::GetModuleFileName( NULL, szExePath, MAX_PATH );
****
Why are you repeating the GetModuleFileName, which was already done? Get
rid of this
line; it serves no useful purpose because you already have the module
filename!
****
DWORD dwDummy;
DWORD dwFVISize = GetFileVersionInfoSize( szExePath, &dwDummy );
****
Given I used the variable "filename" above, this would simply be
DWORD dwFVISize = ::GetFileVersionInfoSize(filename, &dwDummy);
****
LPBYTE lpVersionInfo = new BYTE[dwFVISize];
****
You would be better served by
CBytArray VersionInfo;
VersionInfo.SetSize(dwFVISize];
*****
GetFileVersionInfo( szExePath , 0 , dwFVISize , lpVersionInfo );
****
And then coding the above as
::GetFileVersionInfo(filename, 0, dwFVISize, VersionInfo.GetData());
****
if( lpVersionInfo )
delete lpVersionInfo;
****
Note there is no need to do the delete if you have used the CByteArray.
Note also that you must not delete this data until *after* you have used
it!
And why is it that if the value is NULL, you try to call
::GetFileVersionInfo anyway? If
you were testing for an allocation error, you would test BEFORE you tried
to use the
pointer. And there is no need to condition delete if it is NULL. And
if the call
failed, why are you blindly going on and tryhing to *use* the illegal
values?
VS_FIXEDFILEINFO *lpFfi;
****
And where do I see this pointer being initialized? You have an
uninitialized pointer and
you blindly use it to access values below!
It should be initialized as
VS_FIXEDFILEINFO * Ffi =(VS_FIXEDFILEINFO *)VersionInfo.GetData();
****
DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
DWORD dwLeftMost = HIWORD(dwFileVersionMS);
DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
DWORD dwSecondRight = HIWORD(dwFileVersionLS);
DWORD dwRightMost = LOWORD(dwFileVersionLS);
CString sMsg;
sMsg.Format( _T("Version: %d.%d.%d.%d") , dwLeftMost,
dwSecondLeft,dwSecondRight, dwRightMost );
MessageBox( sMsg );
********************************************************
These are the liker Errors:
Error 1 error LNK2019: unresolved external symbol _GetFileVersionInfoW@16
referenced in function "public: void __thiscall
CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)"
(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj
AppVersionDynamicError 2 error LNK2019: unresolved external symbol
_GetFileVersionInfoSizeW@8
referenced in function "public: void __thiscall
CAppVersionDynamicDlg::OnBnClickedButtonVersion(void)"
(?OnBnClickedButtonVersion@CAppVersionDynamicDlg@@QAEXXZ)AppVersionDynamicDlg.obj
AppVersionDynamic"Joseph M. Newcomer" <newcomer@flounder.com> wrote in
message
news:cc1f16hsn3lejfmtp2b5n0a20093vii1bf@4ax.com...
****
RTFM. The documentation CLEARLY states that the API call is found in
version.lib, so it
is screamingly obvious that this library is not included in the link. So
add it to the
linker list of libraries to search!
joe
****
The idea is that the header file is used to create both the string in
the
About box and
the values in the .rc file that describes the VERSIONINFO.
joe
On Mon, 14 Jun 2010 18:54:46 -0500, "JCO" <someone@somewhere.com> wrote:
I think I'm missing something but I'm interested in this topic.
If you have your version defined in a header file, then you can display
it
in the dialog, however, if you did a "property" on the exe file, has it
really changed? If so, then I got lost somewhere in this thread.
Also;
I was under the impression that you can set something in VS that allowed
the
version to change each time you do a build. I don't remember how to do
this
but I always thought this was possible. Now it may only change the
Build
number and not anything else, however, this is a good feature. Is this
still possible, if so .... how do you do it?
Thanks
"Giovanni Dicanio" <giovanniDOTdicanio@REMOVEMEgmail.com> wrote in
message
news:eg3hiCyCLHA.2012@TK2MSFTNGP02.phx.gbl...
On 13/06/2010 15:47, RB wrote:
void CFileHandlingApp::OnAppAbout()
{
CAboutDlg aboutDlg;
CString s;
s.Format( _T(" version %d.%d.%d.%d"), VERMAJ, VERMIN, VERFIX,
BUILDNUMBER );
aboutDlg.m_CtrlStaticVer.SetWindowText(s); //gets a Debug
Assertion
Failed
aboutDlg.DoModal();
You may want to add a method to your CAboutDlg class like
SetVersionString(LPCTSTR pszVersion) and a data member of type CString
(e.g. CString m_strVersion).
This new method should set the version string, storing it into the
proper
data member.
Then, CAboutDlg::OnInitDialog would get this string and
.SetWindowText()
it in the proper static control.
e.g.:
class CAboutDlg
{
...
public:
void SetVersionString(LPCTSTR pszVersion)
{
m_strVersion = pszVersion;
}
...
private:
CString m_strVersion;
};
In CAboudDlg::OnInitDialog() do:
m_CtrlStaticVer.SetWindowText(m_strVersion);
Giovanni
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm