Created
October 18, 2022 17:35
-
-
Save DamianEdwards/deaec4fa1ef6bf5ad3caa0cc685827d6 to your computer and use it in GitHub Desktop.
Example of .NET console app (that could be made into a cmd line tool) that uses MSBuild to extract project version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Put this in sub-directory of the project named 'assets' --> | |
<Project> | |
<Target Name="_ExtractVersionMetadata"> | |
<WriteLinesToFile File="$(_ProjectVersionMetadataFile)" Lines="$(Version)" /> | |
</Target> | |
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net7.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
<VersionPrefix>1.2.0</VersionPrefix> | |
</PropertyGroup> | |
<ItemGroup> | |
<None Update="assets\GetProjectVersion.targets"> | |
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |
</None> | |
</ItemGroup> | |
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Diagnostics; | |
string? projectFilePath = null; | |
if (args.Length > 0) | |
{ | |
projectFilePath = args[0]; | |
if (!File.Exists(projectFilePath)) | |
{ | |
WriteError($"The specified project file '{projectFilePath}' was not found."); | |
Environment.Exit(1); | |
} | |
} | |
else | |
{ | |
var projectFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj"); | |
if (projectFiles.Length == 1) | |
{ | |
projectFilePath = projectFiles[0]; | |
} | |
else if (projectFiles.Length > 1) | |
{ | |
WriteError("More than one .csproj file found. Please specify a project file, e.g.: dotnet version MyProjectFile.csproj"); | |
Environment.Exit(1); | |
} | |
else | |
{ | |
WriteError("No project file found. Please run this command in the project directory or specify a project file, e.g.: dotnet version MyProjectFile.csproj"); | |
Environment.Exit(1); | |
} | |
} | |
var configuration = "Debug"; | |
var targetsFile = FindTargetsFile(); | |
if (targetsFile is null) | |
{ | |
Environment.Exit(1); | |
} | |
var outputFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); | |
try | |
{ | |
var psi = new ProcessStartInfo | |
{ | |
FileName = "dotnet.exe", | |
RedirectStandardOutput = true, | |
RedirectStandardError = true, | |
UseShellExecute = false, | |
ArgumentList = | |
{ | |
"msbuild", | |
projectFilePath, | |
"/nologo", | |
"/t:_ExtractVersionMetadata", // defined in GetProjectVersion.targets | |
"/p:_ProjectVersionMetadataFile=" + outputFile, | |
"/p:Configuration=" + configuration, | |
"/p:CustomAfterMicrosoftCommonTargets=" + targetsFile, | |
"/p:CustomAfterMicrosoftCommonCrossTargetingTargets=" + targetsFile, | |
"-verbosity:detailed", | |
} | |
}; | |
using var process = new Process() | |
{ | |
StartInfo = psi, | |
}; | |
process.Start(); | |
process.BeginOutputReadLine(); | |
process.BeginErrorReadLine(); | |
process.WaitForExit(); | |
if (process.ExitCode != 0) | |
{ | |
WriteError($"Exit code: {process.ExitCode}"); | |
} | |
if (!File.Exists(outputFile)) | |
{ | |
WriteError("Output file not found"); | |
Environment.Exit(1); | |
} | |
var version = File.ReadAllText(outputFile)?.Trim(); | |
if (string.IsNullOrEmpty(version)) | |
{ | |
WriteError("Output file was empty"); | |
} | |
Console.WriteLine($"Project version: {version}"); | |
} | |
catch (Exception ex) | |
{ | |
WriteError(ex.ToString()); | |
Environment.Exit(1); | |
} | |
void WriteError(string value) | |
{ | |
WriteLine(value, ConsoleColor.Red); | |
} | |
void WriteLine(string value, ConsoleColor color) | |
{ | |
Write(value, color); | |
Console.WriteLine(); | |
} | |
void Write(string value, ConsoleColor color) | |
{ | |
var originalForegroundColor = Console.ForegroundColor; | |
Console.ForegroundColor = color; | |
Console.Write(value); | |
Console.ForegroundColor = originalForegroundColor; | |
} | |
string? FindTargetsFile() | |
{ | |
var assemblyDir = Path.GetDirectoryName(typeof(Program).Assembly.Location); | |
var searchPaths = new[] | |
{ | |
Path.Combine(AppContext.BaseDirectory, "assets"), | |
Path.Combine(assemblyDir, "assets"), | |
AppContext.BaseDirectory, | |
assemblyDir, | |
}; | |
var targetPath = searchPaths.Select(p => Path.Combine(p, "GetProjectVersion.targets")).FirstOrDefault(File.Exists); | |
if (targetPath == null) | |
{ | |
WriteError("Fatal error: could not find GetProjectVersion.targets"); | |
return null; | |
} | |
return targetPath; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment