Наша сборка Qt VS Tools
giy
2022-09-02 ca47896204482bf4a6979e3838bf7f09f61cebeb
QtVsTools.Core/Messages.cs
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt VS Tools.
@@ -26,34 +26,25 @@
**
****************************************************************************/
using EnvDTE;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Thread = System.Threading.Thread;
using System.Windows.Forms;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Threading;
using QtVsTools.VisualStudio;
using Task = System.Threading.Tasks.Task;
namespace QtVsTools.Core
{
    using VisualStudio;
    public static class Messages
    {
        private static OutputWindow Window { get; set; }
        private static OutputWindowPane Pane { get; set; }
        private static OutputWindowPane _BuildPane;
        private static OutputWindowPane BuildPane
        {
            get
            {
                return _BuildPane ?? (_BuildPane = Window.OutputWindowPanes.Cast<OutputWindowPane>()
                    .Where(pane => pane.Guid == "{1BD8A850-02D1-11D1-BEE7-00A0C913D1F8}")
                    .FirstOrDefault());
            }
        }
        private static readonly string PaneName = "Qt VS Tools";
        private static readonly Guid PaneGuid = new Guid("8f6a1e44-fa0b-49e5-9934-1c050555350e");
        /// <summary>
        /// Show a message on the output pane.
@@ -69,13 +60,15 @@
            FlushMessages();
        }
        static void OutputWindowPane_Print(string text)
        public static void Log(this Exception exception, bool clear = false, bool activate = false)
        {
            OutputWindowPane_Init();
            Pane.OutputString(text + "\r\n");
            // show buildPane if a build is in progress
            if (Dte.Solution.SolutionBuild.BuildState == vsBuildState.vsBuildStateInProgress)
                BuildPane?.Activate();
            msgQueue.Enqueue(new Msg()
            {
                Clear = clear,
                Text = ExceptionToString(exception),
                Activate = activate
            });
            FlushMessages();
        }
        /// <summary>
@@ -90,50 +83,44 @@
            FlushMessages();
        }
        static void OutputWindowPane_Activate()
        static async Task OutputWindowPane_ActivateAsync()
        {
            OutputWindowPane_Init();
            Pane?.Activate();
            await OutputWindowPane_InitAsync();
            await Pane?.ActivateAsync();
        }
        private static string ExceptionToString(System.Exception e)
        private static string ExceptionToString(System.Exception exception)
        {
            return e.Message + "\r\n" + "(" + e.StackTrace.Trim() + ")";
            return $"An exception ({exception.GetType().Name}) occurred.\r\n"
                   + $"Message:\r\n   {exception.Message}\r\n"
                   + $"Stack Trace:\r\n   {exception.StackTrace.Trim()}\r\n";
        }
        private static readonly string ErrorString = SR.GetString("Messages_ErrorOccured");
        private static readonly string WarningString = SR.GetString("Messages_Warning");
        private static readonly string SolutionString = SR.GetString("Messages_SolveProblem");
        static public void DisplayCriticalErrorMessage(System.Exception e)
        {
            MessageBox.Show(ErrorString +
                ExceptionToString(e),
                SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        static public void DisplayCriticalErrorMessage(string msg)
        public static void DisplayCriticalErrorMessage(string msg)
        {
            MessageBox.Show(ErrorString +
                msg,
                SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        static public void DisplayErrorMessage(System.Exception e)
        public static void DisplayErrorMessage(System.Exception e)
        {
            MessageBox.Show(ErrorString +
                ExceptionToString(e),
            MessageBox.Show(ExceptionToString(e),
                SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        static public void DisplayErrorMessage(string msg)
        public static void DisplayErrorMessage(string msg)
        {
            MessageBox.Show(ErrorString +
                msg,
                SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        static public void DisplayWarningMessage(System.Exception e, string solution)
        public static void DisplayWarningMessage(System.Exception e, string solution)
        {
            MessageBox.Show(WarningString +
                ExceptionToString(e) +
@@ -142,7 +129,7 @@
                SR.GetString("Resources_QtVsTools"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
        static public void DisplayWarningMessage(string msg)
        public static void DisplayWarningMessage(string msg)
        {
            MessageBox.Show(WarningString +
                msg,
@@ -158,10 +145,10 @@
            FlushMessages();
        }
        static void OutputWindowPane_Clear()
        static async Task OutputWindowPane_ClearAsync()
        {
            OutputWindowPane_Init();
            Pane?.Clear();
            await OutputWindowPane_InitAsync();
            await Pane?.ClearAsync();
        }
        class Msg
@@ -171,33 +158,20 @@
            public bool Activate { get; set; } = false;
        }
        static bool shuttingDown = false;
        static ConcurrentQueue<Msg> msgQueue = new ConcurrentQueue<Msg>();
        static DTE Dte { get; set; } = null;
        static readonly ConcurrentQueue<Msg> msgQueue = new ConcurrentQueue<Msg>();
        private static void OnBeginShutdown()
        private static async Task OutputWindowPane_InitAsync()
        {
            shuttingDown = true;
        }
        private static void OutputWindowPane_Init()
        {
            if (Dte == null)
                Dte = VsServiceProvider.GetService<DTE>();
            var t = Stopwatch.StartNew();
            while (Pane == null && t.ElapsedMilliseconds < 5000) {
                try {
                    Window = Dte.Windows.Item(Constants.vsWindowKindOutput).Object as OutputWindow;
                    Pane = Window?.OutputWindowPanes.Add(SR.GetString("Resources_QtVsTools"));
                } catch {
                }
            try {
                if (Pane == null)
                    Thread.Yield();
                    Pane = await OutputWindowPane.CreateAsync(PaneName, PaneGuid);
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine(ex);
            }
            Dte.Events.DTEEvents.OnBeginShutdown += OnBeginShutdown;
        }
        public static JoinableTaskFactory JoinableTaskFactory { get; set; }
        static readonly object staticCriticalSection = new object();
        static Task FlushTask { get; set; }
        static EventWaitHandle MessageReady { get; set; }
@@ -209,27 +183,21 @@
                    MessageReady = new EventWaitHandle(false, EventResetMode.AutoReset);
                    FlushTask = Task.Run(async () =>
                    {
                        while (!shuttingDown) {
                        var package = VsServiceProvider.Instance as Package;
                        while (!package.Zombied) {
                            if (!await MessageReady.ToTask(3000))
                                continue;
                            while (!msgQueue.IsEmpty) {
                                Msg msg;
                                if (!msgQueue.TryDequeue(out msg)) {
                                if (!msgQueue.TryDequeue(out Msg msg)) {
                                    await Task.Yield();
                                    continue;
                                }
                                ////////////////////////////////////////////////////////////////////
                                // Switch to main (UI) thread
                                await JoinableTaskFactory.SwitchToMainThreadAsync();
                                if (msg.Clear)
                                    OutputWindowPane_Clear();
                                    await OutputWindowPane_ClearAsync();
                                if (msg.Text != null)
                                    OutputWindowPane_Print(msg.Text);
                                    await OutputWindowPane_PrintAsync(msg.Text);
                                if (msg.Activate)
                                    OutputWindowPane_Activate();
                                ////////////////////////////////////////////////////////////////////
                                // Switch to background thread
                                await TaskScheduler.Default;
                                    await OutputWindowPane_ActivateAsync();
                            }
                        }
                    });
@@ -237,5 +205,15 @@
            }
            MessageReady.Set();
        }
        static async Task OutputWindowPane_PrintAsync(string text)
        {
            var active = await OutputWindowPane.GetActiveAsync();
            await OutputWindowPane_InitAsync();
            await Pane.PrintAsync(text);
            (active?.ActivateAsync()).Forget();
        }
    }
}