mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Make default executable name resolution smarter
This commit is contained in:
@@ -6,6 +6,7 @@ using System.Reflection;
|
|||||||
using CliFx.Attributes;
|
using CliFx.Attributes;
|
||||||
using CliFx.Infrastructure;
|
using CliFx.Infrastructure;
|
||||||
using CliFx.Schema;
|
using CliFx.Schema;
|
||||||
|
using CliFx.Utils;
|
||||||
using CliFx.Utils.Extensions;
|
using CliFx.Utils.Extensions;
|
||||||
|
|
||||||
namespace CliFx;
|
namespace CliFx;
|
||||||
@@ -21,7 +22,7 @@ public partial class CliApplicationBuilder
|
|||||||
private bool _isPreviewModeAllowed = true;
|
private bool _isPreviewModeAllowed = true;
|
||||||
private string? _title;
|
private string? _title;
|
||||||
private string? _executableName;
|
private string? _executableName;
|
||||||
private string? _versionText;
|
private string? _version;
|
||||||
private string? _description;
|
private string? _description;
|
||||||
private IConsole? _console;
|
private IConsole? _console;
|
||||||
private ITypeActivator? _typeActivator;
|
private ITypeActivator? _typeActivator;
|
||||||
@@ -144,7 +145,7 @@ public partial class CliApplicationBuilder
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public CliApplicationBuilder SetVersion(string version)
|
public CliApplicationBuilder SetVersion(string version)
|
||||||
{
|
{
|
||||||
_versionText = version;
|
_version = version;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +190,7 @@ public partial class CliApplicationBuilder
|
|||||||
var metadata = new ApplicationMetadata(
|
var metadata = new ApplicationMetadata(
|
||||||
_title ?? GetDefaultTitle(),
|
_title ?? GetDefaultTitle(),
|
||||||
_executableName ?? GetDefaultExecutableName(),
|
_executableName ?? GetDefaultExecutableName(),
|
||||||
_versionText ?? GetDefaultVersionText(),
|
_version ?? GetDefaultVersionText(),
|
||||||
_description
|
_description
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -210,14 +211,9 @@ public partial class CliApplicationBuilder
|
|||||||
|
|
||||||
public partial class CliApplicationBuilder
|
public partial class CliApplicationBuilder
|
||||||
{
|
{
|
||||||
private static readonly Lazy<Assembly?> EntryAssemblyLazy = new(Assembly.GetEntryAssembly);
|
|
||||||
|
|
||||||
// Entry assembly can be null, for example in tests
|
|
||||||
private static Assembly? EntryAssembly => EntryAssemblyLazy.Value;
|
|
||||||
|
|
||||||
private static string GetDefaultTitle()
|
private static string GetDefaultTitle()
|
||||||
{
|
{
|
||||||
var entryAssemblyName = EntryAssembly?.GetName().Name;
|
var entryAssemblyName = EnvironmentEx.EntryAssembly?.GetName().Name;
|
||||||
if (string.IsNullOrWhiteSpace(entryAssemblyName))
|
if (string.IsNullOrWhiteSpace(entryAssemblyName))
|
||||||
return "App";
|
return "App";
|
||||||
|
|
||||||
@@ -226,26 +222,39 @@ public partial class CliApplicationBuilder
|
|||||||
|
|
||||||
private static string GetDefaultExecutableName()
|
private static string GetDefaultExecutableName()
|
||||||
{
|
{
|
||||||
var entryAssemblyLocation = EntryAssembly?.Location;
|
var entryAssemblyLocation = EnvironmentEx.EntryAssembly?.Location;
|
||||||
if (string.IsNullOrWhiteSpace(entryAssemblyLocation))
|
if (string.IsNullOrWhiteSpace(entryAssemblyLocation))
|
||||||
return "app";
|
return "app";
|
||||||
|
|
||||||
// The assembly can be an .exe or a .dll, depending on how it was packaged
|
// If the application was launched via matching EXE apphost, use that as the executable name
|
||||||
|
var isLaunchedViaAppHost = string.Equals(
|
||||||
|
EnvironmentEx.ProcessPath,
|
||||||
|
Path.ChangeExtension(entryAssemblyLocation, ".exe"),
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isLaunchedViaAppHost)
|
||||||
|
return Path.GetFileNameWithoutExtension(entryAssemblyLocation);
|
||||||
|
|
||||||
|
// Otherwise, use the entry assembly as the executable name.
|
||||||
|
// Prefix it with `dotnet` if it's a DLL file.
|
||||||
var isDll = string.Equals(
|
var isDll = string.Equals(
|
||||||
Path.GetExtension(entryAssemblyLocation),
|
Path.GetExtension(entryAssemblyLocation),
|
||||||
".dll",
|
".dll",
|
||||||
StringComparison.OrdinalIgnoreCase
|
StringComparison.OrdinalIgnoreCase
|
||||||
);
|
);
|
||||||
|
|
||||||
var name = isDll
|
return isDll
|
||||||
? "dotnet " + Path.GetFileName(entryAssemblyLocation)
|
? "dotnet " + Path.GetFileName(entryAssemblyLocation)
|
||||||
: Path.GetFileNameWithoutExtension(entryAssemblyLocation);
|
: Path.GetFileNameWithoutExtension(entryAssemblyLocation);
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDefaultVersionText() =>
|
private static string GetDefaultVersionText()
|
||||||
EntryAssembly is not null
|
{
|
||||||
? "v" + EntryAssembly.GetName().Version.ToSemanticString()
|
var entryAssemblyVersion = EnvironmentEx.EntryAssembly?.GetName().Version;
|
||||||
: "v1.0";
|
if (entryAssemblyVersion is null)
|
||||||
|
return "v1.0";
|
||||||
|
|
||||||
|
return "v" + entryAssemblyVersion.ToSemanticString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
20
CliFx/Utils/EnvironmentEx.cs
Normal file
20
CliFx/Utils/EnvironmentEx.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace CliFx.Utils;
|
||||||
|
|
||||||
|
internal static class EnvironmentEx
|
||||||
|
{
|
||||||
|
private static readonly Lazy<string?> ProcessPathLazy = new(() =>
|
||||||
|
{
|
||||||
|
using var process = Process.GetCurrentProcess();
|
||||||
|
return process.MainModule?.FileName;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static string? ProcessPath => ProcessPathLazy.Value;
|
||||||
|
|
||||||
|
private static readonly Lazy<Assembly?> EntryAssemblyLazy = new(Assembly.GetEntryAssembly);
|
||||||
|
|
||||||
|
public static Assembly? EntryAssembly => EntryAssemblyLazy.Value;
|
||||||
|
}
|
||||||
@@ -209,7 +209,7 @@ OPTIONS
|
|||||||
Overall, parameters and options are both used to consume input from the command line, but they differ in a few important ways:
|
Overall, parameters and options are both used to consume input from the command line, but they differ in a few important ways:
|
||||||
|
|
||||||
| | Parameter | Option |
|
| | Parameter | Option |
|
||||||
| ------------------ | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
|
|--------------------|--------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
|
||||||
| **Identification** | Positional (by relative order). | Nominal (by name or short name). |
|
| **Identification** | Positional (by relative order). | Nominal (by name or short name). |
|
||||||
| **Requiredness** | Required by default. Only the last parameter can be configured to be optional. | Optional by default. Any option can be configured to be required without limitations. |
|
| **Requiredness** | Required by default. Only the last parameter can be configured to be optional. | Optional by default. Any option can be configured to be required without limitations. |
|
||||||
| **Arity** | Only the last parameter can be bound to a non-scalar property (i.e. an array). | Any option can be bound to a non-scalar property without limitations. |
|
| **Arity** | Only the last parameter can be bound to a non-scalar property (i.e. an array). | Any option can be bound to a non-scalar property without limitations. |
|
||||||
|
|||||||
Reference in New Issue
Block a user