Skip to content

Commit

Permalink
Create generic function
Browse files Browse the repository at this point in the history
  • Loading branch information
gcbeattyAWS committed Nov 19, 2024
1 parent 6f1429b commit cb68604
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 150 deletions.
183 changes: 82 additions & 101 deletions src/Amazon.Common.DotNetCli.Tools/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,23 @@ public static string DeterminePublishLocation(string workingDirectory, string pr
return path;
}

public static string LookupTargetFrameworkFromProjectFile(string projectLocation)

// <summary>
/// Looks up specified properties from a project file.
/// </summary>
/// <param name="projectLocation">The location of the project file.</param>
/// <param name="propertyNames">The names of the properties to look up.</param>
/// <returns>A dictionary of property names and their values.</returns>
public static Dictionary<string, string> LookupProjectProperties(string projectLocation, params string[] propertyNames)
{
var projectFile = FindProjectFileInDirectory(projectLocation);
if (string.IsNullOrEmpty(projectFile))
{
throw new FileNotFoundException("Could not find a project file in the specified directory.");
}

var arguments = new[]
var properties = new Dictionary<string, string>();
var arguments = new List<string>
{
"msbuild",
projectFile,
"--getProperty:TargetFramework,TargetFrameworks",
"-nologo"
"-nologo",
$"--getProperty:{string.Join(',', propertyNames)}"
};

var process = new Process
Expand All @@ -234,105 +237,94 @@ public static string LookupTargetFrameworkFromProjectFile(string projectLocation
CreateNoWindow = true
}
};

process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();

if (process.ExitCode != 0)
{
throw new Exception($"MSBuild process exited with code {process.ExitCode}. Error: {error}");
}

try
{
using JsonDocument doc = JsonDocument.Parse(output);
JsonElement root = doc.RootElement;
JsonElement properties = root.GetProperty("Properties");
process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();

if (properties.TryGetProperty("TargetFramework", out JsonElement targetFramework))
if (process.ExitCode == 0)
{
string framework = targetFramework.GetString();
if (!string.IsNullOrEmpty(framework))
using JsonDocument doc = JsonDocument.Parse(output);
JsonElement root = doc.RootElement;
JsonElement propertiesElement = root.GetProperty("Properties");

foreach (var property in propertyNames)
{
return framework;
if (propertiesElement.TryGetProperty(property, out JsonElement propertyValue))
{
properties[property] = propertyValue.GetString();
}
}
}

if (properties.TryGetProperty("TargetFrameworks", out JsonElement targetFrameworks))
else
{
string frameworks = targetFrameworks.GetString();
if (!string.IsNullOrEmpty(frameworks))
{
return frameworks.Split(';')[0];
}
Console.WriteLine($"MSBuild process exited with code {process.ExitCode}. Error: {error}");
// Fallback to XML parsing
properties = LookupProjectPropertiesFromXml(projectFile, propertyNames);
}
}
catch (JsonException ex)
catch (Exception ex)
{
throw new Exception($"Failed to parse MSBuild output: {ex.Message}. Output: {output}");
Console.WriteLine($"Error executing MSBuild or parsing output: {ex.Message}");
// Fallback to XML parsing
properties = LookupProjectPropertiesFromXml(projectFile, propertyNames);
}

return null;
return properties;
}

/// <summary>
/// Retrieve the `OutputType` property of a given project
/// </summary>
/// <param name="projectLocation">Path of the project</param>
/// <returns>The value of the `OutputType` property</returns>
public static string LookupOutputTypeFromProjectFile(string projectLocation)
private static Dictionary<string, string> LookupProjectPropertiesFromXml(string projectFile, string[] propertyNames)
{
var process = new Process();
var output = string.Empty;
var msbuildProcessFailed = false;
var properties = new Dictionary<string, string>();
try
{
process.StartInfo = new ProcessStartInfo()
{
FileName = "dotnet",
Arguments = $"msbuild {projectLocation} -getProperty:OutputType",
RedirectStandardOutput = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
};

process.Start();
output = process.StandardOutput.ReadToEnd();
var hasExited = process.WaitForExit(5000);

// If it hasn't completed in the specified timeout, stop the process and give up
if (!hasExited)
{
process.Kill();
msbuildProcessFailed = true;
}

// If it has completed but unsuccessfully, give up
if (process.ExitCode != 0)
var xdoc = XDocument.Load(projectFile);
foreach (var propertyName in propertyNames)
{
msbuildProcessFailed = true;
var element = xdoc.XPathSelectElement($"//PropertyGroup/{propertyName}");
if (element != null && !string.IsNullOrWhiteSpace(element.Value))
{
properties[propertyName] = element.Value;
}
}
}
catch (Exception)
catch (Exception ex)
{
// swallow any exceptions related to `dotnet msbuild`
msbuildProcessFailed = true;
Console.WriteLine($"Error parsing project file XML: {ex.Message}");
}
return properties;
}

if (msbuildProcessFailed)
/// <summary>
/// Looks up the target framework from a project file.
/// </summary>
/// <param name="projectLocation">The location of the project file.</param>
/// <returns>The target framework of the project.</returns>
public static string LookupTargetFrameworkFromProjectFile(string projectLocation)
{
var properties = LookupProjectProperties(projectLocation, "TargetFramework", "TargetFrameworks");
if (properties.TryGetValue("TargetFramework", out var targetFramework) && !string.IsNullOrEmpty(targetFramework))
{
var projectFile = FindProjectFileInDirectory(projectLocation);
var xdoc = XDocument.Load(projectFile);
var element = xdoc.XPathSelectElement("//PropertyGroup/OutputType");
output = element?.Value;
return targetFramework;
}
if (properties.TryGetValue("TargetFrameworks", out var targetFrameworks) && !string.IsNullOrEmpty(targetFrameworks))
{
return targetFrameworks.Split(';')[0];
}
return null;
}

return
string.IsNullOrEmpty(output) ?
null :
output.Trim();
/// <summary>
/// Retrieve the `OutputType` property of a given project
/// </summary>
/// <param name="projectLocation">Path of the project</param>
/// <returns>The value of the `OutputType` property</returns>
public static string LookupOutputTypeFromProjectFile(string projectLocation)
{
var properties = LookupProjectProperties(projectLocation, "OutputType");
return properties.TryGetValue("OutputType", out var outputType) ? outputType.Trim() : null;
}

public static bool LookPublishAotFlag(string projectLocation, string msBuildParameters)
Expand All @@ -350,43 +342,32 @@ public static bool LookPublishAotFlag(string projectLocation, string msBuildPara
}
}

// If the property wasn't provided in msBuildParameters, fall back to searching project file
var projectFile = FindProjectFileInDirectory(projectLocation);

var xdoc = XDocument.Load(projectFile);

var element = xdoc.XPathSelectElement("//PropertyGroup/PublishAot");

if (bool.TryParse(element?.Value, out bool result))
var properties = LookupProjectProperties(projectLocation, "PublishAot");
if (properties.TryGetValue("PublishAot", out var publishAot))
{
return result;
return bool.TryParse(publishAot, out var result) && result;
}

return false;
}


public static bool HasExplicitSelfContainedFlag(string projectLocation, string msBuildParameters)
{
if (msBuildParameters != null && msBuildParameters.IndexOf("--self-contained", StringComparison.InvariantCultureIgnoreCase) != -1)
{
return true;
}

// If the property wasn't provided in msBuildParameters, fall back to searching project file
var projectFile = FindProjectFileInDirectory(projectLocation);

var xdoc = XDocument.Load(projectFile);

var element = xdoc.XPathSelectElement("//PropertyGroup/SelfContained");

if (bool.TryParse(element?.Value, out _))
var properties = LookupProjectProperties(projectLocation, "SelfContained");
if (properties.TryGetValue("SelfContained", out var selfContained))
{
return true;
return bool.TryParse(selfContained, out _);
}

return false;
}

public static string FindProjectFileInDirectory(string directory)
private static string FindProjectFileInDirectory(string directory)
{
if (File.Exists(directory))
return directory;
Expand Down
49 changes: 0 additions & 49 deletions testapps/TestFunctionBuildProps/TestFunctionBuildProps/Readme.md

This file was deleted.

0 comments on commit cb68604

Please sign in to comment.