mirror of
https://github.com/microsoft/PowerToys
synced 2025-08-22 01:58:04 +00:00
CmdPal: Improve page exception details for users (#41035)
## Summary of the Pull Request Show timestamp, HRESULT (hex/decimal), and full Exception.ToString() in the error message. Centralize message generation in a helper class for consistency. Example: ``` ============================================================ 😢 An unexpected error occurred in the 'Open' extension. Summary: Message: Operation is not valid due to the current state of the object. (inferred from HRESULT 0x80131509) Type: System.Runtime.InteropServices.COMException Source: WinRT.Runtime Time: 2025-08-07 15:54:20.4189499 HRESULT: 0x80131509 (-2146233079) Stack Trace: at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|38_0(Int32 hr) at ABI.Microsoft.CommandPalette.Extensions.IListPageMethods.GetItems(IObjectReference _obj) at Microsoft.CmdPal.Core.ViewModels.ListViewModel.FetchItems() at Microsoft.CmdPal.Core.ViewModels.ListViewModel.InitializeProperties() at Microsoft.CmdPal.Core.ViewModels.PageViewModel.InitializeAsync() ------------------ Full Exception Details ------------------ System.Runtime.InteropServices.COMException (0x80131509) at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|38_0(Int32 hr) at ABI.Microsoft.CommandPalette.Extensions.IListPageMethods.GetItems(IObjectReference _obj) at Microsoft.CmdPal.Core.ViewModels.ListViewModel.FetchItems() at Microsoft.CmdPal.Core.ViewModels.ListViewModel.InitializeProperties() at Microsoft.CmdPal.Core.ViewModels.PageViewModel.InitializeAsync() ℹ️ If you need further assistance, please include this information in your support request. ℹ️ Before sending, take a quick look to make sure it doesn't contain any personal or sensitive information. ============================================================ ``` <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #41034 - [ ] **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 ## Validation Steps Performed I crashed an extension on purpose and read the message.
This commit is contained in:
parent
65b752b3ff
commit
409ae3d73a
@ -0,0 +1,66 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.CmdPal.Common.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides utility methods for building diagnostic and error messages.
|
||||
/// </summary>
|
||||
public static class DiagnosticsHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds a comprehensive exception message with timestamp and detailed diagnostic information.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception that occurred.</param>
|
||||
/// <param name="extensionHint">A hint about which extension caused the exception to help with debugging.</param>
|
||||
/// <returns>A string containing the exception details, timestamp, and source information for diagnostic purposes.</returns>
|
||||
public static string BuildExceptionMessage(Exception exception, string? extensionHint)
|
||||
{
|
||||
var locationHint = string.IsNullOrWhiteSpace(extensionHint) ? "application" : $"'{extensionHint}' extension";
|
||||
|
||||
// let's try to get a message from the exception or inferred it from the HRESULT
|
||||
// to show at least something
|
||||
var message = exception.Message;
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
var temp = Marshal.GetExceptionForHR(exception.HResult)?.Message;
|
||||
if (!string.IsNullOrWhiteSpace(temp))
|
||||
{
|
||||
message = temp + $" (inferred from HRESULT 0x{exception.HResult:X8})";
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
message = "[No message available]";
|
||||
}
|
||||
|
||||
// note: keep date time kind and format consistent with the log
|
||||
return $"""
|
||||
============================================================
|
||||
😢 An unexpected error occurred in the {locationHint}.
|
||||
|
||||
Summary:
|
||||
Message: {message}
|
||||
Type: {exception.GetType().FullName}
|
||||
Source: {exception.Source ?? "N/A"}
|
||||
Time: {DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fffffff}
|
||||
HRESULT: 0x{exception.HResult:X8} ({exception.HResult})
|
||||
|
||||
Stack Trace:
|
||||
{exception.StackTrace ?? "[No stack trace available]"}
|
||||
|
||||
------------------ Full Exception Details ------------------
|
||||
{exception}
|
||||
|
||||
ℹ️ If you need further assistance, please include this information in your support request.
|
||||
ℹ️ Before sending, take a quick look to make sure it doesn't contain any personal or sensitive information.
|
||||
============================================================
|
||||
|
||||
""";
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.CmdPal.Common.Helpers;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
@ -223,9 +224,10 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
|
||||
extensionHint ??= ExtensionHost.GetExtensionDisplayName() ?? Title;
|
||||
Task.Factory.StartNew(
|
||||
() =>
|
||||
{
|
||||
ErrorMessage += $"A bug occurred in {$"the \"{extensionHint}\"" ?? "an unknown's"} extension's code:\n{ex.Message}\n{ex.Source}\n{ex.StackTrace}\n\n";
|
||||
},
|
||||
{
|
||||
var message = DiagnosticsHelper.BuildExceptionMessage(ex, extensionHint);
|
||||
ErrorMessage += message;
|
||||
},
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.None,
|
||||
Scheduler);
|
||||
|
@ -410,8 +410,8 @@ public partial class TopLevelCommandManager : ObservableObject,
|
||||
|
||||
void IPageContext.ShowException(Exception ex, string? extensionHint)
|
||||
{
|
||||
var errorMessage = $"A bug occurred in {$"the \"{extensionHint}\"" ?? "an unknown's"} extension's code:\n{ex.Message}\n{ex.Source}\n{ex.StackTrace}\n\n";
|
||||
CommandPaletteHost.Instance.Log(errorMessage);
|
||||
var message = DiagnosticsHelper.BuildExceptionMessage(ex, extensionHint ?? "TopLevelCommandManager");
|
||||
CommandPaletteHost.Instance.Log(message);
|
||||
}
|
||||
|
||||
internal bool IsProviderActive(string id)
|
||||
|
Loading…
x
Reference in New Issue
Block a user