forked from BeyondDimension/SteamTools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCommandLineHost.cs
More file actions
342 lines (303 loc) · 12.6 KB
/
CommandLineHost.cs
File metadata and controls
342 lines (303 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
using System.Application.UI;
using System.Application.Services;
using System.CommandLine;
using System.CommandLine.NamingConventionBinder;
using System.Runtime.InteropServices;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using System.Runtime.Versioning;
using System.Application.Settings;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
namespace System.Application.CommandLine;
/// <summary>
/// 命令行工具(Command Line Tools/CLT)
/// </summary>
public abstract class CommandLineHost : IDisposable
{
public const string command_main = "main";
bool disposedValue;
protected abstract IApplication.IDesktopProgramHost Host { get; }
protected abstract void ConfigureServices(DILevel level);
#if StartWatchTrace
protected abstract void StartWatchTraceRecord(string? mark = null, bool dispose = false);
#endif
public IApplication.SingletonInstance? AppInstance { get; protected set; }
protected abstract void StartApplication(string[] args);
public abstract IApplication? Application { get; }
protected abstract void SetIsMainProcess(bool value);
protected abstract void SetIsCLTProcess(bool value);
public int Run(string[] args)
{
if (args.Length == 0) args = new[] { "-h" };
// https://docs.microsoft.com/zh-cn/archive/msdn-magazine/2019/march/net-parse-the-command-line-with-system-commandline
var rootCommand = new RootCommand("命令行工具(Command Line Tools/CLT)");
void MainHandler() => MainHandler_(null);
void MainHandler_(Action? onInitStartuped)
{
#if StartWatchTrace
StartWatchTraceRecord("ProcessCheck");
#endif
ConfigureServices(Host.IsMainProcess ? DILevel.MainProcess : DILevel.Min);
#if StartWatchTrace
StartWatchTraceRecord("Startup.Init");
#endif
onInitStartuped?.Invoke();
if (Host.IsMainProcess)
{
var isInitAppInstanceReset = false;
initAppInstance: AppInstance = new();
if (!AppInstance.IsFirst)
{
//Console.WriteLine("ApplicationInstance.SendMessage(string.Empty);");
if (IApplication.SingletonInstance.SendMessage(string.Empty))
{
return;
}
else
{
if (!isInitAppInstanceReset &&
IApplication.SingletonInstance.TryKillCurrentAllProcess())
{
isInitAppInstanceReset = true;
AppInstance.Dispose();
goto initAppInstance;
}
else
{
return;
}
}
}
AppInstance.MessageReceived += value =>
{
if (string.IsNullOrEmpty(value))
{
var app = Application;
if (app != null)
{
MainThread2.BeginInvokeOnMainThread(app.RestoreMainWindow);
}
}
};
}
//#if StartWatchTrace
// StartWatchTraceRecord("ApplicationInstance");
//#endif
// initCef();
//#if StartWatchTrace
// StartWatchTraceRecord("InitCefNetApp");
//#endif
if (Host.IsMainProcess)
{
StartApplication(args);
}
#if StartWatchTrace
StartWatchTrace.Record("InitAvaloniaApp");
#endif
}
void MainHandlerByCLT() => MainHandlerByCLT_(null);
void MainHandlerByCLT_(Action? onInitStartuped)
{
SetIsMainProcess(true);
SetIsCLTProcess(false);
MainHandler_(onInitStartuped);
}
#if DEBUG
// -clt debug -args 730
var debug = new Command("debug", "调试");
debug.AddOption(new Option<string>("-args", () => "", "测试参数"));
debug.Handler = CommandHandler.Create((string args) => // 参数名与类型要与 Option 中一致!
{
//Console.WriteLine("-clt debug -args " + args);
// OutputType WinExe 导致控制台输入不会显示,只能附加一个新的控制台窗口显示内容,不合适
// 如果能取消 管理员权限要求,改为运行时管理员权限,
// 则可尝试通过 Windows Terminal 或直接 Host 进行命令行模式
MainHandlerByCLT();
});
rootCommand.AddCommand(debug);
#endif
var main = new Command(command_main)
{
Handler = CommandHandler.Create(MainHandler),
};
rootCommand.AddCommand(main);
// -clt devtools
// -clt devtools -disable_gpu
// -clt devtools -use_wgl
var devtools = new Command("devtools");
devtools.AddOption(new Option<bool>("-disable_gpu", () => false, "禁用 GPU 硬件加速"));
devtools.AddOption(new Option<bool>("-use_wgl", () => false, "使用 Native OpenGL(仅 Windows)"));
devtools.Handler = CommandHandler.Create((bool disable_gpu, bool use_wgl) =>
{
IApplication.EnableDevtools = true;
IApplication.DisableGPU = disable_gpu;
IApplication.UseWgl = use_wgl;
MainHandlerByCLT_(onInitStartuped: () =>
{
IApplication.LoggerMinLevel = LogLevel.Debug;
});
});
rootCommand.AddCommand(devtools);
// -clt c -silence
var common = new Command("c", "common");
common.AddOption(new Option<bool>("-silence", "静默启动(不弹窗口)"));
common.Handler = CommandHandler.Create((bool silence) =>
{
Host.IsMinimize = silence;
MainHandlerByCLT();
});
rootCommand.AddCommand(common);
// -clt steam -account
var steamuser = new Command("steam", "Steam 相关操作");
steamuser.AddOption(new Option<string>("-account", "指定对应 Steam 用户名"));
steamuser.Handler = CommandHandler.Create(async (string account) =>
{
if (!string.IsNullOrEmpty(account))
{
ConfigureServices(DILevel.Steam);
var steamService = ISteamService.Instance;
var users = steamService.GetRememberUserList();
var currentuser = users.Where(s => s.AccountName == account).FirstOrDefault();
await steamService.ShutdownSteamAsync();
if (currentuser != null)
{
currentuser.MostRecent = true;
steamService.UpdateLocalUserData(users);
steamService.SetCurrentUser(account);
}
steamService.StartSteam();
}
});
rootCommand.AddCommand(steamuser);
// -clt app -id 632360
var run_SteamApp = new Command("app", "运行 Steam 应用");
run_SteamApp.AddOption(new Option<int>("-id", "指定一个 Steam 游戏 Id"));
run_SteamApp.AddOption(new Option<bool>("-achievement", "打开成就解锁窗口"));
run_SteamApp.AddOption(new Option<bool>("-cloudmanager", "打开云存档管理窗口"));
run_SteamApp.AddOption(new Option<bool>("-silence", "挂运行服务,不加载窗口,内存占用更小"));
run_SteamApp.Handler = CommandHandler.Create(async (int id, bool achievement, bool cloudmanager) =>
{
try
{
if (id <= 0) return;
if (cloudmanager)
{
ConfigureServices(DILevel.GUI | DILevel.Steam | DILevel.HttpClientFactory);
IViewModelManager.Instance.InitCloudManageMain(id);
StartApplication(args);
}
else if (achievement)
{
ConfigureServices(DILevel.GUI | DILevel.Steam | DILevel.HttpClientFactory);
IViewModelManager.Instance.InitUnlockAchievement(id);
StartApplication(args);
}
else
{
ConfigureServices(DILevel.Steam);
SteamConnectService.Current.Initialize(id);
TaskCompletionSource tcs = new();
await tcs.Task;
}
}
catch (Exception ex)
{
Log.Error(nameof(run_SteamApp), ex, "Start");
}
});
rootCommand.AddCommand(run_SteamApp);
// -clt show -config -cert
var show = new Command("show", "显示信息");
show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
show.AddOption(new Option<bool>("-cert", "显示当前根证书信息"));
show.Handler = CommandHandler.Create((bool config, bool cert) =>
{
if (OperatingSystem.IsWindows()) if (!AttachConsole()) AllocConsole();
if (config)
{
Console.WriteLine("Config: ");
try
{
SettingsHost.Load();
var configValue = SettingsHostBase.Local.ToJsonString();
Console.WriteLine(configValue);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine();
}
if (cert)
{
Console.WriteLine("RootCertificate: ");
try
{
using X509Certificate2 rootCert = new(ICertificateManager.DefaultPfxFilePath, (string?)null, X509KeyStorageFlags.Exportable);
Console.WriteLine("Subject:");
Console.WriteLine(rootCert.Subject);
Console.WriteLine("SerialNumber:");
Console.WriteLine(rootCert.SerialNumber);
Console.WriteLine("PeriodValidity:");
Console.Write(rootCert.GetEffectiveDateString());
Console.Write(" ~ ");
Console.Write(rootCert.GetExpirationDateString());
Console.WriteLine();
Console.WriteLine("SHA256:");
Console.WriteLine(rootCert.GetCertHashStringCompat(HashAlgorithmName.SHA256));
Console.WriteLine("SHA1:");
Console.WriteLine(rootCert.GetCertHashStringCompat(HashAlgorithmName.SHA1));
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine();
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
if (OperatingSystem.IsWindows()) FreeConsole();
});
rootCommand.AddCommand(show);
// TODO
//var proxy = new Command("proxy", "仅启用代理服务,无 GUI 窗口");
var r = rootCommand.InvokeAsync(args).GetAwaiter().GetResult();
return r;
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
AppInstance?.Dispose();
Application?.Dispose();
}
// TODO: 释放未托管的资源(未托管的对象)并重写终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
// // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
// ~CommandLineHost()
// {
// // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
// Dispose(disposing: false);
// }
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
[SupportedOSPlatform("Windows")]
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(int dwProcessId = -1);
[SupportedOSPlatform("Windows")]
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeConsole();
[SupportedOSPlatform("Windows")]
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AllocConsole();
}