Как программно изменить версию продукта проекта? - PullRequest
11 голосов
/ 20 ноября 2008

Вот моя проблема:

У меня есть несколько проектов развертывания. Чтобы развернуть приложение, мне нужно выполнить несколько задач, одна из которых - изменить версию продукта и код продукта каждого проекта развертывания.

Я не могу найти способ программно изменить их.

Кто-нибудь может мне помочь?

Заранее спасибо.

ОБНОВЛЕНИЕ: Так как это проект развертывания (который, наконец, создает исполняемый установщик), я не могу работать с MSBuild, вместо этого я использую Devenv из командной строки. (Бруно, спасибо за быстрый ответ).

Ответы [ 11 ]

11 голосов
/ 29 декабря 2008

Я искал точно такую ​​же вещь сегодня. Я нашел это с помощью Google:

static void Main(string[] args) 
{
    string setupFileName = @"<Replace the path to vdproj file>"; 
    StreamReader reader = File.OpenText(setupFileName); 
    string file = string.Empty; 

    try 
    { 
        Regex expression = new Regex(@"(?:\""ProductCode\"" = 
        \""8.){([\d\w-]+)}"); 
        Regex expression1 = new Regex(@"(?:\""UpgradeCode\"" = 
        \""8.){([\d\w-]+)}"); 
        file = reader.ReadToEnd(); 

        file = expression.Replace(file, "\"ProductCode\" = \"8:{" + 
        Guid.NewGuid().ToString().ToUpper() + "}"); 
        file = expression1.Replace(file, "\"UpgradeCode\" = \"8:{" 
        + Guid.NewGuid().ToString().ToUpper() + "}"); 
    } 
    finally 
    { 
        // Close the file otherwise the compile may not work 
        reader.Close(); 
    } 

    TextWriter tw = new StreamWriter(setupFileName); 
    try 
    { 
        tw.Write(file); 
    } 
    finally 
    { 
        // close the stream 
        tw.Close(); 
    } 
 }
5 голосов
/ 29 декабря 2008

Я знаю, что оригинальный постер ищет .NET 2.0 решение этой проблемы. Однако, поскольку он не был помечен как .NET, я предложу свое решение C ++ для этой проблемы. Это может быть применимо к земле .NET, но я оставлю это другим.

Это не только обновляет информацию о версии в поле about и файле журнала для моего приложения, но также и всю информацию о версии Windows, которая отображается в Проводнике Windows.

ОБНОВЛЕНИЕ: Добавлены некоторые изменения, которые я сделал в процессе со времени моего первоначального ответа.

Прежде всего, я переместил весь блок информации о версии из моего файла Project.rc в мой файл Project.rc2:

/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
 FILEVERSION FILE_VER
 PRODUCTVERSION PROD_VER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
  FILEFLAGS 0x1L
#else
  FILEFLAGS 0x0L
#endif
  FILEOS 0x4L
  FILETYPE 0x1L
  FILESUBTYPE 0x0L
BEGIN
   BLOCK "StringFileInfo"
   BEGIN
       BLOCK "040904e4"
       BEGIN
           VALUE "CompanyName", "MyCompany"
           VALUE "FileDescription", "Software Description"
           VALUE "FileVersion", 1,0,0,1
           VALUE "InternalName", "FileName.exe"
           VALUE "LegalCopyright", "(c) 2008 My Company.  All rights reserved."
           VALUE "OriginalFilename", "FileName.exe"
           VALUE "ProductName", "Product Name"
           VALUE "ProductVersion", 1,0,0,1
       END
   END
   BLOCK "VarFileInfo"
   BEGIN
       VALUE "Translation", 0x409, 1252
   END
END

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

Затем я создал файл VersionInfo.h и добавил его в свой проект:

#pragma once

//major release version of the program, increment only when major changes are made
#define VER_MAJOR 2

//minor release version of the program, increment if any new features are added
#define VER_MINOR 0

//any bugfix updates, no new features
#define VER_REV 0

//if this is some special release (e.g. Alpha 1) put the special release string here
#define STR_SPECIAL_REL "Alpha 1"


#define FILE_VER VER_MAJOR,VER_MINOR,VER_REV
#define PROD_VER FILE_VER

//these are special macros that convert numerical version tokens into string tokens
//we can't use actual int and string types because they won't work in the RC files
#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)

#define STR_FILE_VER STRINGIZE(VER_MAJOR) "." STRINGIZE(VER_MINOR) "." STRINGIZE(VER_REV)
#define STR_PROD_VER STR_FILE_VER " " STR_SPECIAL_REL

#define STR_COPYRIGHT_INFO "©" BuildYear " Your Company. All rights reserved."

Затем я включил VersionInfo.h в файл rc2 и внес следующие изменения:

#include "VersionInfo.h"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//

<no changes>
           VALUE "FileVersion", STR_FILE_VER
           <no changes>
           VALUE "LegalCopyright", STR_COPYRIGHT_INFO
           <no changes>
           VALUE "ProductVersion", STR_PROD_VER
<no changes>

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

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

#define CurrentBuildNumber  "20081020P1525" 

По сути, это дата и время начала сборки. Я создал командный файл, который запускается как событие перед сборкой проекта, который генерирует этот файл. Сценарий также определяет BuildYear, так что авторское право в файле VersionInfo.h всегда содержит год самой последней сборки. Пакетный скрипт выглядит следующим образом:

    echo Generating Build Number
    @For /F "tokens=2,3,4 delims=/ " %%A in ('Date /t') do @(
    Set Month=%%A
    Set Day=%%B
    Set Year=%%C
    )

    @For /F "tokens=1,2,3 delims=/M: " %%A in ('Time /t') do @(
    Set Hour=%%A
    Set Minute=%%B
    Set AmPm=%%C
    )

    @echo #define CurrentBuildNumber  "%Year%%Month%%Day%%AmPm%%Hour%%Minute%" > "$(ProjectDir)\build_number.incl"
    @echo #define BuildYear "%Year%" >> "$(ProjectDir)\build_number.incl"
    echo ----------------------------------------------------------------------

Этот файл затем включается в любой файл в проекте, для которого требуется использовать номер сборки (т. Е. Поле about).

Часть этого была взята из этого поста CodeProject.

Надеюсь, эта информация окажется полезной.

2 голосов
/ 10 марта 2009

У меня была та же проблема, и я обнаружил, что изменение файла .vdproj в prebuildevent не совсем то, что мне нравится.

Я использовал другой код для изменения файла msi после сборки проекта установки, поэтому я использую postbuildevent.

Смотрите мой блог здесь .

1 голос
/ 20 ноября 2008

Мы используем программу, которая обновляет каждый файл AssemblyInfo.cs или AssemblyInfo.vb на основе значения файла конфигурации. мы запускаем этот исполняемый файл перед каждой сборкой. Это было лучшее, что мы могли сделать, чтобы автоматизировать этот процесс. Вы можете добавить вызов к этому пакетному процессу в конфигурации вашего проекта в качестве шага предварительной сборки.

0 голосов
/ 12 августа 2015

Я знаю, что это очень старая тема, но вот решение VBS для достижения той же цели. Просто поместите его в папку развертывания рядом с файлом .vdproj.

Function CreateGuid()
    CreateGuid = Left(CreateObject("Scriptlet.TypeLib").Guid,38)
End Function

Const ForReading = 1, ForWriting = 2, ForAppending = 8

Set fso = CreateObject("Scripting.FileSystemObject")
Set RegEx = CreateObject("VBScript.RegExp")

For Each file in fso.GetFolder(".").Files
    if (fso.GetExtensionName(file.Name) = "vdproj") then
        WScript.Echo "Updating: " + file.Name
        Set oFile = fso.OpenTextFile(file.Name, ForReading, True)
        fileContents = oFile.ReadAll
        oFile.Close
        RegEx.Pattern = """ProductCode"" = ""8:{.*-.*-.*-.*-.*}"
        fileContents=Regex.Replace(fileContents, """ProductCode"" = ""8:" & CreateGuid)
        Set oFile = fso.OpenTextFile(file.Name, ForWriting, True)
        oFile.Write fileContents
        oFile.Close
    end if
Next

Затем в вашем реальном проекте проведите событие после сборки, похожее на:

cd $(SolutionDir)\CustomWebSetup
cscript -nologo UpdateProductCode.vbs

Это обновит vdproj новым ProductCode при подготовке к следующей сборке. После завершения сборки VS запросит перезагрузку проекта развертывания.

0 голосов
/ 08 сентября 2009
0 голосов
/ 28 января 2009

Консоль тюнера ресурсов

Этот консольный редактор ресурсов позволяет создавать надежные и воспроизводимые процесс обновления информации о версии продукта во время финала этап процесса сборки из командной строки.

Более подробно см. Страницу пакетной обработки информации о версии файла :

0 голосов
/ 29 декабря 2008

Изучите использование RCS, CVS и / или Subversion. Я знаком только с RCS; Насколько я понимаю, CVS основан на RCS, но более всеобъемлющ. Я читал на разных досках, что подрывная деятельность лучше, но я никогда не использовал ее. RCS достаточно для отслеживания изменений и версий всех моих документов и программных проектов.

RCS здесь: http://www.cs.purdue.edu/homes/trinkle/RCS/

CVS здесь: http://www.nongnu.org/cvs/

Subversion здесь: http://subversion.tigris.org/

0 голосов
/ 20 ноября 2008

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

0 голосов
/ 20 ноября 2008

Встраивание номера редакции SVN во время компиляции в приложение Windows

В своем ответе на этот вопрос я опишу, как выполнить эту задачу с помощью SVN.

...