mirror of
https://github.com/jie65535/GrasscutterCommandGenerator.git
synced 2025-08-01 15:49:14 +08:00
Support for command line arguments (#155)
This commit is contained in:
parent
aabe6664b4
commit
b2b656b6cb
@ -282,9 +282,11 @@
|
||||
</Compile>
|
||||
<Compile Include="Utils\ArtifactUtils.cs" />
|
||||
<Compile Include="Utils\Common.cs" />
|
||||
<Compile Include="Utils\GuiRedirect.cs" />
|
||||
<Compile Include="Utils\HttpHelper.cs" />
|
||||
<Compile Include="Utils\Logger.cs" />
|
||||
<Compile Include="Utils\GithubHelper.cs" />
|
||||
<Compile Include="Utils\ToggleParser.cs" />
|
||||
<Compile Include="Utils\UIUtil.cs" />
|
||||
<EmbeddedResource Include="Forms\FormActivityEditor.en-US.resx">
|
||||
<DependentUpon>FormActivityEditor.cs</DependentUpon>
|
||||
|
@ -18,11 +18,13 @@
|
||||
**/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using GrasscutterTools.OpenCommand;
|
||||
using GrasscutterTools.Properties;
|
||||
using GrasscutterTools.Utils;
|
||||
|
||||
@ -63,8 +65,12 @@ namespace GrasscutterTools
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void Main()
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
var result = HandleCommandLine(args);
|
||||
if (result != -1)
|
||||
return result;
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
@ -91,8 +97,129 @@ namespace GrasscutterTools
|
||||
|
||||
Application.Run(new Forms.FormMain());
|
||||
Logger.I(TAG, "Program end.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#region - 命令行参数 -
|
||||
|
||||
/// <summary>
|
||||
/// 处理命令行参数并返回处理结果
|
||||
/// </summary>
|
||||
/// <param name="args">命令行参数</param>
|
||||
/// <returns>返回-1表示继续启动应用程序。返回其它值表示退出应用并将该值作为返回结果。</returns>
|
||||
private static int HandleCommandLine(string[] args)
|
||||
{
|
||||
var parser = new ToggleParser(args);
|
||||
if (parser.IsEmpty) return -1;
|
||||
try
|
||||
{
|
||||
GuiRedirect.Redirect();
|
||||
|
||||
// 是否启动日志
|
||||
if (parser.HasToggle("debug") || parser.HasToggle("log"))
|
||||
Logger.IsSaveLogs = true;
|
||||
|
||||
if (parser.HasToggle("v") || parser.HasToggle("version"))
|
||||
{
|
||||
Console.WriteLine("v" + Common.AppVersion.ToString(3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (parser.HasToggle("h") || parser.HasToggle("help") || parser.HasToggle("?"))
|
||||
{
|
||||
Console.WriteLine("Usages:");
|
||||
Console.WriteLine(" GcTools.exe -help");
|
||||
Console.WriteLine(" GcTools.exe -version");
|
||||
Console.WriteLine(" GcTools.exe -c \"cmd arg\"");
|
||||
Console.WriteLine(" GcTools.exe -c \"cmd1 arg\" && GcTools -c \"cmd2 arg1 arg2\"");
|
||||
Console.WriteLine(" GcTools.exe -host http://127.0.0.1:443 -token 123456 -c \"cmd1 arg1 arg2 | cmd2 | cmd3 arg\"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 服务器地址
|
||||
var host = parser.GetToggleValueOrDefault("host", Settings.Default.Host);
|
||||
// 服务器令牌
|
||||
var token = parser.GetToggleValueOrDefault("token", Settings.Default.TokenCache);
|
||||
|
||||
if (Settings.Default.Host != host || Settings.Default.TokenCache != token)
|
||||
{
|
||||
Settings.Default.Host = host;
|
||||
Settings.Default.TokenCache = token;
|
||||
Settings.Default.Save();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Logger.I(TAG, $"Host: {Settings.Default.Host} Token: {Settings.Default.TokenCache}");
|
||||
#endif
|
||||
// UID
|
||||
//Settings.Default.RemoteUid = decimal.Parse(parser.GetToggleValueOrDefault("uid", Settings.Default.RemoteUid.ToString()));
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(Settings.Default.Host) && !string.IsNullOrEmpty(Settings.Default.TokenCache))
|
||||
{
|
||||
Common.OC = new OpenCommandAPI(Settings.Default.Host, Settings.Default.TokenCache);
|
||||
}
|
||||
|
||||
// 解析并执行命令
|
||||
var cmd = parser.GetToggleValueOrDefault("c", string.Empty);
|
||||
if (string.IsNullOrEmpty(cmd)) cmd = parser.GetToggleValueOrDefault("command", string.Empty);
|
||||
if (!string.IsNullOrEmpty(cmd))
|
||||
{
|
||||
return RunCommand(cmd) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.E(TAG, "Parse command failed!", ex);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行命令
|
||||
/// </summary>
|
||||
/// <param name="commands">GC命令,由|分割多条命令</param>
|
||||
/// <returns>返回是否执行成功</returns>
|
||||
private static bool RunCommand(string commands)
|
||||
{
|
||||
if (Common.OC == null || !Common.OC.CanInvoke)
|
||||
{
|
||||
Console.WriteLine(Resources.RequireOpenCommandTip);
|
||||
Logger.E(TAG, Resources.RequireOpenCommandTip);
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var cmd in commands.Split('|').Select(FormatCommand))
|
||||
{
|
||||
var msg = Common.OC.Invoke(cmd).Result;
|
||||
Console.WriteLine(string.IsNullOrEmpty(msg) ? "OK" : msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
Logger.E(TAG, "RunCommand Error:", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化命令
|
||||
/// (去除收尾空白,替换换行)
|
||||
/// </summary>
|
||||
/// <param name="raw">原始输入</param>
|
||||
/// <returns>格式化后可执行命令</returns>
|
||||
private static string FormatCommand(string raw)
|
||||
{
|
||||
return raw.Trim().Replace("\\r", "\r").Replace("\\n", "\n");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region - 全局异常处理 -
|
||||
|
||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
|
64
Source/GrasscutterTools/Utils/GuiRedirect.cs
Normal file
64
Source/GrasscutterTools/Utils/GuiRedirect.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace GrasscutterTools.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="https://stackoverflow.com/a/17534263"/>
|
||||
/// </summary>
|
||||
public class GuiRedirect
|
||||
{
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool AttachConsole(int dwProcessId);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetStdHandle(StandardHandle nStdHandle);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern FileType GetFileType(IntPtr handle);
|
||||
//[DllImport("kernel32.dll", SetLastError = true)]
|
||||
//[return: MarshalAs(UnmanagedType.Bool)]
|
||||
//static extern bool AllocConsole();
|
||||
|
||||
private enum StandardHandle : uint
|
||||
{
|
||||
Input = unchecked((uint)-10),
|
||||
Output = unchecked((uint)-11),
|
||||
Error = unchecked((uint)-12)
|
||||
}
|
||||
|
||||
private enum FileType : uint
|
||||
{
|
||||
Unknown = 0x0000,
|
||||
Disk = 0x0001,
|
||||
Char = 0x0002,
|
||||
Pipe = 0x0003
|
||||
}
|
||||
|
||||
private static bool IsRedirected(IntPtr handle)
|
||||
{
|
||||
FileType fileType = GetFileType(handle);
|
||||
|
||||
return (fileType == FileType.Disk) || (fileType == FileType.Pipe);
|
||||
}
|
||||
|
||||
public static void Redirect()
|
||||
{
|
||||
if (IsRedirected(GetStdHandle(StandardHandle.Output)))
|
||||
{
|
||||
var initialiseOut = Console.Out;
|
||||
}
|
||||
|
||||
bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error));
|
||||
if (errorRedirected)
|
||||
{
|
||||
var initialiseError = Console.Error;
|
||||
}
|
||||
|
||||
AttachConsole(-1);
|
||||
|
||||
if (!errorRedirected)
|
||||
SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output));
|
||||
}
|
||||
}
|
||||
}
|
@ -25,16 +25,17 @@ namespace GrasscutterTools.Utils
|
||||
{
|
||||
public static class Logger
|
||||
{
|
||||
public static bool IsSaveLogs = false;
|
||||
|
||||
private static readonly string LogPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), $"GcTools-{DateTime.Now:MMdd}.log");
|
||||
|
||||
private static void Write(string message)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine($"{DateTime.Now:mm:ss.fff} {message}");
|
||||
#else
|
||||
// Test log
|
||||
//File.AppendAllText(LogPath, $"{DateTime.Now:mm:ss.fff} {message}{Environment.NewLine}");
|
||||
#endif
|
||||
if (IsSaveLogs)
|
||||
{
|
||||
Console.WriteLine($"{DateTime.Now:mm:ss.fff} {message}");
|
||||
File.AppendAllText(LogPath, $"{DateTime.Now:mm:ss.fff} {message}{Environment.NewLine}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void Write(string level, string tag, string message) => Write($"<{level}:{tag}> {message}");
|
||||
|
42
Source/GrasscutterTools/Utils/ToggleParser.cs
Normal file
42
Source/GrasscutterTools/Utils/ToggleParser.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace GrasscutterTools.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple command line toggles parser:
|
||||
/// - toggles are identified with (any number of) '-' prefixes
|
||||
/// - toggle can be with or without associated value
|
||||
/// - toggles are case-insensitive
|
||||
///
|
||||
/// <example>--toggle_without_value -toggle value</example>
|
||||
/// <see cref="https://gist.github.com/jchapuis/64b5adf9d0f3062e6a72dded110a6028"/>
|
||||
/// </summary>
|
||||
internal class ToggleParser
|
||||
{
|
||||
private readonly Dictionary<string, string> toggles;
|
||||
|
||||
public ToggleParser(string[] args)
|
||||
{
|
||||
toggles =
|
||||
args.Zip(args.Skip(1).Concat(new[] { string.Empty }), (first, second) => new { first, second })
|
||||
.Where(pair => IsToggle(pair.first))
|
||||
.ToDictionary(pair => RemovePrefix(pair.first).ToLowerInvariant(), g => IsToggle(g.second) ? string.Empty : g.second);
|
||||
}
|
||||
|
||||
private static string RemovePrefix(string toggle)
|
||||
=> new string(toggle.SkipWhile(c => c == '-').ToArray());
|
||||
|
||||
private static bool IsToggle(string arg)
|
||||
=> arg.StartsWith("-", StringComparison.InvariantCulture);
|
||||
|
||||
public bool HasToggle(string toggle)
|
||||
=> toggles.ContainsKey(toggle.ToLowerInvariant());
|
||||
|
||||
public string GetToggleValueOrDefault(string toggle, string defaultValue)
|
||||
=> toggles.TryGetValue(toggle.ToLowerInvariant(), out var value) ? value : defaultValue;
|
||||
|
||||
public bool IsEmpty => toggles.Count == 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user