diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Actions/ActionRuntimeManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Actions/ActionRuntimeManager.cs new file mode 100644 index 0000000000..995c8a5f6c --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Actions/ActionRuntimeManager.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading; +using System.Threading.Tasks; +using ManagedCommon; +using Windows.AI.Actions; + +namespace Microsoft.CmdPal.Ext.Indexer.Data; + +public static class ActionRuntimeManager +{ + private static readonly Lazy> _lazyRuntime = new(InitializeAsync); + + public static Task InstanceAsync => _lazyRuntime.Value; + + private static async Task InitializeAsync() + { + // If we tried 3 times and failed, should we think the action runtime is not working? + // then we should not use it anymore. + const int maxAttempts = 3; + + for (var attempt = 1; attempt <= maxAttempts; attempt++) + { + try + { + var runtime = ActionRuntimeFactory.CreateActionRuntime(); + await Task.Delay(500); + + return runtime; + } + catch (Exception ex) + { + Logger.LogError($"Attempt {attempt} to initialize ActionRuntime failed: {ex.Message}"); + + if (attempt == maxAttempts) + { + Logger.LogError($"Failed to initialize ActionRuntime: {ex.Message}"); + } + } + } + + return null; + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs index c31d7c5176..2633607e11 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs @@ -2,9 +2,11 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.CmdPal.Ext.Indexer.Data; using Microsoft.CmdPal.Ext.Indexer.Properties; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.Foundation.Metadata; namespace Microsoft.CmdPal.Ext.Indexer; @@ -17,6 +19,10 @@ public partial class IndexerCommandsProvider : CommandProvider Id = "Files"; DisplayName = Resources.IndexerCommandsProvider_DisplayName; Icon = Icons.FileExplorer; + if (ApiInformation.IsApiContractPresent("Windows.AI.Actions.ActionsContract", 4)) + { + _ = ActionRuntimeManager.InstanceAsync; + } } public override ICommandItem[] TopLevelCommands() diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs index d191a5a08c..d8a9d15316 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ActionsListContextItem.cs @@ -2,10 +2,12 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using System.Globalization; using System.Threading; using System.Threading.Tasks; +using ManagedCommon; using Microsoft.CmdPal.Ext.Indexer.Commands; using Microsoft.CmdPal.Ext.Indexer.Data; using Microsoft.CmdPal.Ext.Indexer.Properties; @@ -15,7 +17,7 @@ using Windows.System; namespace Microsoft.CmdPal.Ext.Indexer.Pages; -internal sealed partial class ActionsListContextItem : CommandContextItem +internal sealed partial class ActionsListContextItem : CommandContextItem, IDisposable { private readonly string fullPath; private readonly List actions = []; @@ -41,20 +43,24 @@ internal sealed partial class ActionsListContextItem : CommandContextItem private void UpdateMoreCommands() { - try + lock (UpdateMoreCommandsLock) { - lock (UpdateMoreCommandsLock) + if (actionRuntime == null) { - if (actionRuntime == null) - { - actionRuntime = ActionRuntimeFactory.CreateActionRuntime(); - Task.Delay(500).Wait(); - } - - actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed; - actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed; + actionRuntime = ActionRuntimeManager.InstanceAsync.GetAwaiter().GetResult(); } + if (actionRuntime == null) + { + return; + } + + actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed; + actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed; + } + + try + { var extension = System.IO.Path.GetExtension(fullPath).ToLower(CultureInfo.InvariantCulture); ActionEntity entity = null; if (extension != null) @@ -85,9 +91,20 @@ internal sealed partial class ActionsListContextItem : CommandContextItem MoreCommands = [.. actions]; } } - catch + catch (Exception ex) { - actionRuntime = null; + Logger.LogError($"Error updating commands: {ex.Message}"); + } + } + + public void Dispose() + { + lock (UpdateMoreCommandsLock) + { + if (actionRuntime != null) + { + actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed; + } } } }