Использование MSBuild для обновления FILEVERSION в файле ресурсов C++ приводит к сбоям компиляции

мне было поручено автоматизировать процесс сборки с помощью msbuild. У нас есть около двадцати проектов Visual C++ и двадцать проектов C#, что делает боль вручную редактировать все строки версии. Наши номера версий генерируются во время сборки, поэтому нам нужно передать строку полной версии как свойство в командной строке.

моя первоначальная реализация используется Расширение В MSBuild Пакет ' s File задача сделать замены на .rc и AssemblyInfo.cs файлы.

<FileSystem.File TaskAction="Replace" Files="@(AssemblyInfoFiles)" RegexPattern='[assembly: AssemblyVersion(".*")]' Replacement='[assembly: AssemblyVersion("$(Version)")]'/>
<FileSystem.File TaskAction="Replace" Files="@(AssemblyInfoFiles)" RegexPattern='[assembly: AssemblyFileVersion(".*")]' Replacement='[assembly: AssemblyFileVersion("$(Version)")]'/>
<FileSystem.File TaskAction="Replace" Files="@(RCFiles)" RegexPattern="FILEVERSIONs+S+" Replacement="FILEVERSION $(Version)"/>
<FileSystem.File TaskAction="Replace" Files="@(RCFiles)" RegexPattern="PRODUCTVERSIONs+S+" Replacement="PRODUCTVERSION $(Version)"/>
<FileSystem.File TaskAction="Replace" Files="@(RCFiles)" RegexPattern='VALUEs+"FileVersion",s*".*"' Replacement='VALUE "FileVersion", "$(Version)"'/>
<FileSystem.File TaskAction="Replace" Files="@(RCFiles)" RegexPattern='VALUEs+"ProductVersion",s*".*"' Replacement='VALUE "ProductVersion", "$(Version)"'/>

это отлично работает на AssemblyInfo.cs файлы, но когда я компилирую любой из проектов c++, я получаю такие ошибки:

.MyProject.rc(23): error RC2135: file not found: 0x09
.MyProject.rc(71): error RC2135: file not found: 1
.MyProject.rc(72): error RC2135: file not found: 6
.MyProject.rc(73): error RC2135: file not found: 6
.MyProject.rc(74): error RC2135: file not found: 0x3fL
.MyProject.rc(80): error RC2135: file not found: FILEOS
.MyProject.rc(81): error RC2135: file not found: 0x2L
.MyProject.rc(84): error RC2164: unexpected value in RCDATA
.MyProject.rc(86): error RC2135: file not found: BLOCK
.MyProject.rc(88): error RC2135: file not found: VALUE

первая ошибка встречается в строке 23, но когда я diff MyProject.rc против управления версиями все выглядит нормально. Изменяются только номера версий, эти изменения начинаются в строке 72, а строка 0x09 не отображается нигде в файле. Что здесь происходит? Строк 21 - 25 выглядеть это:

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

Я также открыт для любых предложений по другим методам достижения той же цели.

3 ответов


функция Replace taskaction вставляла символы Юникода, в то время как rc-файлы используют кодировку ASCII. Добавление TextEncoding= "ASCII" ко всем задачам замены rc приводит к компилируемым файлам.

ограничение использования набора символов ASCII заключается в том, что вы не можете использовать символ©. Но если вы выберете TextEncoding= "Windows-1252", это решит проблему.


Я бы отделил информацию о версии от AssemblyInfo.cs и *.rc файлы. Создайте AssemblyVersion.cs и Version.rc файл, который содержит (общую) информацию о версиях для всех ваших сборок. Вы создадите их в начале сборки. Поскольку они содержат только сведения о версиях, которые не нужно использовать регулярные выражения, можно перезаписать весь файл каждый раз.


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

я использовал MSBuild Функции Собственность. Я уверен, что вы можете regex/заменить их тоже.

<FileSystem.File TaskAction="Replace" 
                 TextEncoding="ASCII" 
                 Files="@(AppResource)" 
                 RegexPattern="FILEVERSION\s+\S+" 
                 Replacement="FILEVERSION $(Version.Replace('.',','))"/>