LenovoLegionToolkit

Форк
0
530 строк · 18.2 Кб
1
#if !DEBUG
2
using LenovoLegionToolkit.Lib.System;
3
#endif
4
using System;
5
using System.Diagnostics;
6
using System.Linq;
7
using System.Reflection;
8
using System.Threading;
9
using System.Threading.Tasks;
10
using System.Windows;
11
using System.Windows.Interop;
12
using System.Windows.Media;
13
using System.Windows.Threading;
14
using LenovoLegionToolkit.Lib;
15
using LenovoLegionToolkit.Lib.Automation;
16
using LenovoLegionToolkit.Lib.Controllers;
17
using LenovoLegionToolkit.Lib.Extensions;
18
using LenovoLegionToolkit.Lib.Features;
19
using LenovoLegionToolkit.Lib.Features.Hybrid;
20
using LenovoLegionToolkit.Lib.Features.Hybrid.Notify;
21
using LenovoLegionToolkit.Lib.Features.PanelLogo;
22
using LenovoLegionToolkit.Lib.Features.WhiteKeyboardBacklight;
23
using LenovoLegionToolkit.Lib.Listeners;
24
using LenovoLegionToolkit.Lib.SoftwareDisabler;
25
using LenovoLegionToolkit.Lib.Utils;
26
using LenovoLegionToolkit.WPF.Extensions;
27
using LenovoLegionToolkit.WPF.Pages;
28
using LenovoLegionToolkit.WPF.Resources;
29
using LenovoLegionToolkit.WPF.Utils;
30
using LenovoLegionToolkit.WPF.Windows;
31
using LenovoLegionToolkit.WPF.Windows.Utils;
32
using WinFormsApp = System.Windows.Forms.Application;
33
using WinFormsHighDpiMode = System.Windows.Forms.HighDpiMode;
34

35
namespace LenovoLegionToolkit.WPF;
36

37
public partial class App
38
{
39
    private const string MUTEX_NAME = "LenovoLegionToolkit_Mutex_6efcc882-924c-4cbc-8fec-f45c25696f98";
40
    private const string EVENT_NAME = "LenovoLegionToolkit_Event_6efcc882-924c-4cbc-8fec-f45c25696f98";
41

42
    private Mutex? _singleInstanceMutex;
43
    private EventWaitHandle? _singleInstanceWaitHandle;
44

45
    public new static App Current => (App)Application.Current;
46

47
    private async void Application_Startup(object sender, StartupEventArgs e)
48
    {
49
#if DEBUG
50
        if (Debugger.IsAttached)
51
        {
52
            Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName)
53
                .Where(p => p.Id != Environment.ProcessId)
54
                .ForEach(p =>
55
                {
56
                    p.Kill();
57
                    p.WaitForExit();
58
                });
59
        }
60
#endif
61

62
        var flags = new Flags(e.Args);
63

64
        Log.Instance.IsTraceEnabled = flags.IsTraceEnabled;
65

66
        AppDomain.CurrentDomain.UnhandledException += AppDomain_UnhandledException;
67

68
        if (Log.Instance.IsTraceEnabled)
69
            Log.Instance.Trace($"Flags: {flags}");
70

71
        EnsureSingleInstance();
72

73
        await LocalizationHelper.SetLanguageAsync(true);
74

75
        if (!flags.SkipCompatibilityCheck)
76
        {
77
            await CheckBasicCompatibilityAsync();
78
            await CheckCompatibilityAsync();
79
        }
80

81
        if (Log.Instance.IsTraceEnabled)
82
            Log.Instance.Trace($"Starting... [version={Assembly.GetEntryAssembly()?.GetName().Version}, build={Assembly.GetEntryAssembly()?.GetBuildDateTimeString()}, os={Environment.OSVersion}, dotnet={Environment.Version}]");
83

84
        WinFormsApp.SetHighDpiMode(WinFormsHighDpiMode.PerMonitorV2);
85
        RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
86

87
        IoCContainer.Initialize(
88
            new Lib.IoCModule(),
89
            new Lib.Automation.IoCModule(),
90
            new IoCModule()
91
        );
92

93
        IoCContainer.Resolve<HttpClientFactory>().SetProxy(flags.ProxyUrl, flags.ProxyUsername, flags.ProxyPassword, flags.ProxyAllowAllCerts);
94

95
        IoCContainer.Resolve<PowerModeFeature>().AllowAllPowerModesOnBattery = flags.AllowAllPowerModesOnBattery;
96
        IoCContainer.Resolve<RGBKeyboardBacklightController>().ForceDisable = flags.ForceDisableRgbKeyboardSupport;
97
        IoCContainer.Resolve<SpectrumKeyboardBacklightController>().ForceDisable = flags.ForceDisableSpectrumKeyboardSupport;
98
        IoCContainer.Resolve<WhiteKeyboardLenovoLightingBacklightFeature>().ForceDisable = flags.ForceDisableLenovoLighting;
99
        IoCContainer.Resolve<PanelLogoLenovoLightingBacklightFeature>().ForceDisable = flags.ForceDisableLenovoLighting;
100
        IoCContainer.Resolve<PortsBacklightFeature>().ForceDisable = flags.ForceDisableLenovoLighting;
101
        IoCContainer.Resolve<IGPUModeFeature>().ExperimentalGPUWorkingMode = flags.ExperimentalGPUWorkingMode;
102
        IoCContainer.Resolve<DGPUNotify>().ExperimentalGPUWorkingMode = flags.ExperimentalGPUWorkingMode;
103

104
        AutomationPage.EnableHybridModeAutomation = flags.EnableHybridModeAutomation;
105

106
        await LogSoftwareStatusAsync();
107
        await InitPowerModeFeatureAsync();
108
        await InitBatteryFeatureAsync();
109
        await InitRgbKeyboardControllerAsync();
110
        await InitSpectrumKeyboardControllerAsync();
111
        await InitGpuOverclockControllerAsync();
112
        await InitAutomationProcessorAsync();
113
        await InitHybridModeAsync();
114

115
        await IoCContainer.Resolve<AIController>().StartIfNeededAsync();
116

117
#if !DEBUG
118
        Autorun.Validate();
119
#endif
120

121
        var mainWindow = new MainWindow
122
        {
123
            WindowStartupLocation = WindowStartupLocation.CenterScreen,
124
            TrayTooltipEnabled = !flags.DisableTrayTooltip
125
        };
126
        MainWindow = mainWindow;
127

128
        IoCContainer.Resolve<ThemeManager>().Apply();
129

130
        if (flags.Minimized)
131
        {
132
            if (Log.Instance.IsTraceEnabled)
133
                Log.Instance.Trace($"Sending MainWindow to tray...");
134

135
            mainWindow.WindowState = WindowState.Minimized;
136
            mainWindow.Show();
137
            mainWindow.SendToTray();
138
        }
139
        else
140
        {
141
            if (Log.Instance.IsTraceEnabled)
142
                Log.Instance.Trace($"Showing MainWindow...");
143

144
            mainWindow.Show();
145
        }
146

147
        if (Log.Instance.IsTraceEnabled)
148
            Log.Instance.Trace($"Start up complete");
149
    }
150

151
    private void Application_Exit(object sender, ExitEventArgs e)
152
    {
153
        _singleInstanceMutex?.Close();
154
    }
155

156
    public void RestartMainWindow()
157
    {
158
        if (MainWindow is MainWindow mw)
159
        {
160
            mw.SuppressClosingEventHandler = true;
161
            mw.Close();
162
        }
163

164
        var mainWindow = new MainWindow
165
        {
166
            WindowStartupLocation = WindowStartupLocation.CenterScreen
167
        };
168
        MainWindow = mainWindow;
169
        mainWindow.Show();
170
    }
171

172
    public async Task ShutdownAsync()
173
    {
174
        try
175
        {
176
            if (IoCContainer.TryResolve<AIController>() is { } aiController)
177
                await aiController.StopAsync();
178
        }
179
        catch {  /* Ignored. */ }
180

181
        try
182
        {
183
            if (IoCContainer.TryResolve<RGBKeyboardBacklightController>() is { } rgbKeyboardBacklightController)
184
            {
185
                if (await rgbKeyboardBacklightController.IsSupportedAsync())
186
                    await rgbKeyboardBacklightController.SetLightControlOwnerAsync(false);
187
            }
188
        }
189
        catch {  /* Ignored. */ }
190

191
        try
192
        {
193
            if (IoCContainer.TryResolve<SpectrumKeyboardBacklightController>() is { } spectrumKeyboardBacklightController)
194
            {
195
                if (await spectrumKeyboardBacklightController.IsSupportedAsync())
196
                    await spectrumKeyboardBacklightController.StopAuroraIfNeededAsync();
197
            }
198
        }
199
        catch {  /* Ignored. */ }
200

201
        try
202
        {
203
            if (IoCContainer.TryResolve<NativeWindowsMessageListener>() is { } nativeMessageWindowListener)
204
            {
205
                await nativeMessageWindowListener.StopAsync();
206
            }
207
        }
208
        catch {  /* Ignored. */ }
209

210

211
        Shutdown();
212
    }
213

214
    private void AppDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
215
    {
216
        var exception = e.ExceptionObject as Exception;
217

218
        Log.Instance.ErrorReport("AppDomain_UnhandledException", exception ?? new Exception($"Unknown exception caught: {e.ExceptionObject}"));
219
        Log.Instance.Trace($"Unhandled exception occurred.", exception);
220

221
        MessageBox.Show(string.Format(Resource.UnexpectedException, exception?.ToStringDemystified() ?? "Unknown exception.", Constants.ProjectUri),
222
            "Application Domain Error",
223
            MessageBoxButton.OK,
224
            MessageBoxImage.Error);
225
        Shutdown(1);
226
    }
227

228
    private void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
229
    {
230
        Log.Instance.ErrorReport("Application_DispatcherUnhandledException", e.Exception);
231
        Log.Instance.Trace($"Unhandled exception occurred.", e.Exception);
232

233
        MessageBox.Show(string.Format(Resource.UnexpectedException, e.Exception.ToStringDemystified(), Constants.ProjectUri),
234
            "Application Error",
235
            MessageBoxButton.OK,
236
            MessageBoxImage.Error);
237
        Shutdown(1);
238
    }
239

240
    private async Task CheckBasicCompatibilityAsync()
241
    {
242
        var isCompatible = await Compatibility.CheckBasicCompatibilityAsync();
243
        if (isCompatible)
244
            return;
245

246
        MessageBox.Show(Resource.IncompatibleDevice_Message, Resource.IncompatibleDevice_Title, MessageBoxButton.OK, MessageBoxImage.Error);
247

248
        Shutdown(99);
249
    }
250

251
    private async Task CheckCompatibilityAsync()
252
    {
253
        var (isCompatible, mi) = await Compatibility.IsCompatibleAsync();
254
        if (isCompatible)
255
        {
256
            if (Log.Instance.IsTraceEnabled)
257
                Log.Instance.Trace($"Compatibility check passed. [Vendor={mi.Vendor}, Model={mi.Model}, MachineType={mi.MachineType}, BIOS={mi.BiosVersion}]");
258
            return;
259
        }
260

261
        if (Log.Instance.IsTraceEnabled)
262
            Log.Instance.Trace($"Incompatible system detected. [Vendor={mi.Vendor}, Model={mi.Model}, MachineType={mi.MachineType}, BIOS={mi.BiosVersion}]");
263

264
        var unsupportedWindow = new UnsupportedWindow(mi);
265
        unsupportedWindow.Show();
266

267
        var result = await unsupportedWindow.ShouldContinue;
268
        if (result)
269
        {
270
            Log.Instance.IsTraceEnabled = true;
271

272
            if (Log.Instance.IsTraceEnabled)
273
                Log.Instance.Trace($"Compatibility check OVERRIDE. [Vendor={mi.Vendor}, Model={mi.Model}, MachineType={mi.MachineType}, version={Assembly.GetEntryAssembly()?.GetName().Version}, build={Assembly.GetEntryAssembly()?.GetBuildDateTimeString() ?? string.Empty}]");
274
            return;
275
        }
276

277
        if (Log.Instance.IsTraceEnabled)
278
            Log.Instance.Trace($"Shutting down... [Vendor={mi.Vendor}, Model={mi.Model}, MachineType={mi.MachineType}]");
279

280
        Shutdown(100);
281
    }
282

283
    private void EnsureSingleInstance()
284
    {
285
        if (Log.Instance.IsTraceEnabled)
286
            Log.Instance.Trace($"Checking for other instances...");
287

288
        _singleInstanceMutex = new Mutex(true, MUTEX_NAME, out var isOwned);
289
        _singleInstanceWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, EVENT_NAME);
290

291
        if (!isOwned)
292
        {
293
            if (Log.Instance.IsTraceEnabled)
294
                Log.Instance.Trace($"Another instance running, closing...");
295

296
            _singleInstanceWaitHandle.Set();
297
            Shutdown();
298
            return;
299
        }
300

301
        new Thread(() =>
302
        {
303
            while (_singleInstanceWaitHandle.WaitOne())
304
            {
305
                Current.Dispatcher.BeginInvoke(async () =>
306
                {
307
                    if (Current.MainWindow is { } window)
308
                    {
309
                        if (Log.Instance.IsTraceEnabled)
310
                            Log.Instance.Trace($"Another instance started, bringing this one to front instead...");
311

312
                        window.BringToForeground();
313
                    }
314
                    else
315
                    {
316
                        if (Log.Instance.IsTraceEnabled)
317
                            Log.Instance.Trace($"!!! PANIC !!! This instance is missing main window. Shutting down.");
318

319
                        await ShutdownAsync();
320
                    }
321
                });
322
            }
323
        })
324
        {
325
            IsBackground = true
326
        }.Start();
327
    }
328

329
    private static async Task LogSoftwareStatusAsync()
330
    {
331
        if (!Log.Instance.IsTraceEnabled)
332
            return;
333

334
        var vantageStatus = await IoCContainer.Resolve<VantageDisabler>().GetStatusAsync();
335
        Log.Instance.Trace($"Vantage status: {vantageStatus}");
336

337
        var legionZoneStatus = await IoCContainer.Resolve<LegionZoneDisabler>().GetStatusAsync();
338
        Log.Instance.Trace($"LegionZone status: {legionZoneStatus}");
339

340
        var fnKeysStatus = await IoCContainer.Resolve<FnKeysDisabler>().GetStatusAsync();
341
        Log.Instance.Trace($"FnKeys status: {fnKeysStatus}");
342
    }
343

344
    private static async Task InitHybridModeAsync()
345
    {
346
        try
347
        {
348
            if (Log.Instance.IsTraceEnabled)
349
                Log.Instance.Trace($"Initializing hybrid mode...");
350

351
            var feature = IoCContainer.Resolve<HybridModeFeature>();
352
            await feature.EnsureDGPUEjectedIfNeededAsync();
353
        }
354
        catch (Exception ex)
355
        {
356
            if (Log.Instance.IsTraceEnabled)
357
                Log.Instance.Trace($"Couldn't initialize hybrid mode.", ex);
358
        }
359
    }
360

361
    private static async Task InitAutomationProcessorAsync()
362
    {
363
        try
364
        {
365
            if (Log.Instance.IsTraceEnabled)
366
                Log.Instance.Trace($"Initializing automation processor...");
367

368
            var automationProcessor = IoCContainer.Resolve<AutomationProcessor>();
369
            await automationProcessor.InitializeAsync();
370
            automationProcessor.RunOnStartup();
371
        }
372
        catch (Exception ex)
373
        {
374
            if (Log.Instance.IsTraceEnabled)
375
                Log.Instance.Trace($"Couldn't initialize automation processor.", ex);
376
        }
377
    }
378

379
    private static async Task InitPowerModeFeatureAsync()
380
    {
381
        try
382
        {
383
            var feature = IoCContainer.Resolve<PowerModeFeature>();
384
            if (await feature.IsSupportedAsync())
385
            {
386
                if (Log.Instance.IsTraceEnabled)
387
                    Log.Instance.Trace($"Ensuring god mode state is applied...");
388

389
                await feature.EnsureGodModeStateIsAppliedAsync();
390
            }
391
        }
392
        catch (Exception ex)
393
        {
394
            if (Log.Instance.IsTraceEnabled)
395
                Log.Instance.Trace($"Couldn't ensure god mode state.", ex);
396
        }
397

398
        try
399
        {
400
            var feature = IoCContainer.Resolve<PowerModeFeature>();
401
            if (await feature.IsSupportedAsync())
402
            {
403
                if (Log.Instance.IsTraceEnabled)
404
                    Log.Instance.Trace($"Ensuring correct power plan is set...");
405

406
                await feature.EnsureCorrectPowerPlanIsSetAsync();
407
            }
408
        }
409
        catch (Exception ex)
410
        {
411
            if (Log.Instance.IsTraceEnabled)
412
                Log.Instance.Trace($"Couldn't ensure correct power plan.", ex);
413
        }
414
    }
415

416
    private static async Task InitBatteryFeatureAsync()
417
    {
418
        try
419
        {
420
            var feature = IoCContainer.Resolve<BatteryFeature>();
421
            if (await feature.IsSupportedAsync())
422
            {
423
                if (Log.Instance.IsTraceEnabled)
424
                    Log.Instance.Trace($"Ensuring correct battery mode is set...");
425

426
                await feature.EnsureCorrectBatteryModeIsSetAsync();
427
            }
428
        }
429
        catch (Exception ex)
430
        {
431
            if (Log.Instance.IsTraceEnabled)
432
                Log.Instance.Trace($"Couldn't ensure correct battery mode.", ex);
433
        }
434
    }
435

436
    private static async Task InitRgbKeyboardControllerAsync()
437
    {
438
        try
439
        {
440
            var controller = IoCContainer.Resolve<RGBKeyboardBacklightController>();
441
            if (await controller.IsSupportedAsync())
442
            {
443
                if (Log.Instance.IsTraceEnabled)
444
                    Log.Instance.Trace($"Setting light control owner and restoring preset...");
445

446
                await controller.SetLightControlOwnerAsync(true, true);
447
            }
448
            else
449
            {
450
                if (Log.Instance.IsTraceEnabled)
451
                    Log.Instance.Trace($"RGB keyboard is not supported.");
452
            }
453
        }
454
        catch (Exception ex)
455
        {
456
            if (Log.Instance.IsTraceEnabled)
457
                Log.Instance.Trace($"Couldn't set light control owner or current preset.", ex);
458
        }
459
    }
460

461
    private static async Task InitSpectrumKeyboardControllerAsync()
462
    {
463
        try
464
        {
465
            var controller = IoCContainer.Resolve<SpectrumKeyboardBacklightController>();
466
            if (await controller.IsSupportedAsync())
467
            {
468
                if (Log.Instance.IsTraceEnabled)
469
                    Log.Instance.Trace($"Starting Aurora if needed...");
470

471
                var result = await controller.StartAuroraIfNeededAsync();
472
                if (result)
473
                {
474
                    if (Log.Instance.IsTraceEnabled)
475
                        Log.Instance.Trace($"Aurora started.");
476
                }
477
                else
478
                {
479
                    if (Log.Instance.IsTraceEnabled)
480
                        Log.Instance.Trace($"Aurora not needed.");
481
                }
482
            }
483
            else
484
            {
485
                if (Log.Instance.IsTraceEnabled)
486
                    Log.Instance.Trace($"Spectrum keyboard is not supported.");
487
            }
488
        }
489
        catch (Exception ex)
490
        {
491
            if (Log.Instance.IsTraceEnabled)
492
                Log.Instance.Trace($"Couldn't start Aurora if needed.", ex);
493
        }
494
    }
495

496
    private static async Task InitGpuOverclockControllerAsync()
497
    {
498
        try
499
        {
500
            var controller = IoCContainer.Resolve<GPUOverclockController>();
501
            if (await controller.IsSupportedAsync())
502
            {
503
                if (Log.Instance.IsTraceEnabled)
504
                    Log.Instance.Trace($"Ensuring GPU overclock is applied...");
505

506
                var result = await controller.EnsureOverclockIsAppliedAsync().ConfigureAwait(false);
507
                if (result)
508
                {
509
                    if (Log.Instance.IsTraceEnabled)
510
                        Log.Instance.Trace($"GPU overclock applied.");
511
                }
512
                else
513
                {
514
                    if (Log.Instance.IsTraceEnabled)
515
                        Log.Instance.Trace($"GPU overclock not needed.");
516
                }
517
            }
518
            else
519
            {
520
                if (Log.Instance.IsTraceEnabled)
521
                    Log.Instance.Trace($"GPU overclock is not supported.");
522
            }
523
        }
524
        catch (Exception ex)
525
        {
526
            if (Log.Instance.IsTraceEnabled)
527
                Log.Instance.Trace($"Couldn't overclock GPU.", ex);
528
        }
529
    }
530
}
531

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.