mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-26 09:39:49 +08:00
121 lines
3.9 KiB
C#
121 lines
3.9 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BetterGenshinImpact.GameTask.Common;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace BetterGenshinImpact.GameTask.Shell;
|
|
|
|
[Serializable]
|
|
public class ShellExecutor
|
|
{
|
|
private string command = string.Empty;
|
|
private int maxWaitSeconds = 60;
|
|
private bool noWindow = true;
|
|
private bool output = true;
|
|
|
|
public static readonly JsonSerializerOptions JsonOptions = new()
|
|
{
|
|
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
|
|
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
AllowTrailingCommas = true,
|
|
ReadCommentHandling = JsonCommentHandling.Skip,
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
|
};
|
|
|
|
|
|
public async Task Execute(CancellationToken ct = default)
|
|
{
|
|
if (string.IsNullOrEmpty(command))
|
|
{
|
|
TaskControl.Logger.LogWarning("无法执行Shell: Shell为空");
|
|
return;
|
|
}
|
|
|
|
var cmd = new Process();
|
|
cmd.StartInfo.FileName = "cmd.exe";
|
|
cmd.StartInfo.Arguments = "/k @echo off";
|
|
cmd.StartInfo.RedirectStandardInput = true;
|
|
cmd.StartInfo.RedirectStandardOutput = true;
|
|
cmd.StartInfo.CreateNoWindow = noWindow;
|
|
cmd.StartInfo.UseShellExecute = false;
|
|
if (ct.IsCancellationRequested)
|
|
{
|
|
TaskControl.Logger.LogError("shell {Shell} 被取消", command);
|
|
}
|
|
|
|
TaskControl.Logger.LogInformation("执行shell:{Shell},超时时间为 {Wait} 秒", command, maxWaitSeconds);
|
|
var timeoutSignal = new CancellationTokenSource(TimeSpan.FromSeconds(maxWaitSeconds));
|
|
var mixedToken = CancellationTokenSource.CreateLinkedTokenSource(ct, timeoutSignal.Token).Token;
|
|
|
|
cmd.Start();
|
|
var outputShell = "";
|
|
var outputText = "";
|
|
var cmdCanceled = false;
|
|
try
|
|
{
|
|
await cmd.StandardInput.WriteLineAsync(command.AsMemory(), mixedToken);
|
|
await cmd.StandardInput.FlushAsync(mixedToken);
|
|
cmd.StandardInput.Close();
|
|
await cmd.WaitForExitAsync(mixedToken);
|
|
if (output)
|
|
{
|
|
outputShell = await cmd.StandardOutput.ReadLineAsync(mixedToken) ?? "";
|
|
outputText = await cmd.StandardOutput.ReadToEndAsync(mixedToken);
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
cmdCanceled = true;
|
|
}
|
|
|
|
if (!cmd.HasExited || cmdCanceled)
|
|
{
|
|
cmd.Kill();
|
|
if (ct.IsCancellationRequested)
|
|
{
|
|
TaskControl.Logger.LogError("shell {Shell} 被取消", command);
|
|
}
|
|
else if (timeoutSignal.IsCancellationRequested)
|
|
{
|
|
TaskControl.Logger.LogWarning("shell {Shell} 超时", command);
|
|
}
|
|
else
|
|
{
|
|
TaskControl.Logger.LogWarning("shell {Shell} 出现异常输出,可能未能成功执行。", command);
|
|
}
|
|
}
|
|
|
|
if (output)
|
|
{
|
|
TaskControl.Logger.LogInformation("shell {End} 运行结束,输出:{Output}", outputShell, outputText);
|
|
}
|
|
else
|
|
{
|
|
TaskControl.Logger.LogInformation("shell {End} 运行结束", command);
|
|
}
|
|
|
|
SystemControl.ActivateWindow();
|
|
}
|
|
|
|
public static ShellExecutor BuildFromShellName(string name)
|
|
{
|
|
var obj = new ShellExecutor
|
|
{
|
|
command = name
|
|
};
|
|
return obj;
|
|
}
|
|
|
|
public static ShellExecutor BuildFromJson(string json)
|
|
{
|
|
// 留给以后玩
|
|
var task = JsonSerializer.Deserialize<ShellExecutor>(json, JsonOptions) ??
|
|
throw new Exception("Failed to deserialize ShellExecutorTask");
|
|
return task;
|
|
}
|
|
} |