42

我在以 SVN 作为源代码控制的示例项目中使用 CCNET。CCNET 配置为在每次签入时创建构建。CCNET 使用 MSBuild 构建源代码。

我想AssemblyInfo.cs在编译时使用最新的修订号来生成。如何从 subversion 中检索最新版本并使用 CCNET 中的值?

编辑:我没有使用 NAnt - 只有 MSBuild。

4

12 回答 12

45

CruiseControl.Net 1.4.4 现在有一个Assembly Version Labeller,它生成与 .Net 程序集属性兼容的版本号。

在我的项目中,我将其配置为:

<labeller type="assemblyVersionLabeller" incrementOnFailure="true" major="1" minor="2"/>

(警告:assemblyVersionLabeller在实际的提交触发构建发生之前,不会开始生成基于 svn 修订的标签。)

然后使用MSBuildCommunityTasks.AssemblyInfo从我的 MSBuild 项目中使用它:

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name="BeforeBuild">
  <AssemblyInfo Condition="'$(CCNetLabel)' != ''" CodeLanguage="CS" OutputFile="Properties\AssemblyInfo.cs" 
  AssemblyTitle="MyTitle" AssemblyCompany="MyCompany" AssemblyProduct="MyProduct"
  AssemblyCopyright="Copyright ©  2009" ComVisible="false" Guid="some-random-guid"
  AssemblyVersion="$(CCNetLabel)" AssemblyFileVersion="$(CCNetLabel)"/>
</Target>

为了完整起见,使用 NAnt 而不是 MSBuild 的项目同样容易:

<target name="setversion" description="Sets the version number to CruiseControl.Net label.">
    <script language="C#">
        <references>
            <include name="System.dll" />
        </references>
        <imports>
            <import namespace="System.Text.RegularExpressions" />
        </imports>
        <code><![CDATA[
             [TaskName("setversion-task")]
             public class SetVersionTask : Task
             {
              protected override void ExecuteTask()
              {
               StreamReader reader = new StreamReader(Project.Properties["filename"]);
               string contents = reader.ReadToEnd();
               reader.Close();
               string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["CCNetLabel"] + "\")]";
               string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
               StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
               writer.Write(newText);
               writer.Close();
              }
             }
             ]]>
        </code>
    </script>
    <foreach item="File" property="filename">
        <in>
            <items basedir="..">
                <include name="**\AssemblyInfo.cs"></include>
            </items>
        </in>
        <do>
            <setversion-task />
        </do>
    </foreach>
</target>
于 2009-06-10T12:37:30.197 回答
14

你基本上有两个选择。您可以编写一个简单的脚本来启动并解析来自

svn.exe 信息 --revision HEAD

获取修订号(然后生成 AssemblyInfo.cs 非常简单)或仅使用 CCNET 插件。这里是:

SVN Revision Labeller是 CruiseControl.NET 的插件,它允许您根据 Subversion 工作副本的修订号为您的构建生成 CruiseControl 标签。这可以使用前缀和/或主要/次要版本号进行自定义。

http://code.google.com/p/svnrevisionlabeller/

我更喜欢第一个选项,因为它只有大约 20 行代码:

using System;
using System.Diagnostics;

namespace SvnRevisionNumberParserSample
{
    class Program
    {
        static void Main()
        {
            Process p = Process.Start(new ProcessStartInfo()
                {
                    FileName = @"C:\Program Files\SlikSvn\bin\svn.exe", // path to your svn.exe
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    Arguments = "info --revision HEAD",
                    WorkingDirectory = @"C:\MyProject" // path to your svn working copy
                });

            // command "svn.exe info --revision HEAD" will produce a few lines of output
            p.WaitForExit();

            // our line starts with "Revision: "
            while (!p.StandardOutput.EndOfStream)
            {
                string line = p.StandardOutput.ReadLine();
                if (line.StartsWith("Revision: "))
                {
                    string revision = line.Substring("Revision: ".Length);
                    Console.WriteLine(revision); // show revision number on screen                       
                    break;
                }
            }

            Console.Read();
        }
    }
}
于 2008-08-04T11:56:42.533 回答
4

我在谷歌代码上找到了这个项目。这是CCNET生成标签的插件CCNET

DLL已经过测试,但CCNET 1.3它适用CCNET 1.4于我。我成功地使用这个插件来标记我的构建。

现在将其传递给MSBuild...

于 2008-08-04T11:51:59.297 回答
4

如果您更喜欢在配置上执行它MSBuildCCNet看起来MSBuild社区任务扩展的SvnVersion任务可能会成功。

于 2008-08-04T12:03:03.487 回答
4

我编写了一个 NAnt 构建文件来处理解析 SVN 信息和创建属性。然后,我将这些属性值用于各种构建任务,包括在构建上设置标签。我将此目标与 lubos hasko 提到的 SVN Revision Labeller 结合使用,效果很好。

<target name="svninfo" description="get the svn checkout information">
    <property name="svn.infotempfile" value="${build.directory}\svninfo.txt" />
    <exec program="${svn.executable}" output="${svn.infotempfile}">
        <arg value="info" />
    </exec>
    <loadfile file="${svn.infotempfile}" property="svn.info" />
    <delete file="${svn.infotempfile}" />

    <property name="match" value="" />

    <regex pattern="URL: (?'match'.*)" input="${svn.info}" />
    <property name="svn.info.url" value="${match}"/>

    <regex pattern="Repository Root: (?'match'.*)" input="${svn.info}" />
    <property name="svn.info.repositoryroot" value="${match}"/>

    <regex pattern="Revision: (?'match'\d+)" input="${svn.info}" />
    <property name="svn.info.revision" value="${match}"/>

    <regex pattern="Last Changed Author: (?'match'\w+)" input="${svn.info}" />
    <property name="svn.info.lastchangedauthor" value="${match}"/>

    <echo message="URL: ${svn.info.url}" />
    <echo message="Repository Root: ${svn.info.repositoryroot}" />
    <echo message="Revision: ${svn.info.revision}" />
    <echo message="Last Changed Author: ${svn.info.lastchangedauthor}" />
</target>
于 2008-08-04T13:43:54.530 回答
3

我目前正在使用我的cmdnetsvnrev工具通过 prebuild-exec 任务“手动”执行此操作,但如果有人知道更好的 ccnet 集成方式,我会很高兴听到 :-)

于 2008-08-04T11:41:37.133 回答
3

自定义 csproj 文件以自动生成 AssemblyInfo.cs
http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspx

每次我们创建一个新的 C# 项目时,Visual Studio 都会为我们放置 AssemblyInfo.cs 文件。该文件定义程序集元数据,如其版本、配置或生产者。

找到了使用 MSBuild 自动生成 AssemblyInfo.cs 的上述技术。将很快发布样品。

于 2008-08-04T13:22:31.640 回答
3

我不确定这是否适用于 CCNET,但我已经为 CodePlex 上的Build Version Increment项目创建了一个SVN 版本插件。该工具非常灵活,可以设置为使用 svn 修订版自动为您创建版本号。它不需要编写任何代码或编辑 xml,所以耶!

我希望这会有所帮助!

于 2010-04-12T01:04:20.763 回答
2

我的方法是使用前面提到的 ccnet 插件和一个 nant echo 任务来生成一个VersionInfo.cs只包含版本属性的文件。我只需要将VersionInfo.cs文件包含到构建中

echo 任务只是将我给它的字符串输出到一个文件中。

如果有类似的 MSBuild 任务,您可以使用相同的方法。这是我使用的小任务:

<target name="version" description="outputs version number to VersionInfo.cs">
  <echo file="${projectdir}/Properties/VersionInfo.cs">
    [assembly: System.Reflection.AssemblyVersion("$(CCNetLabel)")]
    [assembly: System.Reflection.AssemblyFileVersion("$(CCNetLabel)")]
  </echo>
</target>

试试这个:

<ItemGroup>
    <VersionInfoFile Include="VersionInfo.cs"/>
    <VersionAttributes>
        [assembly: System.Reflection.AssemblyVersion("${CCNetLabel}")]
        [assembly: System.Reflection.AssemblyFileVersion("${CCNetLabel}")]
    </VersionAttributes>
</ItemGroup>
<Target Name="WriteToFile">
    <WriteLinesToFile
        File="@(VersionInfoFile)"
        Lines="@(VersionAttributes)"
        Overwrite="true"/>
</Target>

请注意,我对 MSBuild 不是很熟悉,所以我的脚本可能无法开箱即用,需要更正......

于 2009-02-03T04:16:04.260 回答
2

基于 skolimas 解决方案,我更新了 NAnt 脚本以更新 AssemblyFileVersion。感谢 skolima 的代码!

<target name="setversion" description="Sets the version number to current label.">
        <script language="C#">
            <references>
                    <include name="System.dll" />
            </references>
            <imports>
                    <import namespace="System.Text.RegularExpressions" />
            </imports>
            <code><![CDATA[
                     [TaskName("setversion-task")]
                     public class SetVersionTask : Task
                     {
                      protected override void ExecuteTask()
                      {
                       StreamReader reader = new StreamReader(Project.Properties["filename"]);
                       string contents = reader.ReadToEnd();
                       reader.Close();                     
                       // replace assembly version
                       string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["label"] + "\")]";
                       contents = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);                                        
                       // replace assembly file version
                       replacement = "[assembly: AssemblyFileVersion(\"" + Project.Properties["label"] + "\")]";
                       contents = Regex.Replace(contents, @"\[assembly: AssemblyFileVersion\("".*""\)\]", replacement);                                        
                       StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
                       writer.Write(contents);
                       writer.Close();
                      }
                     }
                     ]]>
            </code>
        </script>
        <foreach item="File" property="filename">
            <in>
                    <items basedir="${srcDir}">
                            <include name="**\AssemblyInfo.cs"></include>
                    </items>
            </in>
            <do>
                    <setversion-task />
            </do>
        </foreach>
    </target>
于 2009-09-12T10:03:28.150 回答
2

不知道我在哪里找到这个。但我在互联网上的“某处”找到了这个。

这会在构建发生之前更新所有 AssemblyInfo.cs 文件。

奇迹般有效。我所有的 exe 和 dll 都显示为 1.2.3.333(如果“333”是当时的 SVN 修订版。)(并且 AssemblyInfo.cs 文件中的原始版本被列为“1.2.3.0”)


$(ProjectDir) (我的 .sln 文件所在的位置)

$(SVNToolPath) (指向 svn.exe)

是我的自定义变量,它们的声明/定义未在下面定义。


http://msbuildtasks.tigris.org/ 和/或 https://github.com/loresoft/msbuildtasks 具有( FileUpdate 和 SvnVersion )任务。


  <Target Name="SubVersionBeforeBuildVersionTagItUp">

    <ItemGroup>
      <AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
    </ItemGroup>

    <SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
      <Output TaskParameter="Revision" PropertyName="MySubVersionRevision" />
    </SvnVersion>

    <FileUpdate Files="@(AssemblyInfoFiles)"
            Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
            ReplacementText="$1.$2.$3.$(MySubVersionRevision)" />
  </Target>

编辑 - - - - - - - - - - - - - - - - - - - - - - - - - -

在您的 SVN 修订号达到 65534 或更高版本后,上述操作可能会开始失败。

看:

关闭警告 CS1607

这是解决方法。

<FileUpdate Files="@(AssemblyInfoFiles)"
Regex="AssemblyFileVersion\(&quot;(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="AssemblyFileVersion(&quot;$1.$2.$3.$(SubVersionRevision)" />

结果应该是:

在 Windows/资源管理器//文件/属性中……。

程序集版本将为 1.0.0.0。

如果 333 是 SVN 修订版,则文件版本将为 1.0.0.333。

于 2012-09-18T17:18:26.017 回答
1

当心。用于内部版本号的结构很短,因此您对修订可以达到多高有一个上限。

在我们的例子中,我们已经超过了限制。

如果您尝试输入内部版本号 99.99.99.599999,则文件版本属性实际上将显示为 99.99.99.10175。

于 2009-02-03T18:34:49.067 回答