Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

MFC VersionInfo problem

Posted on 2000-03-27
5
Medium Priority
?
1,023 Views
Last Modified: 2013-11-20
I am writing a simple window based dialog that I will show a list of files and allow you to retrieve the version resource information.  I have a class that I pulled off the web called CVersionInfo but I can not seem to get it to work.  I understand that the versioninfo struct is a UNICODE structure and this is where my problem lies.  The file is found, the VersionInfo Struct is populated but the Quickwatch shows the CString values with the a . which equates to the 00 value in the memory watch.  It would appear that the strings are not being converted to Unicode correctly.  When you look at each individual string, the tool tip and the watch value only shows the first character.  It seems like it is a trivial problem, I just don't deal with UNICODE so I do not know how to fix it.

 The code snippet is below

#include "stdafx.h"
#include "version.h"
#include "cversion.h"
#include "string.h"

CVersionInfo::CVersionInfo(LPCSTR szFileToVersion /* = NULL*/,
                                                   LPCSTR szLanguage /* = "0409"*/,
                                                   LPCSTR szCodepage /* = "04e4"*/)
{
        m_lpstrVffInfo = NULL;
        m_strFileName = szFileToVersion;
        m_strLanguage = szLanguage;
        m_strCodepage = szCodepage;
        m_strCompanyName = _T("");
        m_strFileDescription  = _T("");
        m_strFileVersion = _T("");
        m_strInternalName = _T("");
        m_strLegalCopyright = _T("");
        m_strOriginalFilename = _T("");
        m_strProductName = _T("");
        m_strProductVersion = _T("");
        m_strComments = _T("");
        m_strSpecialBuild = _T("");
        m_strPrivateBuild = _T("");
        m_bQueryDone=FALSE;
}

CString CVersionInfo::GetFileVersion()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strFileVersion;
}

CString CVersionInfo::GetPrivateBuild()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strPrivateBuild;
}

CString CVersionInfo::GetSpecialBuild()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strSpecialBuild;
}

CString CVersionInfo::GetCompanyName()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strCompanyName;
}

CString CVersionInfo::GetFileDescription()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strFileDescription;
}

CString CVersionInfo::GetInternalName()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strInternalName;
}

CString CVersionInfo::GetLegalCopyright()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strLegalCopyright;
}

CString CVersionInfo::GetOriginalFilename()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strOriginalFilename;
}

CString CVersionInfo::GetProductVersion()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strProductVersion;
}

CString CVersionInfo::GetComments()
{
        if (!m_bQueryDone)
                GetVersionInfo();
        return m_strComments;
}

void CVersionInfo::GetVersionInfo()
{
        DWORD   dwVerInfoSize;          // Size of version information block
        DWORD   dwVerHnd=0;                     // An 'ignored' parameter, always '0'
        WCHAR szFileName[MAX_PATH];

        m_bQueryDone=TRUE;
        if (m_strFileName.IsEmpty())
                GetModuleFileName(NULL, szFileName, MAX_PATH);
        else
                lstrcpy(szFileName, m_strFileName);
       
        dwVerInfoSize = GetFileVersionInfoSize(szFileName, &dwVerHnd);
        if (dwVerInfoSize) {
                HANDLE  hMem;
                hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
                m_lpstrVffInfo  = (char *)GlobalLock(hMem);
                GetFileVersionInfo(szFileName, dwVerHnd, dwVerInfoSize, m_lpstrVffInfo);
                QueryValue("CompanyName", m_strCompanyName);
                QueryValue("FileDescription", m_strFileDescription);
                QueryValue("FileVersion", m_strFileVersion);
                QueryValue("InternalName", m_strInternalName);
                QueryValue("LegalCopyright", m_strLegalCopyright);
                QueryValue("OriginalFilename", m_strOriginalFilename);
                QueryValue("ProductName", m_strProductName);
                QueryValue("ProductVersion", m_strProductVersion);
                QueryValue("Comments", m_strComments);
                QueryValue("SpecialBuild", m_strSpecialBuild);
                QueryValue("PrivateBuild", m_strPrivateBuild);
                GlobalUnlock(hMem);
                GlobalFree(hMem);
        }
}

void CVersionInfo::QueryValue(LPCSTR szId, CString& s)
{
        ASSERT(m_lpstrVffInfo != NULL);
        LPSTR   lpVersion;                      // String pointer to 'version' text
        UINT    uVersionLen;
        BOOL    bRetCode;

        CString szSelector;  
            
            CString stringfileinfo ="\\StringFileInfo\\";
        szSelector= stringfileinfo + m_strLanguage + m_strCodepage + "\\" + szId;
        bRetCode = VerQueryValue((LPVOID)m_lpstrVffInfo,
                szSelector.GetBuffer(szSelector.GetLength()),
                (LPVOID *)&lpVersion,
                &uVersionLen);
       
        if(bRetCode)
                s = lpVersion;
        else
                s.Empty();
}


My question is how to handle this so I get the correct data in the CStrings?

Scot
0
Comment
Question by:sdewerth
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
5 Comments
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2662139
Change the last couple of lines of QueryValue above to this...

  if(bRetCode)
    s = CString(lpVersion, uVersionLen+1);
  else
    s.Empty();

Then it should work (your code looks very similar to the working code I have .. that was about the only significant difference I could notice.
0
 
LVL 1

Author Comment

by:sdewerth
ID: 2664449
Sorry Ronslow,

After making the changes, I still seem to have the same problem.  The VerQueryInfo returns OK but the QueryValue functions do no return valid(any) data.
0
 
LVL 10

Accepted Solution

by:
RONSLOW earned 450 total points
ID: 2667367
here is the code I use .. try it out:

NOTE: this is hard code for the language I want .. feel free to fiddle with it.  Also, I use different member var names than you do and I also get file/product version numbers into int arrays m_fv, m_pv.

CString CVersionInfo::GetVersionInfoField (CString name, void* bufVersionInfo, WORD* pLanguage) const {
      CString key;
      key.Format("\\StringFileInfo\\%04X%04x\\%s",*((WORD*)pLanguage),*(((WORD*)pLanguage)+1),name);
      UINT ulen;
      char* bufString;
      if (! ::VerQueryValue(bufVersionInfo, const_cast<char*>(LPCTSTR(key)), reinterpret_cast<LPVOID*>(&bufString), &ulen)) return afxEmptyString;
      return CString(bufString, ulen+1);
}

void CVersionInfo::GetVersionInfo (CString filename) const {
      char* path = const_cast<char*>(LPCTSTR(filename));
      
      DWORD hVerDummy;
      DWORD dwVersionInfoSize = ::GetFileVersionInfoSize(path,&hVerDummy);
      if (dwVersionInfoSize == 0L) return;
      
      void* bufVersionInfo = malloc(dwVersionInfoSize);
      if (! bufVersionInfo) return;
      
      if (::GetFileVersionInfo(path,hVerDummy,dwVersionInfoSize,bufVersionInfo)) {
            UINT ulen;
            
            // Get Version Info
            VS_FIXEDFILEINFO *bufFixedFileInfo;
            if (::VerQueryValue(bufVersionInfo,"\\",reinterpret_cast<LPVOID*>(&bufFixedFileInfo), &ulen)){
                  m_fv[0] = HIWORD(bufFixedFileInfo->dwFileVersionMS);
                  m_fv[1] = LOWORD(bufFixedFileInfo->dwFileVersionMS);
                  m_fv[2] = HIWORD(bufFixedFileInfo->dwFileVersionLS);
                  m_fv[3] = LOWORD(bufFixedFileInfo->dwFileVersionLS);
                  m_pv[0] = HIWORD(bufFixedFileInfo->dwProductVersionMS);
                  m_pv[1] = LOWORD(bufFixedFileInfo->dwProductVersionMS);
                  m_pv[2] = HIWORD(bufFixedFileInfo->dwProductVersionLS);
                  m_pv[3] = LOWORD(bufFixedFileInfo->dwProductVersionLS);
            }
            
            WORD* pLanguage;
            if(::VerQueryValue(bufVersionInfo, "\\VarFileInfo\\Translation", reinterpret_cast<LPVOID*>(&pLanguage), &ulen) && ulen != 0) {
                  m_Comments = GetVersionInfoField ("Comments",bufVersionInfo,pLanguage);
                  m_CompanyName = GetVersionInfoField ("CompanyName",bufVersionInfo,pLanguage);
                  m_FileDescription = GetVersionInfoField ("FileDescription",bufVersionInfo,pLanguage);
                  m_InternalName = GetVersionInfoField ("InternalName",bufVersionInfo,pLanguage);
                  m_LegalCopyright = GetVersionInfoField ("LegalCopyright",bufVersionInfo,pLanguage);
                  m_LegalTrademarks = GetVersionInfoField ("LegalTrademarks",bufVersionInfo,pLanguage);
                  m_OriginalFilename = GetVersionInfoField ("OriginalFilename",bufVersionInfo,pLanguage);
                  m_PrivateBuild = GetVersionInfoField ("PrivateBuild",bufVersionInfo,pLanguage);
                  m_ProductName = GetVersionInfoField ("ProductName",bufVersionInfo,pLanguage);
                  m_SpecialBuild = GetVersionInfoField ("SpecialBuild",bufVersionInfo,pLanguage);
            }      
      }
      free(bufVersionInfo);
}

0
 
LVL 1

Author Comment

by:sdewerth
ID: 2667528
I'll give you this one Ronslow.  The first answer did help me.  I finally found an MSDN article from the MSJ that I grabbed some code from.  Seems like the code you are using.  My problem actually occured because I was not using the correct language code page to get the stringfileinfo.  What I did to remedy this was do a query with \\VarInfo\Translation to get the language codepage and then do a call with StringFileInfo.  It works like a champ now.  However, I would like to find the architect that coded this API...

Thanks for the help
Scot
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2672702
indeed .. there's some strange code in Win32.  Makes you wonder sometimes :-)
0

Featured Post

Moving data to the cloud? Find out if you’re ready

Before moving to the cloud, it is important to carefully define your db needs, plan for the migration & understand prod. environment. This wp explains how to define what you need from a cloud provider, plan for the migration & what putting a cloud solution into practice entails.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question