I have a requirement to install multiple web setup projects (using VS2005 and ASP.Net/C#) into the same virtual folder. The projects share some assembly references (the file systems are all structured to use the same 'bin' folder), making deployment of changes to those assemblies problematic since the MS installer will only overwrite assemblies if the currently installed version is older than the one in the MSI.
我需要在同一个虚拟文件夹中安装多个Web安装项目(使用VS2005和ASP.Net/C#)。这些项目共享一些程序集引用(文件系统都被构造为使用相同的“bin”文件夹),这使得对这些程序集的更改部署成为问题,因为如果当前安装的版本早于版本中的版本,则MS安装程序将仅覆盖程序集。 MSI。
I'm not suggesting that the pessimistic installation scheme is wrong - only that it creates a problem in the environment I've been given to work with. Since there are a sizable number of common assemblies and a significant number of developers who might change a common assembly but forget to update its version number, trying to manage versioning manually will eventually lead to massive confusion at install time.
我并不是说悲观的安装方案是错误的 - 只是它在我给予的环境中产生了一个问题。由于有相当数量的通用程序集和大量开发人员可能会更改常见程序集但忘记更新其版本号,因此尝试手动管理版本控制最终会导致安装时出现大量混淆。
On the flip side of this issue, it's also important not to spontaneously update version numbers and replace all common assemblies with every install, since that could (temporarily at least) obscure cases where actual changes were made.
在这个问题的另一面,同样重要的是不要自发更新版本号并用每次安装替换所有通用程序集,因为这可能(暂时至少)模糊实际更改的情况。
That said, what I'm looking for is a means to update assembly version information (preferably using MSBuild) only in cases where the assembly constituents (code modules, resources etc) has/have actually changed.
也就是说,我正在寻找的是只有在程序集成分(代码模块,资源等)实际已经发生变化的情况下才更新程序集版本信息(最好使用MSBuild)的方法。
I've found a few references that are at least partially pertinent here (AssemblyInfo task on MSDN) and here (looks similar to what I need, but more than two years old and without a clear solution).
我在这里找到了一些至少部分相关的参考文献(MSDN上的AssemblyInfo任务)和这里(看起来类似于我需要的,但超过两年,没有明确的解决方案)。
My team also uses TFS version control, so an automated solution should probably include a means by which the AssebmlyInfo can be checked out/in during the build.
我的团队也使用TFS版本控制,因此自动化解决方案应该包括在构建期间可以检出/输入AssebmlyInfo的方法。
Any help would be much appreciated.
任何帮助将非常感激。
Thanks in advance.
提前致谢。
3 个解决方案
#1
10
I cannot answer all your questions, as I don't have experience with TFS.
我无法回答你的所有问题,因为我没有TFS的经验。
But I can recommend a better approach to use for updating your AssemblyInfo.cs files than using the AssemblyInfo task. That task appears to just recreate a standard AssemblyInfo file from scratch, and loses any custom portions you may have added.
但我建议使用更好的方法来更新AssemblyInfo.cs文件,而不是使用AssemblyInfo任务。该任务似乎只是从头开始重新创建标准AssemblyInfo文件,并丢失您可能添加的任何自定义部分。
For that reason, I suggest you look into the FileUpdate task, from the MSBuild Community Tasks project. It can look for specific content in a file and replace it, like this:
因此,我建议您从MSBuild社区任务项目中查看FileUpdate任务。它可以在文件中查找特定内容并替换它,如下所示:
<FileUpdate
Files="$(WebDir)\Properties\AssemblyInfo.cs"
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$(Major).$(ServicePack).$(Build).$(Revision)"
Condition="'$(Configuration)' == 'Release'"
/>
There are several ways you can control the incrementing of the build number. Because I only want the build number to increment if the build is completely successful, I use a 2-step method:
有几种方法可以控制内部版本号的增量。因为我只想在构建完全成功时增加构建号,所以我使用两步法:
- read a number from a text file (the only thing in the file is the number) and add 1 without changing the file;
- as a final step in the build process, if everything succeeded, save the incremented number back to the text file.
从文本文件中读取一个数字(文件中唯一的内容是数字)并在不更改文件的情况下添加1;
作为构建过程的最后一步,如果一切都成功,将增加的数字保存回文本文件。
There are tasks such as ReadLinesFromFile, that can help you with this, but I found it easiest to write a small custom task:
有一些任务,如ReadLinesFromFile,可以帮助你解决这个问题,但我发现编写一个小的自定义任务最简单:
using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace CredibleCustomBuildTasks
{
public class IncrementTask : Task
{
[Required]
public bool SaveChange { get; set; }
[Required]
public string IncrementFileName { get; set; }
[Output]
public int Increment { get; set; }
public override bool Execute()
{
if (File.Exists(IncrementFileName))
{
string lines = File.ReadAllText(IncrementFileName);
int result;
if(Int32.TryParse(lines, out result))
{
Increment = result + 1;
}
else
{
Log.LogError("Unable to parse integer in '{0}' (contents of {1})");
return false;
}
}
else
{
Increment = 1;
}
if (SaveChange)
{
File.Delete(IncrementFileName);
File.WriteAllText(IncrementFileName, Increment.ToString());
}
return true;
}
}
}
I use this before the FileUpdateTask to get the next build number:
我在FileUpdateTask之前使用它来获取下一个构建号:
<IncrementTask
IncrementFileName="$(BuildNumberFile)"
SaveChange="false">
<Output TaskParameter="Increment" PropertyName="Build" />
</IncrementTask>
and as my final step (before notifying others) in the build:
并且作为我在构建中的最后一步(在通知其他人之前):
<IncrementTask
IncrementFileName="$(BuildNumberFile)"
SaveChange="true"
Condition="'$(Configuration)' == 'Release'" />
Your other question of how to update the version number only when source code has changed is highly dependent on your how your build process interacts with your source control. Normally, checking in source file changes should initiate a Continuous Integration build. That is the one to use to update the relevant version number.
关于如何仅在源代码更改时更新版本号的另一个问题在很大程度上取决于构建过程与源代码控制的交互方式。通常,检入源文件更改应启动持续集成构建。这是用于更新相关版本号的那个。
#2
0
I have written one custome task you can refer the code below. It will create an utility to which you can pass assemblyinfo path Major,minor and build number. you can modify it to get revision number. Since in my case this task was done by developer i used to search it and again replace whole string.
我写了一个客户任务,你可以参考下面的代码。它将创建一个实用程序,您可以将assemblyinfo路径传递给Major,minor和build number。你可以修改它以获得修订号。因为在我的情况下,这个任务是由开发人员完成的,我用来搜索它并再次替换整个字符串。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace UpdateVersion
{
class SetVersion
{
static void Main(string[] args)
{
String FilePath = args[0];
String MajVersion=args[1];
String MinVersion = args[2];
String BuildNumber = args[3];
string RevisionNumber = null;
StreamReader Reader = File.OpenText(FilePath);
string contents = Reader.ReadToEnd();
Reader.Close();
MatchCollection match = Regex.Matches(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", RegexOptions.IgnoreCase);
if (match[0].Value != null)
{
string strRevisionNumber = match[0].Value;
RevisionNumber = strRevisionNumber.Substring(strRevisionNumber.LastIndexOf(".") + 1, (strRevisionNumber.LastIndexOf("\"")-1) - strRevisionNumber.LastIndexOf("."));
String replaceWithText = String.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]", MajVersion, MinVersion, BuildNumber, RevisionNumber);
string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replaceWithText);
StreamWriter writer = new StreamWriter(FilePath, false);
writer.Write(newText);
writer.Close();
}
else
{
Console.WriteLine("No matching values found");
}
}
}
}
#3
0
I hate to say this but it seems that you may be doing it wrongly. Is much easier if you do generate the assembly versions on the fly instead of trying to patch them.
我讨厌这样说,但似乎你错了。如果你动态生成汇编版本而不是试图修补它们会容易得多。
Take a look at https://sbarnea.com/articles/easy-windows-build-versioning/
看看https://sbarnea.com/articles/easy-windows-build-versioning/
Why I do think you are doing it wrong? * A build should not modify the version number * if you build the same changeset twice you should get the same build numbers * if you put build number inside what microsoft calls build number (proper naming would be PATCH level) you will eventually reach the 65535 limitation.
为什么我认为你做错了? *构建不应该修改版本号*如果您构建相同的变更集两次,您应该获得相同的构建号*如果您将构建号放在微软调用构建号内(正确命名将是PATCH级别),您最终将达到65535局限性。
#1
10
I cannot answer all your questions, as I don't have experience with TFS.
我无法回答你的所有问题,因为我没有TFS的经验。
But I can recommend a better approach to use for updating your AssemblyInfo.cs files than using the AssemblyInfo task. That task appears to just recreate a standard AssemblyInfo file from scratch, and loses any custom portions you may have added.
但我建议使用更好的方法来更新AssemblyInfo.cs文件,而不是使用AssemblyInfo任务。该任务似乎只是从头开始重新创建标准AssemblyInfo文件,并丢失您可能添加的任何自定义部分。
For that reason, I suggest you look into the FileUpdate task, from the MSBuild Community Tasks project. It can look for specific content in a file and replace it, like this:
因此,我建议您从MSBuild社区任务项目中查看FileUpdate任务。它可以在文件中查找特定内容并替换它,如下所示:
<FileUpdate
Files="$(WebDir)\Properties\AssemblyInfo.cs"
Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$(Major).$(ServicePack).$(Build).$(Revision)"
Condition="'$(Configuration)' == 'Release'"
/>
There are several ways you can control the incrementing of the build number. Because I only want the build number to increment if the build is completely successful, I use a 2-step method:
有几种方法可以控制内部版本号的增量。因为我只想在构建完全成功时增加构建号,所以我使用两步法:
- read a number from a text file (the only thing in the file is the number) and add 1 without changing the file;
- as a final step in the build process, if everything succeeded, save the incremented number back to the text file.
从文本文件中读取一个数字(文件中唯一的内容是数字)并在不更改文件的情况下添加1;
作为构建过程的最后一步,如果一切都成功,将增加的数字保存回文本文件。
There are tasks such as ReadLinesFromFile, that can help you with this, but I found it easiest to write a small custom task:
有一些任务,如ReadLinesFromFile,可以帮助你解决这个问题,但我发现编写一个小的自定义任务最简单:
using System;
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace CredibleCustomBuildTasks
{
public class IncrementTask : Task
{
[Required]
public bool SaveChange { get; set; }
[Required]
public string IncrementFileName { get; set; }
[Output]
public int Increment { get; set; }
public override bool Execute()
{
if (File.Exists(IncrementFileName))
{
string lines = File.ReadAllText(IncrementFileName);
int result;
if(Int32.TryParse(lines, out result))
{
Increment = result + 1;
}
else
{
Log.LogError("Unable to parse integer in '{0}' (contents of {1})");
return false;
}
}
else
{
Increment = 1;
}
if (SaveChange)
{
File.Delete(IncrementFileName);
File.WriteAllText(IncrementFileName, Increment.ToString());
}
return true;
}
}
}
I use this before the FileUpdateTask to get the next build number:
我在FileUpdateTask之前使用它来获取下一个构建号:
<IncrementTask
IncrementFileName="$(BuildNumberFile)"
SaveChange="false">
<Output TaskParameter="Increment" PropertyName="Build" />
</IncrementTask>
and as my final step (before notifying others) in the build:
并且作为我在构建中的最后一步(在通知其他人之前):
<IncrementTask
IncrementFileName="$(BuildNumberFile)"
SaveChange="true"
Condition="'$(Configuration)' == 'Release'" />
Your other question of how to update the version number only when source code has changed is highly dependent on your how your build process interacts with your source control. Normally, checking in source file changes should initiate a Continuous Integration build. That is the one to use to update the relevant version number.
关于如何仅在源代码更改时更新版本号的另一个问题在很大程度上取决于构建过程与源代码控制的交互方式。通常,检入源文件更改应启动持续集成构建。这是用于更新相关版本号的那个。
#2
0
I have written one custome task you can refer the code below. It will create an utility to which you can pass assemblyinfo path Major,minor and build number. you can modify it to get revision number. Since in my case this task was done by developer i used to search it and again replace whole string.
我写了一个客户任务,你可以参考下面的代码。它将创建一个实用程序,您可以将assemblyinfo路径传递给Major,minor和build number。你可以修改它以获得修订号。因为在我的情况下,这个任务是由开发人员完成的,我用来搜索它并再次替换整个字符串。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace UpdateVersion
{
class SetVersion
{
static void Main(string[] args)
{
String FilePath = args[0];
String MajVersion=args[1];
String MinVersion = args[2];
String BuildNumber = args[3];
string RevisionNumber = null;
StreamReader Reader = File.OpenText(FilePath);
string contents = Reader.ReadToEnd();
Reader.Close();
MatchCollection match = Regex.Matches(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", RegexOptions.IgnoreCase);
if (match[0].Value != null)
{
string strRevisionNumber = match[0].Value;
RevisionNumber = strRevisionNumber.Substring(strRevisionNumber.LastIndexOf(".") + 1, (strRevisionNumber.LastIndexOf("\"")-1) - strRevisionNumber.LastIndexOf("."));
String replaceWithText = String.Format("[assembly: AssemblyVersion(\"{0}.{1}.{2}.{3}\")]", MajVersion, MinVersion, BuildNumber, RevisionNumber);
string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replaceWithText);
StreamWriter writer = new StreamWriter(FilePath, false);
writer.Write(newText);
writer.Close();
}
else
{
Console.WriteLine("No matching values found");
}
}
}
}
#3
0
I hate to say this but it seems that you may be doing it wrongly. Is much easier if you do generate the assembly versions on the fly instead of trying to patch them.
我讨厌这样说,但似乎你错了。如果你动态生成汇编版本而不是试图修补它们会容易得多。
Take a look at https://sbarnea.com/articles/easy-windows-build-versioning/
看看https://sbarnea.com/articles/easy-windows-build-versioning/
Why I do think you are doing it wrong? * A build should not modify the version number * if you build the same changeset twice you should get the same build numbers * if you put build number inside what microsoft calls build number (proper naming would be PATCH level) you will eventually reach the 65535 limitation.
为什么我认为你做错了? *构建不应该修改版本号*如果您构建相同的变更集两次,您应该获得相同的构建号*如果您将构建号放在微软调用构建号内(正确命名将是PATCH级别),您最终将达到65535局限性。