列举可执行文件的所有版本描述字符串

程序开头加上如下引用,不然编译不过。

#pragma comment(lib, "Version.lib")


结构定义:

struct LANGANDCODEPAGE
{
  WORD wLanguage;
  WORD wCodePage;
};    


struct VS_VERSIONINFO
{
  WORD                wLength;
  WORD                wValueLength;
  WORD                wType;
  WCHAR               szKey[1];
  WORD                wPadding1[1];  //以零填充szKey以对齐数据为32位(4个字节)
  VS_FIXEDFILEINFO    Value;
  WORD                wPadding2[1];
  WORD                wChildren[1];
};


struct KEYSTRING 
{
  WORD   wLength; 
  WORD   wValueLength; 
  WORD   wType; 
  WCHAR  szKey[1]; 
  WORD   Padding[1]; 
  WORD   Value[1]; 
};


struct STRINGTABLE 
{
  WORD        wLength; 
  WORD        wValueLength; 
  WORD        wType; 
  WCHAR       szKey[1]; 
  WORD        Padding[1]; 
  KEYSTRING   Children[1];
};


struct STRINGFILEINFO
{
  WORD         wLength;
  WORD         wValueLength;
  WORD         wType;
  WCHAR        szKey[1];
  WORD         Padding[1];
  STRINGTABLE  Children[1];
};


VS_VERSIONINFO及相关的结构是个相当复杂的结构,主要是因为他它里面的szKey及 诸如Children等成员的大小并不确定,所以在定义这些结构时都是以1为单位,在实际应用时才确定其具体地址。

定义两个字符串于存储字段名及字段值:

CHAR szKey[MAX_PATH]={0}, szValue[MAX_PATH]={0};


因为各字符串都是以宽字符形式存储的,所以要进行转换,相关函数:

//*****************************************************************************
// 宽字符串转为标准字符串
// swSource:宽字符串 szDescription=保存标准字符串的缓冲区 nSize = 缓冲区大小
//*****************************************************************************
BOOL TransformStringWideToAnsi(LPCWSTR swSource, LPSTR szDescription, UINT nSize)
{
  UINT nLength = WideCharToMultiByte(CP_ACP, NULL, swSource, -1, NULL, 0, NULL, NULL);
  if((nLength<=0)||(nSize<nLength)) return FALSE; 


  WideCharToMultiByte(CP_ACP, NULL, swSource, -1, szDescription, nLength, NULL, NULL); 
  szDescription[nLength-1]=0;
  
  return TRUE;
}

//*****************************************************************************

// 列举文件描述信息
// lpszAppFile=文件名
//*****************************************************************************
BOOL ListAppDescription(LPCSTR lpszAppFile)
{
  BOOL   fgRet = FALSE;
  DWORD  dwHandle, dwSize;
  LPSTR  lpFileName = (LPSTR)lpszAppFile;
   
  //获取版本信息区大小 
  dwSize = ::GetFileVersionInfoSize(lpFileName, &dwHandle);
  if(dwSize == 0)  return FALSE;
 
  //建立缓冲区,
  LPBYTE lpBuffer = new BYTE[dwSize];  
  ZeroMemory(lpBuffer, dwSize);
  
  do
  {
    //读取版本信息
    if(!::GetFileVersionInfo(lpFileName, 0, dwSize, lpBuffer))  break;
  
//获取语言代码
UINT nSize;
LANGANDCODEPAGE *lpTranslate = NULL;
if(!::VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), (LPVOID *)(&lpTranslate), &nSize)) break;

//定位VS_VERSIONINFO结构体
VS_VERSIONINFO *pVerInfo;   
pVerInfo = (VS_VERSIONINFO *)lpBuffer;    
if(pVerInfo->wValueLength == 0) break;
        if(!wcscmp(pVerInfo->szKey, (WCHAR *)"VS_VERSION_INFO")) break;

//定位VS_FIXEDFILEINFO结构体 
        VS_FIXEDFILEINFO *pFixedInfo;
nSize = wcslen(pVerInfo->szKey);
LPBYTE pOffsetBytes = (BYTE *)pVerInfo->szKey + ((nSize+1)*sizeof(WCHAR));         //跳过szkey
        pFixedInfo = (VS_FIXEDFILEINFO *)(pOffsetBytes+(nSize*sizeof(WCHAR))%4);    //修正偏移地址
if(pFixedInfo->dwSignature != 0xfeef04bd) break;                            //检查标记

        //定位STRINGFILEINFO结构体
STRINGFILEINFO *pStringFileInfo;             
pOffsetBytes = (BYTE *)pFixedInfo + sizeof(VS_FIXEDFILEINFO);        //跳过VS_FIXEDFILEINFO即为STRINGFILEINFO
        pStringFileInfo = (STRINGFILEINFO *)pOffsetBytes;

//定位STRINGTABLE结构体 
        STRINGTABLE *pStringTable;
nSize = wcslen(pStringFileInfo->szKey);
       pOffsetBytes = (BYTE *)pStringFileInfo->szKey + ((nSize+1)*sizeof(WCHAR));
pStringTable = (STRINGTABLE *)(pOffsetBytes+(nSize*sizeof(WCHAR))%4);

//定位KEYSTRING结构体
KEYSTRING *pKeyString;
nSize = wcslen(pStringTable->szKey);
pOffsetBytes = (BYTE *)pStringTable->szKey + ((nSize+1)*sizeof(WCHAR));    //跳过块头(中文(080404b0))
pOffsetBytes += (nSize*sizeof(WCHAR))%4;

WCHAR *pwString=NULL, swKeyName[MAX_PATH];
TransformStringAnsiToWide(lpszKeyName, swKeyName, MAX_PATH);
while((pOffsetBytes-(BYTE *)pStringTable)<pStringTable->wLength)

 pKeyString = (KEYSTRING *)pOffsetBytes; //KEYSTRING结构体
 nSize = wcslen(pKeyString->szKey);      //跳过KEY_NAME
          pwString = pKeyString->szKey+nSize+1;   //算上结束字符
          pwString += (nSize%4)/sizeof(WCHAR);    //对齐32位,得到KEY_VALUE地址

    //转换为标准字符串
  TransformStringWideToAnsi(pKeyString->szKey, szKey, MAX_PATH);
  if(pKeyString->wValueLength)  TransformStringWideToAnsi(pwString, szValue, MAX_PATH);

          //显示部分略
  //strcat(szKey, "=");
  //strcat(szKey, szValue);
         //ShowMessage(szKey);

 //计算下一项地址
         pOffsetBytes += pKeyString->wLength;
 pOffsetBytes += pKeyString->wLength%4;  //对齐32位
}
  }while(FALSE);

  delete []lpBuffer;
  
  return fgRet;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值