现在,我正在编写VS 2008宏来替换AssemblyInfo.cs文件中的Assembly版本。从MSDN,必须使用以下模式编写程序集版本。
MAJOR.MINOR [.build [.revision]]
示例
我需要为'AssemblyInfo.cs'文件动态生成内部版本号,并使用正则表达式将旧版本号替换为新生成的内部版本号。
你有任何正则表达式来解决这个问题吗?此外,构建号不得包含在注释语句中,如下面的代码。最后,不要忘记查看正则表达式的内联注释。
请勿替换任何已评论的内部版本号
//[assembly: AssemblyVersion("0.1.0.0")]
/*[assembly: AssemblyVersion("0.1.0.0")]*/
/*
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("0.1.0.0")]
*/
替换未注释的内部版本号
[assembly: AssemblyVersion("0.1.0.0")] // inline comment
/* inline comment */ [assembly: AssemblyVersion("0.1.0.0")]
[assembly: /*inline comment*/AssemblyVersion("0.1.0.0")]
提示。
尝试你的正则表达式答案 0 :(得分:3)
这有些粗糙,但您可以执行以下操作。
搜索:
^{\[assembly\: :w\(\"0\.1\.}\*
替换为:
\1####
其中####是您的替换字符串。
这个正则表达式的工作原理如下:
注释行被忽略,因为它们不以[assembly:。后续的内嵌注释保持不变,因为它们未被正则表达式捕获。
如果这不是您所需要的,那么试验正则表达式以捕获和/或替换该行的不同部分是相当简单的。
答案 1 :(得分:0)
我怀疑使用正则表达式会对你有好处。虽然可以制定一个与“未注释”的汇编版本属性相匹配的表达式,但它很难维护和理解。
您使用您提供的语法对自己非常努力。如何在AssemblyInfo.cs文件中强制执行编码标准,该文件应始终使用开头//并禁止内联注释注释掉行?然后,使用StreamReader解析它应该很容易。
如果你不能这样做,那么只有一个解析器可以保证处理所有边缘情况,那就是C#编译器。如何编译程序集然后反映它以检测版本号?
var asm = Assembly.LoadFile("foo.dll");
var version = Assembly.GetExecutingAssembly().GetName().Version;
如果您只是想增加内置编号,那么您应该看一下这个问题:Can I automatically increment the file build version when using Visual Studio?
答案 2 :(得分:0)
我只是找到了我的问题的答案。但答案非常复杂。很长的正则表达式。顺便说一句,我每个解决方案只使用这种语法一次。因此,它不会影响整体性能。请查看我的完整源代码。
模块EnvironmentEvents.vb
Public Module EnvironmentEvents
Private Sub BuildEvents_OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, ByVal Action As EnvDTE.vsBuildAction) Handles BuildEvents.OnBuildBegin
If DTE.Solution.FullName.EndsWith(Path.DirectorySeparatorChar & "[Solution File Name]") Then
If Scope = vsBuildScope.vsBuildScopeSolution And Action = vsBuildAction.vsBuildActionRebuildAll Then
AutoGenerateBuildNumber()
End If
End If
End Sub
End Module
模块AssemblyInfoHelp.vb
Public Module AssemblyInfoHelper
ReadOnly AssemblyInfoPath As String = Path.Combine("Common", "GlobalAssemblyInfo.cs")
Sub AutoGenerateBuildNumber()
'Declear required variables
Dim solutionPath As String = Path.GetDirectoryName(DTE.Solution.Properties.Item("Path").Value)
Dim globalAssemblyPath As String = Path.Combine(solutionPath, AssemblyInfoPath)
Dim globalAssemblyContent As String = ReadFileContent(globalAssemblyPath)
Dim rVersionAttribute As Regex = New Regex("\[[\s]*(\/\*[\s\S]*?\*\/)?[\s]*assembly[\s]*(\/\*[\s\S]*?\*\/)?[\s]*:[\s]*(\/\*[\s\S]*?\*\/)?[\s]*AssemblyVersion[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\([\s]*(\/\*[\s\S]*?\*\/)?[\s]*\""([0-9]+)\.([0-9]+)(.([0-9]+))?(.([0-9]+))?\""[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\)[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\]")
Dim rVersionInfoAttribute As Regex = New Regex("\[[\s]*(\/\*[\s\S]*?\*\/)?[\s]*assembly[\s]*(\/\*[\s\S]*?\*\/)?[\s]*:[\s]*(\/\*[\s\S]*?\*\/)?[\s]*AssemblyInformationalVersion[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\([\s]*(\/\*[\s\S]*?\*\/)?[\s]*\""([0-9]+)\.([0-9]+)(.([0-9]+))?[\s]*([^\s]*)[\s]*(\([\s]*Build[\s]*([0-9]+)[\s]*\))?\""[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\)[\s]*(\/\*[\s\S]*?\*\/)?[\s]*\]")
'Find Version Attribute for Updating Build Number
Dim mVersionAttributes As MatchCollection = rVersionAttribute.Matches(globalAssemblyContent)
Dim mVersionAttribute As Match = GetFirstUnCommentedMatch(mVersionAttributes, globalAssemblyContent)
Dim gBuildNumber As Group = mVersionAttribute.Groups(9)
Dim newBuildNumber As String
'Replace Version Attribute for Updating Build Number
If (gBuildNumber.Success) Then
newBuildNumber = GenerateBuildNumber(gBuildNumber.Value)
globalAssemblyContent = globalAssemblyContent.Substring(0, gBuildNumber.Index) + newBuildNumber + globalAssemblyContent.Substring(gBuildNumber.Index + gBuildNumber.Length)
End If
'Find Version Info Attribute for Updating Build Number
Dim mVersionInfoAttributes As MatchCollection = rVersionInfoAttribute.Matches(globalAssemblyContent)
Dim mVersionInfoAttribute As Match = GetFirstUnCommentedMatch(mVersionInfoAttributes, globalAssemblyContent)
Dim gBuildNumber2 As Group = mVersionInfoAttribute.Groups(12)
'Replace Version Info Attribute for Updating Build Number
If (gBuildNumber2.Success) Then
If String.IsNullOrEmpty(newBuildNumber) Then
newBuildNumber = GenerateBuildNumber(gBuildNumber2.Value)
End If
globalAssemblyContent = globalAssemblyContent.Substring(0, gBuildNumber2.Index) + newBuildNumber + globalAssemblyContent.Substring(gBuildNumber2.Index + gBuildNumber2.Length)
End If
WriteFileContent(globalAssemblyPath, globalAssemblyContent)
End Sub
Function GenerateBuildNumber(Optional ByVal oldBuildNumber As String = "0") As String
oldBuildNumber = Int16.Parse(oldBuildNumber) + 1
Return oldBuildNumber
End Function
Private Function GetFirstUnCommentedMatch(ByRef mc As MatchCollection, ByVal content As String) As Match
Dim rSingleLineComment As Regex = New Regex("\/\/.*$")
Dim rMultiLineComment As Regex = New Regex("\/\*[\s\S]*?\*\/")
Dim mSingleLineComments As MatchCollection = rSingleLineComment.Matches(content)
Dim mMultiLineComments As MatchCollection = rMultiLineComment.Matches(content)
For Each m As Match In mc
If m.Success Then
For Each singleLine As Match In mSingleLineComments
If singleLine.Success Then
If m.Index >= singleLine.Index And m.Index + m.Length <= singleLine.Index + singleLine.Length Then
GoTo NextAttribute
End If
End If
Next
For Each multiLine As Match In mMultiLineComments
If multiLine.Success Then
If m.Index >= multiLine.Index And m.Index + m.Length <= multiLine.Index + multiLine.Length Then
GoTo NextAttribute
End If
End If
Next
Return m
End If
NextAttribute:
Next
Return Nothing
End Function
End Module
谢谢大家
PS。特别感谢[RegExr:在线正则表达式测试工具] [1]。我曾经玩过的最好的在线正则表达式工具。 [1]:http://gskinner.com/RegExr/
答案 3 :(得分:0)
通过下载并安装MS Build Extension Pack并在.csproj文件的顶部添加以下行,您可以更轻松地实现同样的效果:
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.VersionNumber.targets"/>
这将自动使用当前日期(MMdd)作为内部版本号,并为您增加修订号。现在,要覆盖次要版本和主要版本(默认设置为1.0),只需在.csproj文件中的任何位置添加以下内容:
<PropertyGroup>
<AssemblyMajorVersion>2</AssemblyMajorVersion>
<AssemblyFileMajorVersion>1</AssemblyFileMajorVersion>
</PropertyGroup>
您可以通过为属性列表设置其他属性see this page来进一步自定义构建号和修订版的生成方式,甚至可以设置公司,版权等。