Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> VS: счётчик версий 
V
    Опции темы
Rickert
Дата 2.4.2009, 04:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: нет
Всего: 52



Есть ли в Visual studio како-йнибудь счётчик версий, номер которой можно получить каким-нибудь макросом?


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
Andrey44
Дата 2.4.2009, 07:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 8
Всего: 26



Цитата(Rickert @  2.4.2009,  04:29 Найти цитируемый пост)
како-йнибудь счётчик версий

Какой нибудь может и есть! smile А поконкретнее?


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Rickert
Дата 2.4.2009, 07:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: нет
Всего: 52



Допустим счётчик билдов.
Хотя я думал что есть какя-нибудь внутрення тулза, которая позволяет программировать номер версии, типа: 1.n, где n - номер билда; а потом получать данное значение в коде, ввиде набора char'ов, что-нить типа __VERSION__.


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
Dem_max
Дата 2.4.2009, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39





--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Rickert
Дата 2.4.2009, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: нет
Всего: 52



Народ короче велосипеды пишет, потому что гениальный мелкоСофта не догадался сделать такой фишки. Чем же они там от студии к студии занимаются? smile 

Это сообщение отредактировал(а) Rickert - 2.4.2009, 09:45


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
Dem_max
Дата 2.4.2009, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



Лично для меня это не надо, если уж релиз готов то его в редакторе ресурсов за 30 секунд можно вставить версию


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
Rickert
Дата 2.4.2009, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: нет
Всего: 52



Dem_max, неудобно. ИМХО: номер версии - это вещь о которой программист вообще задумываться не должен ни на одну наносекунду.


Это сообщение отредактировал(а) Rickert - 2.4.2009, 10:50


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
jonie
Дата 2.4.2009, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



На сборочном конвейере такое делается всегда.
Например Automated Build Studio имеет спец step для этих целей.

С чего бы изменение версий должно быть в языке?! языку на версию наплевать.

лично я не задумываюсь о версии - пусть конвеер сам считает как ему надо. Например у нас это Major.Minor.BuildVersion(increment each build).Subversion(or perforce) revision of source code with builded.



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Rickert
Дата 2.4.2009, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: нет
Всего: 52



Вообще-то вопрос ро конкретную среду разработки.


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
GremlinProg
Дата 2.4.2009, 18:32 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



вопрос, конечно интересный с точки зрения версионализации конечного продукта
но он на самом деле отпадает, если решается каким-нибудь CVS или SVN (больше возможностей)
но если опираться на этот счетчик в качестве индикатора по отлову багов,
то майкрософт просто предоставил решать эту проблему по своему усмотрению, не ограничивая конечного пользователя (программиста)
а Build-event'ы - это как раз механизм, позволяющий такое творить

формат версии продукта ведь не закреплен жестко, так что любая попытка навязать майкрософтом свое видение на проблему будет скорее расценено как ущемление прав и т.д. и т.п. (а у них с этим строго)

так что любое готовое решение - скорее "вариации на тему...", а не конструирование велосипеда


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 3.4.2009, 12:53 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



посмотрел я некоторые счетчики и как-то не понравилось мне, что они копаются в моих же потрохах
такое лучше делать в отдельном rc-файле

мой вариант - это шаблон ресурса, который парсится утилитой в момент его компиляции и генерирует на его основе rc
этот rc можно подключить прямо в проект, тогда и счетчик будет работоспособным и конфликтов с существующими ресурсами не будет

я приложу свой VerBuilder, а пока,
как это работает:

1. подключаем в проект простой текстовый файл
2. пишем в нем нечто вроде такого:
Код

/*%>>
    Current version: %b[3],%b[2],%b[1],%b[0]
    Current version: %w[1],%w[0]
    Current version: %dw
%<<*/
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
#ifdef _WIN32
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#endif //_WIN32
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION        %b[3],%b[2],%b[1],%b[0]
PRODUCTVERSION    %b[3],%b[2],%b[1],%b[0]
FILEFLAGSMASK    0x3fL
#ifdef _DEBUG
    FILEFLAGS    0x1L
#else
    FILEFLAGS    0x0L
#endif
FILEOS            0x0L
FILETYPE        0x1L
FILESUBTYPE        0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904E4"
        BEGIN
            VALUE "CompanyName",        "Company"
            VALUE "FileDescription",    "Product"
            VALUE "FileVersion",        "%b[3],%b[2],%b[1],%b[0]\0"
            VALUE "InternalName",        "Product"
            VALUE "LegalCopyright",        "Product"
            VALUE "OriginalFilename",    "Product.exe"
            VALUE "ProductName",        "Product"
            VALUE "ProductVersion",        "%b[3],%b[2],%b[1],%b[0]\0"
        END
    END
END

3. Сохраняем, щелкаем на этом файле правой кнопкой мыши в Solution Explorer'е, выбираем Properties
4. Выбираем все конфигурации, ну или Release, кому как удобнее
5. Раскрываем Custom Build Step :: General
6. В Command Line пишем VerBuilder "$(InputName).ini" "$(InputFileName)"  "$(InputName).rc"
7. В Outputs пишем $(InputName).rc
8. Сохраняем настройки и нажимаем Ctrl + F7 (компиляция ресурса). Если все сделано правильно, то в директории, где лежит этот текстовый файл появятся два дополнительных файла с тем же именем, но с расширениями .ini и .rc
9. Снова открываем  Solution Explorer и добавляем в него файл(с расширением .rc

Ну вот и все, теперь при каждом билде, этот ресурс будет обновляться в соответствии с новой версией
а в консоли Output при этом, вы всегда будете наблюдать запись:
Код

    Current version: <номер версии в форме 4-х байт>
    Current version: <номер версии в форме 2-х слов>
    Current version: <номер версии в форме двойного слова>

это просто пример, на самом деле, вы можете формировать свой вывод и шаблон так, как вам будет сподручнее
спецификация шаблона такая:
Код

%     - управляющий символ escape-последовательности, которая всегда заменяется в выходном файле конкретным значением
%dw   - номер версии (4-байтовое целое в десятичной форме)
%w[0] - младшее слово версии (2-байтовое целое в десятичной форме)
%w[1] - старшее слово версии (2-байтовое целое в десятичной форме)
%b[0] - первый байт версии (1-байтовое целое в десятичной форме)
%b[1] - второй байт версии (1-байтовое целое в десятичной форме)
%b[2] - третий байт версии (1-байтовое целое в десятичной форме)
%b[3] - четвертый байт версии (1-байтовое целое в десятичной форме)
%>>   - открывает режим echo
%<<   - закрывает режим echo
%%   - экранирование символа %%

формат командной строки:
Код

<опции> <параметры> <вход> <выход>
опции:
  -a - <шаблон> и <выход> в кодировке ANSI
  -U - <шаблон> и <выход> в кодировке UNICODE
  -u - <шаблон> и <выход> в кодировке UTF-8
  -e - <шаблон> и <выход> в кодировке UTF-16LE


файл VerBuilder.exe перед использованием как у меня в примере, необходимо поместить в какую-нибудь рабочую директорию MSVC, например в $(VSInstallDir)Common7\Tools\, в 9-й версии, обычно это C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools
в младших версиях примерно так же

Кто работает с мастерами, могут соорудить простенький мастер версий
В моей версии rc.exe двухбайтовые кодировки не поддерживаются, так что конкретно при построении RC, не пользуйтесь флагами -uUe, файл генерируется правильно, даже с БОМами, но RC-компилятор просто не заточен на них, не понимает (это удобно в других случаях, например когда вам нужно версию хранить не в VERSIONINFO, а например в текстовом ресурсе, или просто во внешнем файле)

по умолчанию, если флаги не определены, то считается, что вход и выход в кодировке  ANSI
вложенные echo наследуются, т.е. обрабатываются как парные скобки (ошибок тут не будет, даже если вы пропустили какую-нибудь скобку, максимум - просто до конца файла вывод будет дублирован в консоли)

Присоединённый файл ( Кол-во скачиваний: 12 )
Присоединённый файл  VerBuilder.rar 41,90 Kb


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 3.4.2009, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



если кому-то захочется расширить функционал транслятора, вот его исходный код:
Код

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h>

int usage(void){
    _tprintf(
        _T("VerBuilder - версионализатор, версия 1.0.0.0:\r\n")
        _T("\r\nинструкция:\r\n")
        _T("<опции> <параметры> <вход> <выход>\r\n\r\n")
        _T("\r\nопции:\r\n")
        _T("  -a - <шаблон> и <выход> в кодировке ANSI\r\n")
        _T("  -U - <шаблон> и <выход> в кодировке UNICODE\r\n")
        _T("  -u - <шаблон> и <выход> в кодировке UTF-8\r\n")
        _T("  -e - <шаблон> и <выход> в кодировке UTF-16LE\r\n")
        _T("\r\nвход:\r\n")
        _T("  имя файла-шаблона\r\n")
        _T("  это может быть любой текстовый файл\r\n")
        _T("  содержимое этого файла транслируется в файл <выход>,\r\n")
        _T("  согласно следующей спецификации:\r\n")
        _T("    %%     - символ escape-последовательности\r\n")
        _T("             которая всегда заменяется в выходном файле конкретным значением\r\n")
        _T("    %%dw   - номер версии (4-байтовое целое в десятичной форме)\r\n")
        _T("    %%w[0] - младшее слово версии (2-байтовое целое в десятичной форме)\r\n")
        _T("    %%w[1] - старшее слово версии (2-байтовое целое в десятичной форме)\r\n")
        _T("    %%b[0] - первый байт версии (1-байтовое целое в десятичной форме)\r\n")
        _T("    %%b[1] - второй байт версии (1-байтовое целое в десятичной форме)\r\n")
        _T("    %%b[2] - третий байт версии (1-байтовое целое в десятичной форме)\r\n")
        _T("    %%b[3] - четвертый байт версии (1-байтовое целое в десятичной форме)\r\n")
        _T("    %%>>   - открывает режим echo \r\n")
        _T("    %%<<   - закрывает режим echo \r\n")
        _T("    %%%%   - экранирование символа %% \r\n")
        _T("\r\nрежим echo:\r\n")
        _T("  в этом режиме, весь вывод начинает дублироваться в stdout,\r\n")
        _T("  что позволяет наблюдать за режимом трансляции,\r\n")
        _T("  выводить и логировать необходимые участки выходного файла,\r\n")
        _T("  отлаживать файл шаблона\r\n")
        _T("\r\nпараметры:\r\n")
        _T("  имя файла-параметров, в котором хранится текущая версия\r\n")
        _T("  это обычный INI-файл следующего вида:\r\n\r\n")
        _T("    <general>\r\n")
        _T("    version=12345\r\n")
    );
    return S_FALSE;
}
bool translate(FILE*output,_TCHAR**lpszInput,size_t ilen,_TCHAR*lpszTemplate,int value,int out,int std_out){
    size_t tlen;
    tlen    = _tcslen(lpszTemplate);
    if( (ilen < tlen) || _tcsnicmp(*lpszInput,lpszTemplate,tlen) ){
        return false;
    }
    if(out){
        _ftprintf(output,_T("%i"),value);
        if(std_out){
            _ftprintf(stdout,_T("%i"),value);
        }
    }
    *lpszInput    += tlen - 1;
    return true;
}
int _tmain(int argc, _TCHAR* argv[]){
    _TCHAR szINI[MAX_PATH];
    _TCHAR mode[64];
    LPTSTR lpszInput,lpszOutput,lpszINI,lpszBuffer,lpCh,lpCCs;
    FILE*output,*input;
    size_t i,len,std_out;
    errno_t err;
    long bomlen;
    DWORD version;
    //
    _tsetlocale(LC_ALL,_T("Russian"));
    //
    if( argc < 4 ){
        return usage();
    }
    //
    lpszINI        = argv[argc - 3];
    lpszInput    = argv[argc - 2];
    lpszOutput    = argv[argc - 1];
    //
    if( ::GetFileAttributes(lpszInput) == INVALID_FILE_ATTRIBUTES ){
        return usage();
    }
    //
    for(lpCCs = _T(""),i = argc - 4;i--;){
        lpCh    = argv[i + 1];
        if( !_tcschr(_T("-/"),*lpCh) )continue;
        for(len = 0; *lpCh ;++len,++lpCh);
        if( !len )continue;
        for(--lpCh; len-- && !_tcschr(_T("aUue"),*lpCh) ; --lpCh);
        if( !++len )continue;
        switch( *lpCh ){
            case _T('U'):{
                lpCCs    = _T(", ccs=UNICODE");
                _tsetlocale(LC_ALL,_T(".OCP"));
                break;
            }
            case _T('u'):{
                lpCCs    = _T(", ccs=UTF-8");
                _tsetlocale(LC_ALL,_T(".OCP"));
                break;
            }
            case _T('e'):{
                lpCCs    = _T(", ccs=UTF-16LE");
                _tsetlocale(LC_ALL,_T(".OCP"));
                break;
            }
        }
        break;
    }
    _stprintf_s(mode,_T("rt%s"),lpCCs);
    if( err = _tfopen_s(&input,lpszInput,mode) ){
        _tprintf(_T("ошибка: при открытии файла-шаблона\r\n"));
        return usage();
    }
    if( ::GetFileAttributes(lpszOutput) != INVALID_FILE_ATTRIBUTES ){
        ::DeleteFile(lpszOutput);
    }
    _stprintf_s(mode,_T("wt%s"),lpCCs);
    if( err = _tfopen_s(&output,lpszOutput,mode) ){
        _tprintf(_T("ошибка: при создании выходного файла\r\n"));
        fclose(input);
        return usage();
    }
    //
    bomlen    = ftell(input);
    for(len = 0; !feof(input) ;_fgettc(input),++len);
    lpszBuffer        = (LPTSTR)malloc( (len + 1) * sizeof(_TCHAR) );
    lpszBuffer[len]    = _T('\0');
    fseek(input,bomlen,SEEK_SET);
    for(std_out = 0,lpCh = lpszBuffer; !feof(input) ;*(lpCh++) = _fgettc(input));
    fclose(input);
    //
    ::GetFullPathName(lpszINI,sizeof(szINI) / sizeof(_TCHAR),szINI,NULL);
    version    = ::GetPrivateProfileInt(_T("general"),_T("version"),0x00000000,szINI);
    _stprintf_s(mode,_T("%#.8x"),++version);
    ::WritePrivateProfileString(_T("general"),_T("version"),mode,szINI);
    //
    for(lpCh = lpszBuffer; *lpCh ;++lpCh){
        switch( *lpCh ){
            case _T('%'):{
                if( lpCh[1] == _T('%') ){
                    ++lpCh;
                }else{
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%<<"),version,0,std_out) ){
                        ++std_out;
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%>>"),version,0,std_out) ){
                        --std_out;
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%dw"),version,1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%w[0]"),LOWORD(version),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%w[1]"),HIWORD(version),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b[0]"),LOBYTE(LOWORD(version)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b[1]"),HIBYTE(LOWORD(version)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b[2]"),LOBYTE(HIWORD(version)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b[3]"),HIBYTE(HIWORD(version)),1,std_out) ){
                        continue;
                    }
                }
            }
            default:{
                _fputtc(*lpCh,output);
                if(std_out){
                    _fputtc(*lpCh,stdout);
                }
            }
        }
    }
    free(lpszBuffer);
    fclose(output);
    return S_OK;
}

на самом деле, тут можно добавить более гибкую работу с INI: дать возможность создать несколько счетчиков, а не один, как у меня; модифицировать эскейп-ключи; добавить комбинационную логику и т.п.
вобщем, все открыто, пользуйтесь

Это сообщение отредактировал(а) GremlinProg - 3.4.2009, 13:16


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 3.4.2009, 18:08 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



немного расширил возможности, пока время есть:
1. добавлен флаг -r (read-only)
если он присутствует в опциях, то увеличение счетчика не происходит (только трансляция его в файл с текущим значением)
зачем это нужно?
чтобы на основе одного счетчика можно было собирать любое число шаблонов и только один, контрольный, будет увеличивать счетчик, остальные - только читать (в таком случае, следите за порядком включения шаблонов в цепочку компиляции, контрольный шаблон должен быть либо в ее начале, либо в конце, чтобы не было смешивания версий в промежуточных шаблонах)
2. расширена размерность счетчика, по-честному ), теперь он 64-битный
3. несколько упрощена спецификация:
Код

%qw    - 8-байтовое целое в десятичной форме
%dw.x - 4-байтовое целое в десятичной форме, x={0,1}
%w.x   - 2-байтовое целое в десятичной форме, x={0,1,2,3}
%b.x    - 1-байтовое целое в десятичной форме, x={0,1,2,3,4,5,6,7}
x          - номер части счетчика

через точку, думаю, будет меньше путаницы
4. счетчик переведен в натуральный диапазон, т.е. отрицательных значений он теперь никогда не сгенерирует
пример шаблона со всеми вариантами:
Код

/*%>>
    Current version : %qw
    Current version : %dw.1.%dw.0
    Current version : %w.3.%w.2.%w.1[%w.0]
    Current version : %b.7.%b.6.%b.5.%b.4.%b.3.%b.2.%b.1.%b.0
%<<*/

третья строка - это обычный формат версии, который и нужно передавать в ресурсы

Есть еще один плюс флага -r (read-only): отпадает необходимость усложнять транслятор, т.е. не нужно заводить переменное число счетчиков, этого эффекта можно добиться цепочкой шаблонов, к примеру, если у нас 2 счетчика: 2,34,0,6 - для файла и 1,0,0,1 - для продукта, то:
Код

VS_VERSION_INFO VERSIONINFO
PRODUCTVERSION    %w.3,%w.2,%w.1,%w.0
FILEVERSION        %%w.3,%%w.2,%%w.1,%%w.0

этот шаблон сгенерирует, к примеру выход для первого счетчика:
Код

VS_VERSION_INFO VERSIONINFO
PRODUCTVERSION    1,0,0,1
FILEVERSION        %w.3,%w.2,%w.1,%w.0

если этот выход снова подать в качестве шаблона, то получится второй счетчик:
Код

VS_VERSION_INFO VERSIONINFO
PRODUCTVERSION    1,0,0,1
FILEVERSION        2,34,0,6

и т.д.

исходник скорректированного билдера:
Код

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h>

int usage(void){
    _tprintf(
        _T("VerBuilder - версионализатор, версия 1.0.0.1:\r\n")
        _T("\r\nинструкция:\r\n")
        _T("<опции> <параметры> <вход> <выход>\r\n\r\n")
        _T("\r\nопции:\r\n")
        _T("  -a - <шаблон> и <выход> в кодировке ANSI\r\n")
        _T("  -U - <шаблон> и <выход> в кодировке UNICODE\r\n")
        _T("  -u - <шаблон> и <выход> в кодировке UTF-8\r\n")
        _T("  -e - <шаблон> и <выход> в кодировке UTF-16LE\r\n")
        _T("  -r - не увеличивать значение счетчика\r\n")
        _T("\r\nвход:\r\n")
        _T("  имя файла-шаблона\r\n")
        _T("  это может быть любой текстовый файл\r\n")
        _T("  содержимое этого файла транслируется в файл <выход>,\r\n")
        _T("  согласно следующей спецификации:\r\n")
        _T("    %%     - символ escape-последовательности\r\n")
        _T("             которая всегда заменяется в выходном файле конкретным значением\r\n")
        _T("    %%qw   - 8-байтовое целое в десятичной форме\r\n")
        _T("    %%dw.x - 4-байтовое целое в десятичной форме, x={0,1}\r\n")
        _T("    %%w.x  - 2-байтовое целое в десятичной форме, x={0,1,2,3}\r\n")
        _T("    %%b.x  - 1-байтовое целое в десятичной форме, x={0,1,2,3,4,5,6,7})\r\n")
        _T("    x      - номер части счетчика\r\n")
        _T("    %%>>   - открывает режим echo \r\n")
        _T("    %%<<   - закрывает режим echo \r\n")
        _T("    %%%%   - экранирование символа %% \r\n")
        _T("\r\nрежим echo:\r\n")
        _T("  в этом режиме, весь вывод начинает дублироваться в stdout,\r\n")
        _T("  что позволяет наблюдать за режимом трансляции,\r\n")
        _T("  выводить и логировать необходимые участки выходного файла,\r\n")
        _T("  отлаживать файл шаблона\r\n")
        _T("\r\nпараметры:\r\n")
        _T("  имя файла-параметров, в котором хранится текущая версия\r\n")
        _T("  это обычный INI-файл следующего вида:\r\n\r\n")
        _T("    <general>\r\n")
        _T("    version=12345\r\n")
    );
    return S_FALSE;
}
bool translate(FILE*output,_TCHAR**lpszInput,size_t ilen,CONST _TCHAR*lpszTemplate,ULONG64 value,int out,int std_out){
    size_t tlen;
    tlen    = _tcslen(lpszTemplate);
    if( (ilen < tlen) || _tcsnicmp(*lpszInput,lpszTemplate,tlen) ){
        return false;
    }
    if(out){
        _ftprintf(output,_T("%I64u"),value);
        if(std_out){
            _ftprintf(stdout,_T("%I64u"),value);
        }
    }
    *lpszInput    += tlen - 1;
    return true;
}
int _tmain(int argc, _TCHAR* argv[]){
    _TCHAR szINI[MAX_PATH];
    _TCHAR mode[64];
    LPTSTR lpszInput,lpszOutput,lpszINI,lpszBuffer,lpCh,lpCCs;
    FILE*output,*input;
    size_t i,len,std_out;
    errno_t err;
    long bomlen;
    LARGE_INTEGER version;
    //
    _tsetlocale(LC_ALL,_T("Russian"));
    //
    if( argc < 4 ){
        return usage();
    }
    //
    lpszINI        = argv[argc - 3];
    lpszInput    = argv[argc - 2];
    lpszOutput    = argv[argc - 1];
    //
    if( ::GetFileAttributes(lpszInput) == INVALID_FILE_ATTRIBUTES ){
        return usage();
    }
    //
    for(lpCCs = _T(""),i = argc - 4;i--;){
        lpCh    = argv[i + 1];
        if( !_tcschr(_T("-/"),*lpCh) )continue;
        for(len = 0; *lpCh ;++len,++lpCh);
        if( !len )continue;
        for(--lpCh; len-- && !_tcschr(_T("aUue"),*lpCh) ; --lpCh);
        if( !++len )continue;
        switch( *lpCh ){
            case _T('U'):{
                lpCCs    = _T(", ccs=UNICODE");
                _tsetlocale(LC_ALL,_T(".OCP"));
                break;
            }
            case _T('u'):{
                lpCCs    = _T(", ccs=UTF-8");
                _tsetlocale(LC_ALL,_T(".OCP"));
                break;
            }
            case _T('e'):{
                lpCCs    = _T(", ccs=UTF-16LE");
                _tsetlocale(LC_ALL,_T(".OCP"));
                break;
            }
        }
        break;
    }
    _stprintf_s(mode,_T("rt%s"),lpCCs);
    if( err = _tfopen_s(&input,lpszInput,mode) ){
        _tprintf(_T("ошибка: при открытии файла-шаблона\r\n"));
        return usage();
    }
    _stprintf_s(mode,_T("wt%s"),lpCCs);
    if( err = _tfopen_s(&output,lpszOutput,mode) ){
        _tprintf(_T("ошибка: при создании выходного файла\r\n"));
        fclose(input);
        return usage();
    }
    //
    bomlen    = ftell(input);
    for(len = 0; !feof(input) ;_fgettc(input),++len);
    lpszBuffer        = (LPTSTR)malloc( (len + 1) * sizeof(_TCHAR) );
    lpszBuffer[len]    = _T('\0');
    fseek(input,bomlen,SEEK_SET);
    for(std_out = 0,lpCh = lpszBuffer; !feof(input) ;*(lpCh++) = _fgettc(input));
    fclose(input);
    //
    ::GetFullPathName(lpszINI,sizeof(szINI) / sizeof(_TCHAR),szINI,NULL);
    version.LowPart        = ::GetPrivateProfileInt(_T("general"),_T("low"),0x00000000,szINI);
    version.HighPart    = ::GetPrivateProfileInt(_T("general"),_T("high"),0x00000000,szINI);
    //
    for(i = argc - 4;i--;){
        lpCh    = argv[i + 1];
        if( _tcschr(_T("-/"),*lpCh) ){
            if( _tcschr(lpCh + 1,_T('r')) ){
                break;
            }
        }
    }
    if( !(i + 1) ){
        ++version.QuadPart;
        _stprintf_s(mode,_T("%#.8x"),version.LowPart);
        ::WritePrivateProfileString(_T("general"),_T("low"),mode,szINI);
        _stprintf_s(mode,_T("%#.8x"),version.HighPart);
        ::WritePrivateProfileString(_T("general"),_T("high"),mode,szINI);
    }
    //
    for(lpCh = lpszBuffer; *lpCh ;++lpCh){
        switch( *lpCh ){
            case _T('%'):{
                if( lpCh[1] == _T('%') ){
                    ++lpCh;
                }else{
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%<<"),0,0,std_out) ){
                        ++std_out;
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%>>"),0,0,std_out) ){
                        --std_out;
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%qw"),version.QuadPart,1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%dw.0"),version.LowPart,1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%dw.1"),version.HighPart,1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%w.0"),LOWORD(version.LowPart),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%w.1"),HIWORD(version.LowPart),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%w.2"),LOWORD(version.HighPart),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%w.3"),HIWORD(version.HighPart),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.0"),LOBYTE(LOWORD(version.LowPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.1"),HIBYTE(LOWORD(version.LowPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.2"),LOBYTE(HIWORD(version.LowPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.3"),HIBYTE(HIWORD(version.LowPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.4"),LOBYTE(LOWORD(version.HighPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.5"),HIBYTE(LOWORD(version.HighPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.6"),LOBYTE(HIWORD(version.HighPart)),1,std_out) ){
                        continue;
                    }
                    if( translate(output,&lpCh,len - (lpCh - lpszBuffer),_T("%b.7"),HIBYTE(HIWORD(version.HighPart)),1,std_out) ){
                        continue;
                    }
                }
            }
            default:{
                _fputtc(*lpCh,output);
                if(std_out){
                    _fputtc(*lpCh,stdout);
                }
            }
        }
    }
    free(lpszBuffer);
    fclose(output);
    return S_OK;
}


если используется следующий шаблон:
Код

...
VS_VERSION_INFO VERSIONINFO
PRODUCTVERSION    %w.3,%w.2,%w.1,%w.0
...

то эту версию продукта можно обнаружить по следующим полям:
Код

VS_FIXEDFILEINFO::dwProductVersionLS;
VS_FIXEDFILEINFO::dwProductVersionMS;

Программно можно обратиться к ним двумя способами:
1. Используя API для работы с версиями, например как показано здесь: http://www.ncsystems.ru/ru/programming/articles/fileversion/
2. Используя API для работы с ресурсами:
Код

inline bool GetFixedFileInfo(LPCVOID lpVersionResource,DWORD size,VS_FIXEDFILEINFO**lplpVsFixedFileInfo,WORD*lpLength){
    WORD*lpwLength,*lpwValueLength,*lpwType;
    WCHAR*lpKey;
    BYTE*lpPadding;
    ULONG_PTR module,key_length,length;
    LPCWSTR lpszKey    = L"VS_VERSION_INFO";
    //
    lpwLength        = (WORD*)lpVersionResource;
    lpwValueLength    = lpwLength + 1;
    lpwType            = lpwLength + 2;
    lpKey            = (WCHAR*)(lpwLength + 3);
    key_length        = wcslen(lpszKey);
    lpPadding        = (BYTE*)(lpKey + key_length + 1);
    length            = 3 * sizeof(WORD) + (key_length + 1) * sizeof(WCHAR);
    //
    if( (size < length) || (*lpwLength < length) ){
        return false;
    }
    if( !*lpwValueLength ){
        return false;
    }
    if( _wcsnicmp(lpKey,lpszKey,key_length) ){
        return false;
    }
    if(module = length % 4){
        lpPadding    -= module;
        lpPadding    += 4;
    }
    *lplpVsFixedFileInfo    = (VS_FIXEDFILEINFO*)lpPadding;
    *lpLength                = *lpwValueLength;
    return true;
}
inline ULONG64 GetProductVersion(HMODULE hModule,LPCTSTR lpName){
    LARGE_INTEGER        version;
    HRSRC                hRSrc;
    HGLOBAL                hResource;
    LPVOID                lpResource;
    VS_FIXEDFILEINFO    *lpFixed;
    DWORD                min_length;
    WORD                length;
    //
    version.QuadPart    = 0UL;
    if( hRSrc = ::FindResource(hModule,lpName,RT_VERSION) ){
        if( hResource = ::LoadResource(NULL,hRSrc) ){
            if( lpResource = ::LockResource(hResource) ){
                if( ::GetFixedFileInfo(lpResource,::SizeofResource(hModule,hRSrc),&lpFixed,&length) ){
                    if( lpFixed->dwSignature == 0xfeef04bd ){
                        min_length    = sizeof(DWORD) + max(
                            FIELD_OFFSET(VS_FIXEDFILEINFO,dwProductVersionMS),
                            FIELD_OFFSET(VS_FIXEDFILEINFO,dwProductVersionLS)
                        );
                        if( length >= min_length ){
                            version.LowPart        = lpFixed->dwProductVersionLS;
                            version.HighPart    = lpFixed->dwProductVersionMS;
                        }
                    }
                }
            }
        }
    }
    return version.QuadPart;
}

этот вариант хоть и работает согласно спецификации ресурса VERSIONINFO, но использовать его рекомендуется только в случае, когда ресурс версии имеет идентификатор, отличный от VS_VERSION_INFO = 1
либо когда таких ресурсов несколько

в обычном случае, ресурс можно использовать так:
Код

GetProductVersion(NULL,MAKEINTRESOURCE(VS_VERSION_INFO));

или так:
Код

LARGE_INTEGER version;
version.QuadPart    = ::GetProductVersion(NULL,MAKEINTRESOURCE(VS_VERSION_INFO));
HIWORD(version.HighPart);    // w.3
LOWORD(version.HighPart);    // w.2
HIWORD(version.LowPart);    // w.1
LOWORD(version.LowPart);    // w.0 - обычно build number


вот Rickert, тебе и макрос )

Присоединённый файл ( Кол-во скачиваний: 9 )
Присоединённый файл  VerBuilder_x64.rar 42,48 Kb


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Dem_max
Дата 3.4.2009, 19:11 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 16
Всего: 39



Господа вам не лениво было писать все это ? Столько коду и чтобы показать какая у вас версия в релизе. 


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
GremlinProg
Дата 3.4.2009, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



не показать, Dem_max, а учесть в ней реальное число билдов
ну и плюс обратная связь, соответственно


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1143 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.