mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Co-authored-by: Yu Leng <yuleng@microsoft.com>
244 lines
9.8 KiB
C#
244 lines
9.8 KiB
C#
#pragma warning disable IDE0073
|
|
// Copyright (c) Brice Lambson
|
|
// The Brice Lambson licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
|
|
#pragma warning restore IDE0073
|
|
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using ImageResizer.Models;
|
|
using ImageResizer.Properties;
|
|
using ImageResizer.Utilities;
|
|
using ImageResizer.ViewModels;
|
|
using ImageResizer.Views;
|
|
using ManagedCommon;
|
|
|
|
namespace ImageResizer
|
|
{
|
|
public partial class App : Application, IDisposable
|
|
{
|
|
private const string LogSubFolder = "\\Image Resizer\\Logs";
|
|
|
|
/// <summary>
|
|
/// Gets cached AI availability state, checked at app startup.
|
|
/// Can be updated after model download completes or background initialization.
|
|
/// </summary>
|
|
public static AiAvailabilityState AiAvailabilityState { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// Event fired when AI initialization completes in background.
|
|
/// Allows UI to refresh state when initialization finishes.
|
|
/// </summary>
|
|
public static event EventHandler<AiAvailabilityState> AiInitializationCompleted;
|
|
|
|
static App()
|
|
{
|
|
try
|
|
{
|
|
// Initialize logger early (mirroring PowerOCR pattern)
|
|
Logger.InitializeLogger(LogSubFolder);
|
|
}
|
|
catch
|
|
{
|
|
/* swallow logger init issues silently */
|
|
}
|
|
|
|
try
|
|
{
|
|
string appLanguage = LanguageHelper.LoadLanguage();
|
|
if (!string.IsNullOrEmpty(appLanguage))
|
|
{
|
|
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(appLanguage);
|
|
}
|
|
}
|
|
catch (CultureNotFoundException ex)
|
|
{
|
|
Logger.LogError("CultureNotFoundException: " + ex.Message);
|
|
}
|
|
|
|
Console.InputEncoding = Encoding.Unicode;
|
|
}
|
|
|
|
protected override void OnStartup(StartupEventArgs e)
|
|
{
|
|
// Fix for .net 3.1.19 making Image Resizer not adapt to DPI changes.
|
|
NativeMethods.SetProcessDPIAware();
|
|
|
|
// TODO: Re-enable AI Super Resolution in next release by removing this #if block
|
|
// Temporarily disable AI Super Resolution feature (hide from UI but keep code)
|
|
#if true // Set to false to re-enable AI Super Resolution
|
|
AiAvailabilityState = AiAvailabilityState.NotSupported;
|
|
ResizeBatch.SetAiSuperResolutionService(Services.NoOpAiSuperResolutionService.Instance);
|
|
|
|
// Skip AI detection mode as well
|
|
if (e?.Args?.Length > 0 && e.Args[0] == "--detect-ai")
|
|
{
|
|
Services.AiAvailabilityCacheService.SaveCache(AiAvailabilityState.NotSupported);
|
|
Environment.Exit(0);
|
|
return;
|
|
}
|
|
#else
|
|
// Check for AI detection mode (called by Runner in background)
|
|
if (e?.Args?.Length > 0 && e.Args[0] == "--detect-ai")
|
|
{
|
|
RunAiDetectionMode();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (PowerToys.GPOWrapperProjection.GPOWrapper.GetConfiguredImageResizerEnabledValue() == PowerToys.GPOWrapperProjection.GpoRuleConfigured.Disabled)
|
|
{
|
|
/* TODO: Add logs to ImageResizer.
|
|
* Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
|
*/
|
|
Logger.LogWarning("GPO policy disables ImageResizer. Exiting.");
|
|
Environment.Exit(0); // Current.Exit won't work until there's a window opened.
|
|
return;
|
|
}
|
|
|
|
// AI Super Resolution is not supported on Windows 10 - skip cache check entirely
|
|
if (OSVersionHelper.IsWindows10())
|
|
{
|
|
AiAvailabilityState = AiAvailabilityState.NotSupported;
|
|
ResizeBatch.SetAiSuperResolutionService(Services.NoOpAiSuperResolutionService.Instance);
|
|
Logger.LogInfo("AI Super Resolution not supported on Windows 10");
|
|
}
|
|
else
|
|
{
|
|
// Load AI availability from cache (written by Runner's background detection)
|
|
var cachedState = Services.AiAvailabilityCacheService.LoadCache();
|
|
|
|
if (cachedState.HasValue)
|
|
{
|
|
AiAvailabilityState = cachedState.Value;
|
|
Logger.LogInfo($"AI state loaded from cache: {AiAvailabilityState}");
|
|
}
|
|
else
|
|
{
|
|
// No valid cache - default to NotSupported (Runner will detect and cache for next startup)
|
|
AiAvailabilityState = AiAvailabilityState.NotSupported;
|
|
Logger.LogInfo("No AI cache found, defaulting to NotSupported");
|
|
}
|
|
|
|
// If AI is potentially available, start background initialization (non-blocking)
|
|
if (AiAvailabilityState == AiAvailabilityState.Ready)
|
|
{
|
|
_ = InitializeAiServiceAsync(); // Fire and forget - don't block UI
|
|
}
|
|
else
|
|
{
|
|
// AI not available - set NoOp service immediately
|
|
ResizeBatch.SetAiSuperResolutionService(Services.NoOpAiSuperResolutionService.Instance);
|
|
}
|
|
}
|
|
|
|
var batch = ResizeBatch.FromCommandLine(Console.In, e?.Args);
|
|
|
|
// TODO: Add command-line parameters that can be used in lieu of the input page (issue #14)
|
|
var mainWindow = new MainWindow(new MainViewModel(batch, Settings.Default));
|
|
mainWindow.Show();
|
|
|
|
// Temporary workaround for issue #1273
|
|
WindowHelpers.BringToForeground(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle);
|
|
}
|
|
|
|
/// <summary>
|
|
/// AI detection mode: perform detection, write to cache, and exit.
|
|
/// Called by Runner in background to avoid blocking ImageResizer UI startup.
|
|
/// </summary>
|
|
private void RunAiDetectionMode()
|
|
{
|
|
try
|
|
{
|
|
Logger.LogInfo("Running AI detection mode...");
|
|
|
|
// AI Super Resolution is not supported on Windows 10
|
|
if (OSVersionHelper.IsWindows10())
|
|
{
|
|
Logger.LogInfo("AI detection skipped: Windows 10 does not support AI Super Resolution");
|
|
Services.AiAvailabilityCacheService.SaveCache(AiAvailabilityState.NotSupported);
|
|
Environment.Exit(0);
|
|
return;
|
|
}
|
|
|
|
// Perform detection (reuse existing logic)
|
|
var state = CheckAiAvailability();
|
|
|
|
// Write result to cache file
|
|
Services.AiAvailabilityCacheService.SaveCache(state);
|
|
|
|
Logger.LogInfo($"AI detection complete: {state}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogError($"AI detection failed: {ex.Message}");
|
|
Services.AiAvailabilityCacheService.SaveCache(AiAvailabilityState.NotSupported);
|
|
}
|
|
|
|
// Exit silently without showing UI
|
|
Environment.Exit(0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check AI Super Resolution availability on this system.
|
|
/// Performs architecture check and model availability check.
|
|
/// </summary>
|
|
private static AiAvailabilityState CheckAiAvailability()
|
|
{
|
|
// AI feature disabled - always return NotSupported
|
|
return AiAvailabilityState.NotSupported;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize AI Super Resolution service asynchronously in background.
|
|
/// Runs without blocking UI startup - state change event notifies completion.
|
|
/// </summary>
|
|
private static async System.Threading.Tasks.Task InitializeAiServiceAsync()
|
|
{
|
|
AiAvailabilityState finalState;
|
|
|
|
try
|
|
{
|
|
// Create and initialize AI service using async factory
|
|
var aiService = await Services.WinAiSuperResolutionService.CreateAsync();
|
|
|
|
if (aiService != null)
|
|
{
|
|
ResizeBatch.SetAiSuperResolutionService(aiService);
|
|
Logger.LogInfo("AI Super Resolution service initialized successfully.");
|
|
finalState = AiAvailabilityState.Ready;
|
|
}
|
|
else
|
|
{
|
|
// Initialization failed - use default NoOp service
|
|
ResizeBatch.SetAiSuperResolutionService(Services.NoOpAiSuperResolutionService.Instance);
|
|
Logger.LogWarning("AI Super Resolution service initialization failed. Using default service.");
|
|
finalState = AiAvailabilityState.NotSupported;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Log error and use default NoOp service
|
|
ResizeBatch.SetAiSuperResolutionService(Services.NoOpAiSuperResolutionService.Instance);
|
|
Logger.LogError($"Exception during AI service initialization: {ex.Message}");
|
|
finalState = AiAvailabilityState.NotSupported;
|
|
}
|
|
|
|
// Update cached state and notify listeners
|
|
AiAvailabilityState = finalState;
|
|
AiInitializationCompleted?.Invoke(null, finalState);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// Dispose AI Super Resolution service
|
|
ResizeBatch.DisposeAiSuperResolutionService();
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
}
|