From da07907434f3b36d0e4c71069eb572c4c6d4afb8 Mon Sep 17 00:00:00 2001 From: Andrey Shchekin Date: Wed, 29 Jul 2015 22:03:51 +1200 Subject: [PATCH] [gh-9] Potential fix to the startup crash. --- ExceptionBreaker/ExceptionBreaker.csproj | 1 + ExceptionBreaker/ExceptionBreakerPackage.cs | 2 +- .../Implementation/ExtensionLogger.cs | 46 +++++++++++++++++-- .../Implementation/IDiagnosticLogger.cs | 6 ++- .../Implementation/VSInteropHelper.cs | 21 +++++++++ 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 ExceptionBreaker/Implementation/VSInteropHelper.cs diff --git a/ExceptionBreaker/ExceptionBreaker.csproj b/ExceptionBreaker/ExceptionBreaker.csproj index 2e57c3e..984f919 100644 --- a/ExceptionBreaker/ExceptionBreaker.csproj +++ b/ExceptionBreaker/ExceptionBreaker.csproj @@ -172,6 +172,7 @@ + diff --git a/ExceptionBreaker/ExceptionBreakerPackage.cs b/ExceptionBreaker/ExceptionBreakerPackage.cs index 8fa6227..4898b67 100644 --- a/ExceptionBreaker/ExceptionBreakerPackage.cs +++ b/ExceptionBreaker/ExceptionBreakerPackage.cs @@ -62,7 +62,7 @@ protected override void Initialize() { Trace.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this)); base.Initialize(); - Logger = new ExtensionLogger("ExceptionBreaker", paneCaption => GetOutputPane(GuidList.OutputPane, paneCaption)); + Logger = new ExtensionLogger("ExceptionBreaker", this, GuidList.OutputPane); _dte = (DTE)GetService(typeof(DTE)); SetupExceptionBreakManager(); diff --git a/ExceptionBreaker/Implementation/ExtensionLogger.cs b/ExceptionBreaker/Implementation/ExtensionLogger.cs index 37d1940..c935625 100644 --- a/ExceptionBreaker/Implementation/ExtensionLogger.cs +++ b/ExceptionBreaker/Implementation/ExtensionLogger.cs @@ -1,25 +1,61 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell.Interop; namespace ExceptionBreaker.Implementation { public class ExtensionLogger : IDiagnosticLogger { - private readonly IVsOutputWindowPane _outputPane; private readonly string _traceCategory; + private readonly IServiceProvider _serviceProvider; + private readonly Guid _outputPaneGuid; + private readonly string _outputPaneCaption; - public ExtensionLogger(string name, Func getOutputPane) { - _outputPane = getOutputPane("Ext: " + name + " (Diagnostic)"); + public ExtensionLogger(string name, IServiceProvider serviceProvider, Guid outputPaneGuid) { _traceCategory = name; + _serviceProvider = serviceProvider; + _outputPaneGuid = outputPaneGuid; + _outputPaneCaption = "Ext: " + _traceCategory + " (Diagnostic)"; } public void WriteLine(string message) { - _outputPane.OutputString(message + Environment.NewLine); + var outputPane = GetOutputPane(); + if (outputPane != null) + outputPane.OutputString(message + Environment.NewLine); + Trace.WriteLine(message, _traceCategory); } public void WriteLine(string format, params object[] args) { WriteLine(string.Format(format, args)); } + + public void WriteLine(string format, object arg1) { + WriteLine(string.Format(format, arg1)); + } + + public void WriteLine(string format, object arg1, object arg2) { + WriteLine(string.Format(format, arg1, arg2)); + } + + private IVsOutputWindowPane GetOutputPane() { + var outputWindow = (IVsOutputWindow)_serviceProvider.GetService(typeof(SVsOutputWindow)); + if (outputWindow == null) + return null; + + var guid = _outputPaneGuid; + var pane = (IVsOutputWindowPane)null; + var hr = outputWindow.GetPane(ref guid, out pane); + if (hr != VSConstants.E_FAIL && hr != VSConstants.E_INVALIDARG) + VSInteropHelper.Validate(hr); + + if (pane == null) { + VSInteropHelper.Validate(outputWindow.CreatePane(ref guid, _outputPaneCaption, 1, 1)); + VSInteropHelper.Validate(outputWindow.GetPane(ref guid, out pane)); + } + + VSInteropHelper.Validate(pane.Activate()); + return pane; + } } -} +} \ No newline at end of file diff --git a/ExceptionBreaker/Implementation/IDiagnosticLogger.cs b/ExceptionBreaker/Implementation/IDiagnosticLogger.cs index b270dfd..cd40e0a 100644 --- a/ExceptionBreaker/Implementation/IDiagnosticLogger.cs +++ b/ExceptionBreaker/Implementation/IDiagnosticLogger.cs @@ -1,6 +1,10 @@ -namespace ExceptionBreaker.Implementation { +using JetBrains.Annotations; + +namespace ExceptionBreaker.Implementation { public interface IDiagnosticLogger { void WriteLine(string message); void WriteLine(string format, params object[] args); + void WriteLine(string format, object arg1); + void WriteLine(string format, object arg1, object arg2); } } \ No newline at end of file diff --git a/ExceptionBreaker/Implementation/VSInteropHelper.cs b/ExceptionBreaker/Implementation/VSInteropHelper.cs new file mode 100644 index 0000000..67d00c9 --- /dev/null +++ b/ExceptionBreaker/Implementation/VSInteropHelper.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio; + +namespace ExceptionBreaker.Implementation { + public static class VSInteropHelper { + public static void Validate(int hresult) { + if (hresult != VSConstants.S_OK) + Marshal.ThrowExceptionForHR(hresult); + } + + public static void Release(object comObject) { + if (comObject == null) + return; + + Marshal.ReleaseComObject(comObject); + } + } +} \ No newline at end of file