Увеличение номера сборки
От: denaturat  
Дата: 04.07.06 05:45
Оценка: 36 (3)
#Имя: FAQ.tools.vs.autobuildcount
Давно сие спрашивают, и наконец-то руки дошли. Это все для VC# 2005 Express, но если немного поменять пару строк, то можно и в обычных Win32-проектах использовать.

Работа скрипта основана на простом поиске вхождения указанной подстроки с версией, выдирании фрагмента в кавычках, разборе его и инкрементировании номера ревизии.

Я тут извращения ради изменяю сразу и AssemblyVersion, и AssemblyFileVersion

Если вы пишете под Win, то в файле ресурсов имеется секция VERSIONINFO, порывшись в которой, можно подправить сей скрипт.

Как его использовать?
1. Засуньте в каталог Properties
2. Запишите в свойствах проекта pre-build event как "$(ProjectDir)Properties\buildinc.js", причем, обязательно в кавычках
3. Готово, правда при каждом нажатии на Ctrl+F5, даже если проект уже был до этого собран, pre-build event снова сработает, соответственно, скрипт тоже запустится и build снова произойдет.

Удачи, и жду замечаний.


/* 
   buildinc.js
   Скрипт для автоматического увеличения номера ревизии/сборки
   для проектов Visual C# (VS 2005 Express)
   файл должен содержать строку вида
   [assembly: AssemblyVersion("0.1.0.0")]
   эта строка ищется и изменяется с инкрементированием номера ревизии
*/

// чтение содержимого файла
function fnLoadContent(filename)
{
    fileObj = new ActiveXObject("Scripting.FileSystemObject");
    var ForReading = 1, ForWriting = 2, ForAppending = 8;
    var TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0;
    
    f = fileObj.GetFile(filename);
    ts = f.OpenAsTextStream(ForReading, TristateUseDefault);
    var s = ts.ReadAll();         // прочитать и вывести весь файл
    ts.Close();                   // закрыть текстовый поток
    return s;
}

// sContent - содержимое файла. В случае обнаружения искомой 
// строки оно изменяется на новое значение
function fnIncrementVerInfo(sContent, sAssemblyOrFile)
{
    var searchString = sAssemblyOrFile;
    var begin = sContent.indexOf(searchString);
    if (begin < 0)
        return sContent;
    begin += searchString.length;
    // найти конец строки с информацией о версии
    var end = sContent.indexOf("\")]", begin);
    if (end < 0)
        return sContent;
    var verMajor = 0;
    var verMinor = 0;
    var build = 0;
    var revision = 0;
    
    // эту часть текста мы вырежем и заменим новой информацией о версии
    var cutBegin = begin;
    var cutEnd = end;
    
    // копируем строку с версией
    var info = sContent.substring(begin, end);
    // разбираем
    
    // старший номер версии
    begin = 0;
    end = info.indexOf(".");
    if (end < 0)
        return sContent;
    verMajor = info.substring(begin, end);

    info = info.substr(end+1);

    // младший номер версии
    begin = 0;
    end = info.indexOf(".");
    if (end < 0)
        return sContent;
    verMinor = info.substring(begin, end);

    info = info.substr(end+1);
    
    // сборка
    begin = 0;
    end = info.indexOf(".");
    if (end < 0)
        return sContent;
    build = info.substring(begin, end);

    info = info.substr(end+1);
    
    // ревизия
    begin = 0;
    end = info.length;
    if (end < 0)
        return sContent;
    revision = info;

    // увеличиваем номер
    revision++;
    var info = verMajor + "." + verMinor + "." + build + "." + revision;
    
    // собираем новый файл
    var s = sContent.substring(0, cutBegin) + info + sContent.substring(cutEnd, sContent.length);
    return s;
}

// основная программа
function main()
{
    var sFileToParse = "..\\..\\Properties\\AssemblyInfo.cs";
    // открыть файл
    var content = fnLoadContent(sFileToParse);
    // увеличить номер ревизии
    content = fnIncrementVerInfo(content, "[assembly: AssemblyVersion(\"");
    content = fnIncrementVerInfo(content, "[assembly: AssemblyFileVersion(\"");
    // Создать объект FileSystemObject.
    var myFileSysObj = new ActiveXObject("Scripting.FileSystemObject")
    // Создать объект TextStream.
    var myTextStream = myFileSysObj.OpenTextFile(sFileToParse, 2, true)
    // Записать в файл результат
    myTextStream.Write(content);
}

// пуск
main();
Re: Увеличение номера сборки
От: denaturat  
Дата: 04.07.06 05:52
Оценка:
Небольшое замечание. Бывает так, что вместо того, чтобы скрипту запуститься, выскакивает Блокнот. Просто кто-то с кривыми руками попортил вашу систему. В свойствах папки выберите "Типы файлов", найдите расширение JS, нажмите кнопку "Дополнительно", для действия "Открыть" запишите
cscript.exe "%1"

вроде теперь все.
Re: Увеличение номера сборки
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 04.07.06 07:27
Оценка:
Здравствуйте, denaturat, Вы писали:

D>Давно сие спрашивают, и наконец-то руки дошли.


как бы извратиться что оно только при сборках Release срабатывало?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Увеличение номера сборки
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 04.07.06 08:10
Оценка: 9 (1)
OE>как бы извратиться что оно только при сборках Release срабатывало?

уже извратился :

Pre-Build Event:
"$(ProjectDir)Properties\buildinc.js" "$(ConfigurationName)"

и

// основная программа
function main()
{
   var args = WScript.Arguments;
      
   if( args(0) == "Release")
   {
      var sFileToParse = "..\\..\\Properties\\AssemblyInfo.cs";
      // открыть файл
      var content = fnLoadContent(sFileToParse);
      // увеличить номер ревизии
      content = fnIncrementVerInfo(content, "[assembly: AssemblyVersion(\"");
      content = fnIncrementVerInfo(content, "[assembly: AssemblyFileVersion(\"");
      // Создать объект FileSystemObject.
      var myFileSysObj = new ActiveXObject("Scripting.FileSystemObject")
      // Создать объект TextStream.
      var myTextStream = myFileSysObj.OpenTextFile(sFileToParse, 2, true)
      // Записать в файл результат
      myTextStream.Write(content);
   }
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Увеличение номера сборки
От: denaturat  
Дата: 04.07.06 08:18
Оценка:
Re: Увеличение номера сборки
От: stasukas  
Дата: 04.07.06 10:26
Оценка: 4 (1)
Здравствуйте, denaturat, Вы писали:

Есть еще addin для студии (для тех, кто делает сборки из студии). Поддерживает VS2002?, VS2003, VS2005.
http://www.codeproject.com/dotnet/versioningcontrolledbuild.asp
... << RSDN@Home 1.2.0 alpha rev. 653>>
C:\>DUMP StateOf(My.Brain) >> http://www.usecase.ru/
Re[2]: Увеличение номера сборки
От: denaturat  
Дата: 05.07.06 05:14
Оценка:
Здравствуйте, stasukas, Вы писали:

S>Здравствуйте, denaturat, Вы писали:


S>Есть еще addin для студии (для тех, кто делает сборки из студии). Поддерживает VS2002?, VS2003, VS2005.

S>http://www.codeproject.com/dotnet/versioningcontrolledbuild.asp

Вот вся фигня-то в том, что для Express это и много другое не ставится, вот и извращаемся, как можем.
Re: Увеличение номера сборки
От: adontz Грузия http://adontz.wordpress.com/
Дата: 21.01.08 11:49
Оценка: 4 (1)
Здравствуйте, denaturat, Вы писали:

D>Удачи, и жду замечаний.


Вот натолкнулся, решил поделится своей разработкой
То что ниже не увеличивает номер версии, а устанавливает его равным ревизии SVN. Это удобно, так как позволяет по бинарнику точно понять с какого кода он скомпилирован.

CMD скрипт
@if "%SVN_PATH%" == "" (
@goto NO_SVN
)

"%SVN_PATH%" update "Source"
Executables\Utilities\Nabu.SvnToVersion.exe -pd "Source" -td "Source" -tf "AssemblyInfo.cs" -re ?.net
"%SVN_PATH%" commit --editor-cmd notepad.exe "Source"

@goto EXIT

:NO_SVN
@echo Environment variable %%SVN_PATH%% with value of path to svn.exe must be defined.
@goto EXIT

:EXIT

утилита
http://nabu-library.googlecode.com/svn/trunk/Source/Utilities/Nabu.SvnToVersion/
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[3]: Увеличение номера сборки
От: _FRED_ Черногория
Дата: 21.01.08 13:01
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>>как бы извратиться что оно только при сборках Release срабатывало?

OE>уже извратился :

OE>Pre-Build Event:

OE>// основная программа


ИМХО, кузявее эту логику вынести из скрипта в Pre-Build Event:
If "$(ConfigurationName)" == "Release" (
  Rem …
)
Help will always be given at Hogwarts to those who ask for it.
Re: Увеличение номера сборки
От: Left2 Украина  
Дата: 21.01.08 13:25
Оценка: +1
D>2. Запишите в свойствах проекта pre-build event как "$(ProjectDir)Properties\buildinc.js", причем, обязательно в кавычках
cscript.exe //NoLogo "$(ProjectDir)Properties\buildinc.js"
И никто больше шаловливыми ручками систему не испортит

D>Удачи, и жду замечаний.

Из есть у меня

Искать подстроки по indexOf — это путь (как бы так сказать) "нелёгкий". В JS (как и во многих других языках) рулят регэкспы. Вот для примера кусок моего скрипта который работает с ресурсным файлом (инкрементит младший номер версии, старшие выставляет в месяц-день):

function IncrementRCVersion(strRCFileName, iVersion)
{    
    var objStream = objFileSystem.OpenTextFile(strRCFileName, 1);
    var objOutStream = objFileSystem.CreateTextFile(strRCFileName + ".new", true);
    
    var arrToSearch = [
        "^(\\s*FILEVERSION\\s+)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(.*)$",
        "^(\\s*PRODUCTVERSION\\s+)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(.*)$",
        "^(\\s*VALUE\\s*\"FolderVersion\"\\s*,\\s*\")(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(\".*)",
        "^(\\s*VALUE\\s*\"FileVersion\"\\s*,\\s*\")(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(\".*)",
        "^(\\s*VALUE\\s*\"ProductVersion\"\\s*,\\s*\")(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(,\\s*)(\\d+)(\".*)"
    ];
    
    while (!objStream.AtEndOfStream)
    {
        var strLine = objStream.ReadLine(); 

        for (var i=0; i<arrToSearch.length; ++i)
        {
            var objRegExp = new RegExp(arrToSearch[i], "");
                        
            if (objRegExp.exec(strLine) != null)
            {
                var strMonth = "" + ((new Date()).getMonth() + 1);
                var strDay = "" + ((new Date()).getDate());
                if (typeof(iVersion) == "undefined")
                {
                    iVersion = parseInt(RegExp.$8, 10) + 1;
                }
                var strBuild = "" + iVersion;
                strLine = RegExp.$1 + 
                    "1" + RegExp.$3 + // Version
                    strMonth + RegExp.$5 + // Month
                    strDay + RegExp.$7 + // Day
                    strBuild + RegExp.$9; // Version number (auto-increment)
            }
        }
        
        objOutStream.WriteLine(strLine);
    }
    objStream.Close();
    objOutStream.Close();
    
    // Replace RC file
    CopyFile(strRCFileName + ".new", strRCFileName);    
    
    // Remove temporary file
    objFileSystem.DeleteFile(strRCFileName + ".new");
    
    return iVersion;
}
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[4]: Увеличение номера сборки
От: Left2 Украина  
Дата: 21.01.08 13:36
Оценка: 1 (1)
_FR>ИМХО, кузявее эту логику вынести из скрипта в Pre-Build Event:

Честно говоря не люблю Pre- и Post- ивенты. Натыкался на глюки непонятности при их работе. Посему обычно добавляю в проект отдельный текстовый файл типа IncrementVersion.txt у которого custom build step выставляю в вызов скрипта. А для rc-файла ставлю этот IncrementVersion.txt в additional dependencies. Тогда и с тем чтобы отключить это в Debug или Release проблем не возникает.

А вообще самый правильный путь здесь (ИМХО!) это написать скрипт который билдит релиз, благо кроме собственно билда Exe и Dll наверняка приходится делать кучу дополнительных задач (у меня к примеру есть в проекте куча XML-файлов, билд скрипт проверяет их на валидность, и т.д. и т.п.). Вот именно в этом скрипте самое место инкременту версии.
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[2]: Увеличение номера сборки
От: Left2 Украина  
Дата: 21.01.08 13:36
Оценка: 28 (2)
D>>2. Запишите в свойствах проекта pre-build event как "$(ProjectDir)Properties\buildinc.js", причем, обязательно в кавычках
L>cscript.exe //NoLogo "$(ProjectDir)Properties\buildinc.js"
L>И никто больше шаловливыми ручками систему не испортит

Да, кстати — огромное преимущество использования JScript для таких задач — это то что эти скрипты очень легко отладить. Для этого добавляем ключик /D
cscript.exe //D //NoLogo "$(ProjectDir)Properties\buildinc.js"

И в теле скрипта пишем там где нам нужно остановиться:
debugger;

Всё, при достижении этой строчки нас спросят каким дебагером аттачится (если на машине стоит более одной версии Visual Studio). Аттачимся любой из них (можно даже той же из которой запустили билд) и отлаживаемся на здоровье. Можно даже после окончания отладки ключик //D не выкидывать — на нормальную работу он не окажет никакого влияния, а вот при возникновении исключения тут же предложит всё это отладить.
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[2]: Увеличение номера сборки
От: Vain Россия google.ru
Дата: 21.01.08 14:01
Оценка:
Здравствуйте, denaturat, Вы писали:

D>Небольшое замечание. Бывает так, что вместо того, чтобы скрипту запуститься, выскакивает Блокнот. Просто кто-то с кривыми руками попортил вашу систему. В свойствах папки выберите "Типы файлов", найдите расширение JS, нажмите кнопку "Дополнительно", для действия "Открыть" запишите

D>
D>cscript.exe "%1"
D>

D>вроде теперь все.
Не проще ли сразу батник сделать который скрипт запускает?
cscript.exe "%~1" //Nologo
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Увеличение номера сборки
От: _FRED_ Черногория
Дата: 21.01.08 15:24
Оценка:
Здравствуйте, Left2, Вы писали:

_FR>>ИМХО, кузявее эту логику вынести из скрипта в Pre-Build Event:


L>Честно говоря не люблю Pre- и Post- ивенты. Натыкался на глюки непонятности при их работе.




L>Посему обычно добавляю в проект отдельный текстовый файл типа IncrementVersion.txt у которого custom build step выставляю в вызов скрипта. А для rc-файла ставлю этот IncrementVersion.txt в additional dependencies. Тогда и с тем чтобы отключить это в Debug или Release проблем не возникает.


Ага, ты это в шестой студии делаешь или где?

L>А вообще самый правильный путь здесь (ИМХО!) это написать скрипт который билдит релиз, благо кроме собственно билда Exe и Dll наверняка приходится делать кучу дополнительных задач (у меня к примеру есть в проекте куча XML-файлов, билд скрипт проверяет их на валидность, и т.д. и т.п.). Вот именно в этом скрипте самое место инкременту версии.


Build — скрипт это немного другое. Например, используя указанный If по конфигурации могу запускать post-build утилиты (которые, вообще говоря, понятия не имеют о конфигурациях средства разработки) с разным набором параметров:
If "$(ConfigurationName)" == "Debug" (
  Rem Создаёт результат SGen в отдельной папке, сохраняя исходники для отладки
  SGen.exe /Force /Assembly:"$(TargetPath)" /Out:"$(TargetDir)SGenOutput" /ParsableErrors /NoLogo /Debug /Keep
  Copy /Y "$(TargetDir)SGenOutput\$(TargetName).XmlSerializers.dll" "$(TargetDir)"
  Copy /Y "$(TargetDir)SGenOutput\$(TargetName).XmlSerializers.pdb" "$(TargetDir)"
) Else (
  Rem Просто создаёт результирующю сборку "без мусора"
  SGen.exe /Force /Assembly:"$(TargetPath)" /ParsableErrors /NoLogo
)

Выносить этот If в скрипт, которому передаётся параметр — — из скрипта не будет доступа к таким полезным вещам как $(TargetDir), $(TargetPath), … Пережавать их все в качестве параметров тоже не красиво.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Увеличение номера сборки
От: Left2 Украина  
Дата: 21.01.08 16:01
Оценка:
L>>Посему обычно добавляю в проект отдельный текстовый файл типа IncrementVersion.txt у которого custom build step выставляю в вызов скрипта. А для rc-файла ставлю этот IncrementVersion.txt в additional dependencies. Тогда и с тем чтобы отключить это в Debug или Release проблем не возникает.
_FR>Ага, ты это в шестой студии делаешь или где?
Да натыкался по-моему и в 2003-й.

L>>А вообще самый правильный путь здесь (ИМХО!) это написать скрипт который билдит релиз, благо кроме собственно билда Exe и Dll наверняка приходится делать кучу дополнительных задач (у меня к примеру есть в проекте куча XML-файлов, билд скрипт проверяет их на валидность, и т.д. и т.п.). Вот именно в этом скрипте самое место инкременту версии.

_FR>Build — скрипт это немного другое.

Ну у меня к примеру есть два вида скриптов для билда:
1. Главный билд-скрипт, у которого на выходе — готовая инсталляция продукта. В числе прочих задач он запускает devenv.com с параметром Release.
2. "Мелкие" билд-скрипты — они вызываются самой студией и работают в custom build steps, нужны для кодогенерации каких-то кусков, т.д. и т.п.

К примеру, инкрементить версию лучше в главном билд-скрипте, дабы экономить время на билдах. Он, в свою очередь, запустит "мелкие" билд-скрипты в процессе билда solution-а (вернее, запустит-то их devenv.com).
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[2]: Увеличение номера сборки
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 25.01.08 09:55
Оценка:
Здравствуйте, adontz, Вы писали:

A>утилита

A>http://nabu-library.googlecode.com/svn/trunk/Source/Utilities/Nabu.SvnToVersion/

еще есть SubWCRev.exe
... << RSDN@Home 1.2.0 alpha rev. 786>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.