C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Как узнать программно версию exe -файла
Gal
Отправлено: 04.06.2004, 10:22


Станционный диспетчер

Группа: Участник
Сообщений: 124



Как узнать программно версию exe -файла
olegenty
Отправлено: 04.06.2004, 10:31


Ветеран

Группа: Модератор
Сообщений: 2412



если пользуешься RxLib, то так:

CODE

#include "RxVerInf.hpp"

...



   TVersionInfo *p = NULL;
   try
   {
       try
       {
           TVersionInfo *p = new TVersionInfo(Application->ExeName);
           if (p->Valid)
           {
               laFileVersion->Caption = p->FileVersion;
           } else
           {
               laFileVersion->Visible = false;
               laFileVersionCaption->Visible = false;
           }
       }
       catch(const Exception &E)
       {
           ShowMessage(E.Message.Trim());
       }
   } __finally
   {
       if (p) delete p;
   }

Gedeon
Отправлено: 04.06.2004, 10:41


Ветеран

Группа: Модератор
Сообщений: 1742



Вот готовая функция
CODE

bool GetAppVersion(char* FileName, int* VerInfo){ // получение версии файла
if(!IsFile(FileName)){ // Проверяем наличие файла
return false; // Если нет ф-ция неуспешна
}
DWORD FSize = GetFileVersionInfoSize(FileName,NULL); // размер инфы о версии файла
if(FSize==0){ // Если 0 функция неуспешна
return false;
}
LPVOID pBlock = (char*)malloc(FSize); // адрес буфера для ресурсов версии
GetFileVersionInfo(FileName,NULL,FSize,pBlock); // получаем ресурс информации о версии
LPVOID MS;
UINT LS;
try{
VerQueryValue(pBlock,"\\",&MS,&LS); // извлекаем информацию из ресурса
}
catch(...){
return false; // в случае ошибки функция неуспешна
}
VS_FIXEDFILEINFO FixedFileInfo; // структура с информацией о версии файла
memmove(&FixedFileInfo, MS, LS); // приводим информацию к структуре

DWORD FileVersionMS = FixedFileInfo.dwFileVersionMS;
DWORD FileVersionLS = FixedFileInfo.dwFileVersionLS;

VerInfo[0] = HIWORD(FileVersionMS); // получаем значения
VerInfo[1] = LOWORD(FileVersionMS); // и присваиваеи их входному указателю
VerInfo[2] = HIWORD(FileVersionLS);
VerInfo[3] = LOWORD(FileVersionLS);

return true; // функция успешна
}

biggrin.gif Заставили меня его прокоментировать для идиотов, а вот пригодилось.

Вот так пользоваться
CODE

int ApplicationVersion[4] = {0,0,0,0}; // массив с информацией о версии

if(GetAppVersion(Application->ExeName.c_str(), ApplicationVersion)){ // занести в него информацию


AppMajor = ApplicationVersion[0]; // версия обновляемого приложения
AppMinor = ApplicationVersion[1];
AppRelease = ApplicationVersion[2];
AppBuild = ApplicationVersion[3];
}



И уже вопрос в догонку от меня: если в эту функцию имя приложения засунуть в таком виде, как я привел в примере, то че то происходит со значением указателя и он после выполнения функции(успешного и правильного) с последней буквой F в конце и без трех своих. Лечил созданием нового указателя и копированием в него значения Application->ExeName.c_str(), но не понятно че за ботва?

Отредактировано Gedeon — 04/06/2004, 11:45
xTrim
Отправлено: 04.06.2004, 10:56


Машинист паровоза

Группа: Участник
Сообщений: 208



у меня похожая есть smile.gif
CODE

//---------------------------------------------------------------------------

template <class T>
class GlobalMem
{
public:
GlobalMem(DWORD s):size(s){buf = (T) GlobalAlloc(GMEM_FIXED, size);}
~GlobalMem(){GlobalFree(buf);}
T operator()(){return buf;}
private:
T buf;
DWORD size;
};

//---------------------------------------------------------------------------
AnsiString GetAnyAppParam(AnsiString appname,AnsiString pname)
{
//pname = ProductName,FileVersion,LegalCopyright,CompanyName и т.д.
AnsiString ret("<Invalid parametr>");
DWORD h;
DWORD Size = GetFileVersionInfoSize(appname.c_str(), &h);
if (Size == 0) return ret;

GlobalMem<char*> buf(Size);

if (GetFileVersionInfo(appname.c_str(), h, Size, buf()) == 0) return ret;

char* ValueBuf;
UINT Len;
VerQueryValue(buf(), "\\VarFileInfo\\Translation", &(void *) ValueBuf, &Len);
if (Len < 4) return ret;

AnsiString CharSet = IntToHex((int)MAKELONG(*(int*) (ValueBuf + 2), *(int*) ValueBuf),8);
AnsiString fn = "\\StringFileInfo\\" + CharSet + "\\"+pname;

if (VerQueryValue(buf(),fn.c_str(),&(void *) ValueBuf, &Len) != 0)
 ret = ValueBuf;

return ret;
}
//---------------------------------------------------------------------------

использовать
CODE

Label1->Caption = GetAnyAppParam(Application->ExeName,"ProductName")+" "+GetAnyAppParam(Application->ExeName,"FileVersion");
Label2->Caption = GetAnyAppParam("C:\\Program Files\\Opera75\\opera.exe","ProductName")+" "+GetAnyAppParam("C:\\Program Files\\Opera75\\opera.exe","FileVersion");

вроде не глючит
Gedeon
Отправлено: 04.06.2004, 11:43


Ветеран

Группа: Модератор
Сообщений: 1742



Да нет, сама функция у меня не глючит, вот с указателем что-то происходит, char* иногда преподносит сюрпризы. Вот подумалось надо было не мудрствуя лукаво обьявить его как const.
Treumer
Отправлено: 22.06.2005, 09:31


Станционный диспетчер

Группа: Участник
Сообщений: 92



QUOTE (olegenty @ 04/06/2004, 10:31)
если пользуешься RxLib, то так:

CODE

#include "RxVerInf.hpp"

...



TVersionInfo *p = NULL;
try
{
try
{
TVersionInfo *p = new TVersionInfo(Application->ExeName);
if (p->Valid)
{
laFileVersion->Caption = p->FileVersion;
} else
{
laFileVersion->Visible = false;
laFileVersionCaption->Visible = false;
}
}
catch(const Exception &E)
{
ShowMessage(E.Message.Trim());
}
} __finally
{
if (p) delete p;
}


Странная получается ерунда: делаю как описано, а она все время на TVersionInfo как на "unresolved external" ругается!

Вернуться в Вопросы программирования в C++Builder