결국 빌드 서버가 어셈블리를 자동 버전하는 작업에 대한 다른 솔루션을 만들었습니다. T4를 사용하여 솔루션 내의 다른 프로젝트에 대한 항목 링크를 통해 공유 할 AssemblyInfo.cs 파일을 동적으로 생성하는 대신,이 목적을 위해 파일의 재생을 최신 상태로 유지하는 방법을 알아내는 성가심을 처리해야합니다. T4를 완전히 피했습니다. T4 조작 등을 허용하는 Addons 및 SDK를 관리하는 타사 원격 빌드 머신과 통합하는 작업이 너무 많았습니다. MSBuild 커뮤니티 작업 내가 찾은 것 이렇게 질문. 솔루션은 T4에 비해 우아하게 간단합니다! 흔들리는 방법은 다음과 같습니다.
이 프로젝트마다 Application.versioning.csproj가 구축 될 때마다 3 자, Nuget Installed 'MSBuildCommunity Tasks'라이브러리에 정의 된 MSBuild 작업이 동적으로 생성됩니다. AssemblyFileVersion, AssemblyInformationalVersion, 조립 전환 현재 UTC 날짜 시간을 기준 으로이 프로젝트의 'Properties'디렉토리 (AssemblyInfo.cs 파일과 함께)에 상주하는 새 파일 인 Autoversion.cs에 입력합니다. AssemblyInfo.cs에는 곱하기 정의 된 어셈블리 속성의 빌드 오류를 피하기 위해 이러한 어셈블리 속성이 영원히 고정되어 있습니다). Autoversion.cs의 생성 후 (빌드 직전에 발생), 컴파일러는 위에서 언급 한 어셈블리 버전화 속성을 빌드 어셈블리에 통합합니다. 이 버전 작성은 그들이 구축 된 UTC 시간을 반영합니다 (아래 참조).
.sln의 다른 .csproj는 생성 된 자동화 된 autoversion.cs 파일에 대한 파일 링크를 작성하는이 동적 빌드 타임 어셈블리 버전을 구독합니다. 이 어셈블리에는 또한 어셈블리 인포 (AssemblyInfo.cs) 가지가 잘 어울려야합니다. .sln에서 모든 가입 .csprojs에 대한 어셈블리 버전은 myApplication.versioning.csproj가 구축 (또는 재건) 될 때마다 수행됩니다. 버전 관리 프로젝트의 .csproj는 다음과 같습니다.
<!-- START DYNAMIC ASSEMBLY VERSIONING WORK-->
<!--MSBuild Community Tasks path as installed via the nuget package 'Install-Package MSBuildTasks'-->
<PropertyGroup>
<MSBuildCommunityTasksPath>$(MSBuildThisFileDirectory)..\.build</MSBuildCommunityTasksPath>
<My-PropertiesDir>Properties</My-PropertiesDir>
</PropertyGroup>
<PropertyGroup>
<!--this should only be incremented (starting at zero) for MAJOR application releases this should never be reset only incremented!-->
<ManualMajorVersion>0</ManualMajorVersion>
<!--3 digits maximum should only be manually incremented (starting at zero) for feature releases-->
<!--!this should be reset to '0' at the start of each caldenar Year-->
<ManualMinorVersion>0</ManualMinorVersion>
</PropertyGroup>
<!--Import MSBuild Community Tasks library installed from Nuget -->
<!--This library contains defined MSBUILD tasks useful for dynamically generating Assembly information via MSBUILD https://github.com/loresoft/msbuildtasks-->
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" />
<Target Name="BeforeBuild">
<Time Format="yy.MM.dd.HHmm" Kind="Utc">
<Output TaskParameter="FormattedTime" PropertyName="My-VersionNumber" />
</Time>
<Message Text="Auto versioning from UTC time: $(My-VersionNumber) ...">
</Message>
<Time Format="yy" Kind="Utc">
<Output TaskParameter="FormattedTime" PropertyName="Year" />
</Time>
<Time Format="MM" Kind="Utc">
<Output TaskParameter="FormattedTime" PropertyName="Month" />
</Time>
<Time Format="dd" Kind="Utc">
<Output TaskParameter="FormattedTime" PropertyName="Day" />
</Time>
<Time Format="HH" Kind="Utc">
<Output TaskParameter="FormattedTime" PropertyName="Hour" />
</Time>
<Time Format="mm" Kind="Utc">
<Output TaskParameter="FormattedTime" PropertyName="Minute" />
</Time>
<ItemGroup>
<My-AssemblyInfo Include="$(My-PropertiesDir)\AutoVersion.cs" />
<Compile Include="@(My-AssemblyInfo)" />
</ItemGroup>
<MakeDir Directories="$(My-PropertiesDir)" />
<PropertyGroup>
<GeneratedAssemblyVersion>$(ManualMajorVersion).$(Year)$(ManualMinorVersion).$(Month)$(Day).$(Hour)$(Minute)</GeneratedAssemblyVersion>
</PropertyGroup>
<AssemblyInfo OutputFile="@(My-AssemblyInfo)" CodeLanguage="CS" AssemblyFileVersion="$(GeneratedAssemblyVersion)" AssemblyInformationalVersion="$(GeneratedAssemblyVersion)" AssemblyVersion="$(GeneratedAssemblyVersion)" Condition="$(GeneratedAssemblyVersion) != '' " />
</Target>
<!-- END DYNAMIC ASSEMBLY VERSIONING WORK-->
직접 확인하기위한 단위 테스트뿐만 아니라 :
/// <summary> A test to validate the configured, auto-generated assembly versioning is working as expected </summary>
[Test]
public void AssemblyVersioningTest()
{
DirectoryInfo currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
DirectoryInfo versioningDir = new DirectoryInfo(currentDirectory.FullName + "\\" + VERSIONING_DYNAMIC_FILE_DIRECTORY);
// verify versioning directory located/loaded/exists
Assert.IsTrue(versioningDir.Exists);
// locate the VERSIONING_DYNAMIC_FILE file within the VERSIONING_DYNAMIC_FILE_DIRECTORY directory
string dynamicFilePath = versioningDir.FullName + "\\" + VERSIONING_DYNAMIC_FILE;
// get the FileInfo for the file that is used to dynamically generate assembly versioning
FileInfo dynamicVersioningFileInfo = new FileInfo(dynamicFilePath);
Assert.IsTrue(dynamicVersioningFileInfo.Exists);
// get the two digit creation Dates/Times for the assembly's file as strings
// since that's what the versioning reflects
DateTime dynamicVersioningFileLastWriteTime = dynamicVersioningFileInfo.LastWriteTime;
#region Created VERSIONING_DYNAMIC_FILE
string dynamicVersioningFileLastWriteTimeYear = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("yy");
string dynamicVersioningFileLastWriteTimeMonth = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("MM");
string dynamicVersioningFileLastWriteTimeDay = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("dd");
string dynamicVersioningFileLastWriteTimeHour = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("HH");
string dynamicVersioningFileLastWriteTimeMinute = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("mm");
#endregion Created VERSIONING_DYNAMIC_FILE
// get *this* assembly from the .sln using reflection since this assembly consumes/is dependent upon the versioning functionality we
// are testing
Assembly theAssemblyExecutingThisTest = Assembly.GetExecutingAssembly();
// get this assembly's version
// we will investigate this to compare it to a reverse-engineering of what we would
// expect it to be based
AssemblyName testingAssemblyName = theAssemblyExecutingThisTest.GetName();
Version testingAssemblyVersion = testingAssemblyName.Version;
#region Generated Assembly Versioning
// get the first two digits of the assemblyVersion.MinorVersion - these represent the year
string testingAssemblyVersionMinorYear = testingAssemblyVersion.Minor.ToString().Substring(0, 2);
// the rest of the digits represent the manually-configured version and can be 1-3 chars long
string testingAssemblyVersionMinorManual = GetMinorManualFromVersionString(testingAssemblyVersion.Minor.ToString());
string testingAssemblyVersionBuildMonth = testingAssemblyVersion.Build.ToString("D4").Substring(0, 2);
string testingAssemblyVersionBuildDay = testingAssemblyVersion.Build.ToString("D4").Substring(2, 2);
string testingAssemblyVersionRevisionHour = testingAssemblyVersion.Revision.ToString("D4").Substring(0, 2);
string testingAssemblyVersionRevisionMinute = testingAssemblyVersion.Revision.ToString("D4").Substring(2, 2);
#endregion Generated Assembly Versioning
// verify the assembly's minor version: last two digits match of assembly file creation year
// (pad minorversion 4 spaces in case released minor version is empty)
Assert.AreEqual(dynamicVersioningFileLastWriteTimeYear,
testingAssemblyVersionMinorYear,
"Assembly's minor version: last two digits do not match assembly file last write time year");
// verify the assembly's minor version is comprised of two digit 'released minor version' + two digit year of assembly file creation date
Assert.AreEqual(dynamicVersioningFileLastWriteTimeYear + testingAssemblyVersionMinorManual,
testingAssemblyVersionMinorYear + testingAssemblyVersionMinorManual,
"Assembly's minor version: not comprised of two digit year of assembly file last write time date + dynamically-sized 'minor manual version' + ");
// verify the Assembly's build version is comprised of two digit month + two digit day of assembly file creation date
Assert.AreEqual(dynamicVersioningFileLastWriteTimeMonth + dynamicVersioningFileLastWriteTimeDay,
testingAssemblyVersionBuildMonth + testingAssemblyVersionBuildDay,
"Assembly's build version: not comprised of two digit month + two digit day of assembly file last write time date");
// verify the Assembly's revision version is comprised two digit hour + two digit minute of assembly file creation date
Assert.AreEqual(dynamicVersioningFileLastWriteTimeHour + dynamicVersioningFileLastWriteTimeMinute,
testingAssemblyVersionRevisionHour + testingAssemblyVersionRevisionMinute,
"Assembly's revision version: comprised two digit hour + two digit minute of assembly file last write time date");
}