Skip to content

Commit 617a86b

Browse files
Don't lose OutputWindow contents after reload
After project/solution conversion a reload will be needed, so it's kind of annoying to destroy the log Could refine this more to only restore the log in that particular circumstance, but there seems little to lose doing it all the time.
1 parent 7fd6f7a commit 617a86b

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

Vsix/CodeConversion.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class CodeConversion
2424
private readonly VisualStudioWorkspace _visualStudioWorkspace;
2525
public static readonly string ConverterTitle = "Code converter";
2626
private static readonly string Intro = Environment.NewLine + Environment.NewLine + new string(Enumerable.Repeat('-', 80).ToArray()) + Environment.NewLine + "Writing converted files to disk:";
27+
private VisualStudioInteraction.OutputWindow _outputWindow;
2728
private string SolutionDir => Path.GetDirectoryName(_visualStudioWorkspace.CurrentSolution.FilePath);
2829

2930
public CodeConversion(IServiceProvider serviceProvider, VisualStudioWorkspace visualStudioWorkspace,
@@ -32,6 +33,7 @@ public CodeConversion(IServiceProvider serviceProvider, VisualStudioWorkspace vi
3233
GetOptions = getOptions;
3334
_serviceProvider = serviceProvider;
3435
_visualStudioWorkspace = visualStudioWorkspace;
36+
_outputWindow = new VisualStudioInteraction.OutputWindow();
3537
}
3638

3739
public async Task PerformProjectConversion<TLanguageConversion>(IReadOnlyCollection<Project> selectedProjects) where TLanguageConversion : ILanguageConversion, new()
@@ -52,7 +54,7 @@ await Task.Run(() => {
5254

5355
if (GetOptions().CopyResultToClipboardForSingleDocument) {
5456
Clipboard.SetText(conversionResult.ConvertedCode ?? conversionResult.GetExceptionsAsString());
55-
VisualStudioInteraction.OutputWindow.WriteToOutputWindow("Conversion result copied to clipboard.");
57+
_outputWindow.WriteToOutputWindow("Conversion result copied to clipboard.");
5658
VisualStudioInteraction.ShowMessageBox(_serviceProvider, "Conversion result copied to clipboard.", conversionResult.GetExceptionsAsString(), false);
5759
}
5860

@@ -66,8 +68,9 @@ private void WriteConvertedFilesAndShowSummary(IEnumerable<ConversionResult> con
6668
string longestFilePath = null;
6769
var longestFileLength = -1;
6870

69-
VisualStudioInteraction.OutputWindow.WriteToOutputWindow(Intro);
70-
VisualStudioInteraction.OutputWindow.ForceShowOutputPane();
71+
_outputWindow.Clear();
72+
_outputWindow.WriteToOutputWindow(Intro);
73+
_outputWindow.ForceShowOutputPane();
7174

7275
foreach (var convertedFile in convertedFiles) {
7376
if (convertedFile.SourcePathOrNull == null) continue;
@@ -96,8 +99,8 @@ private void FinalizeConversion(List<string> files, List<string> errors, string
9699
{
97100
var options = GetOptions();
98101
var conversionSummary = GetConversionSummary(files, errors);
99-
VisualStudioInteraction.OutputWindow.WriteToOutputWindow(conversionSummary);
100-
VisualStudioInteraction.OutputWindow.ForceShowOutputPane();
102+
_outputWindow.WriteToOutputWindow(conversionSummary);
103+
_outputWindow .ForceShowOutputPane();
101104

102105
if (longestFilePath != null)
103106
{
@@ -113,14 +116,14 @@ private void FinalizeConversion(List<string> files, List<string> errors, string
113116
if (shouldOverwriteSolutionAndProjectFiles)
114117
{
115118
var titleMessage = options.CreateBackups ? "Creating backups and overwriting files:" : "Overwriting files:" + "";
116-
VisualStudioInteraction.OutputWindow.WriteToOutputWindow(titleMessage);
119+
_outputWindow.WriteToOutputWindow(titleMessage);
117120
foreach (var fileToOverwrite in filesToOverwrite)
118121
{
119122
if (options.CreateBackups) File.Copy(fileToOverwrite.SourcePathOrNull, fileToOverwrite.SourcePathOrNull + ".bak", true);
120123
File.WriteAllText(fileToOverwrite.TargetPathOrNull, fileToOverwrite.ConvertedCode);
121124

122125
var targetPathRelativeToSolutionDir = PathRelativeToSolutionDir(fileToOverwrite.TargetPathOrNull);
123-
VisualStudioInteraction.OutputWindow.WriteToOutputWindow(Environment.NewLine + $"* {targetPathRelativeToSolutionDir}");
126+
_outputWindow.WriteToOutputWindow(Environment.NewLine + $"* {targetPathRelativeToSolutionDir}");
124127
}
125128
}
126129
}
@@ -163,7 +166,7 @@ private void LogProgress(ConversionResult convertedFile, List<string> errors)
163166
output += $" contains errors{Environment.NewLine} {indentedException}";
164167
}
165168

166-
VisualStudioInteraction.OutputWindow.WriteToOutputWindow(output);
169+
_outputWindow.WriteToOutputWindow(output);
167170
}
168171

169172
private string PathRelativeToSolutionDir(string path)

Vsix/VisualStudioInteraction.cs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Linq;
66
using System.Reflection;
77
using System.Runtime.InteropServices;
8+
using System.Text;
89
using EnvDTE;
910
using EnvDTE80;
1011
using Microsoft.VisualStudio;
@@ -147,12 +148,25 @@ public static bool ShowMessageBox(IServiceProvider serviceProvider, string title
147148
defaultOk || !showCancelButton ? OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST : OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_SECOND) == answeredOk;
148149
}
149150

150-
public static class OutputWindow
151+
public class OutputWindow
151152
{
152153
private const string PaneName = "Code Converter";
153154
private static readonly Guid PaneGuid = new Guid("44F575C6-36B5-4CDB-AAAE-E096E6A446BF");
154-
private static readonly Lazy<IVsOutputWindowPane> OutputPane = new Lazy<IVsOutputWindowPane>(CreateOutputPane);
155-
155+
private readonly IVsOutputWindowPane _outputPane;
156+
private readonly StringBuilder _cachedOutput = new StringBuilder();
157+
158+
// Reference to avoid GC https://docs.microsoft.com/en-us/dotnet/api/envdte.solutionevents?view=visualstudiosdk-2017#remarks
159+
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
160+
private readonly SolutionEvents _solutionEvents;
161+
162+
public OutputWindow()
163+
{
164+
_outputPane = CreateOutputPane();
165+
166+
_solutionEvents = Dte.Events.SolutionEvents;
167+
_solutionEvents.Opened += () => { WriteToOutputWindow(_cachedOutput.ToString()); };
168+
}
169+
156170
private static IVsOutputWindow GetOutputWindow()
157171
{
158172
IServiceProvider serviceProvider = new ServiceProvider(Dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
@@ -161,9 +175,8 @@ private static IVsOutputWindow GetOutputWindow()
161175
private static IVsOutputWindowPane CreateOutputPane()
162176
{
163177
Guid generalPaneGuid = PaneGuid;
164-
IVsOutputWindowPane pane;
165178
var outputWindow = GetOutputWindow();
166-
outputWindow.GetPane(ref generalPaneGuid, out pane);
179+
outputWindow.GetPane(ref generalPaneGuid, out var pane);
167180

168181
if (pane == null) {
169182
outputWindow.CreatePane(ref generalPaneGuid, PaneName, 1, 1);
@@ -173,15 +186,22 @@ private static IVsOutputWindowPane CreateOutputPane()
173186
return pane;
174187
}
175188

176-
public static void ForceShowOutputPane()
189+
public void Clear()
190+
{
191+
_cachedOutput.Clear();
192+
_outputPane.Clear();
193+
}
194+
195+
public void ForceShowOutputPane()
177196
{
178197
Dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput).Visible = true;
179-
OutputPane.Value.Activate();
198+
_outputPane.Activate();
180199
}
181200

182-
public static void WriteToOutputWindow(string message)
201+
public void WriteToOutputWindow(string message)
183202
{
184-
OutputPane.Value.OutputString(message);
203+
_cachedOutput.AppendLine(message);
204+
_outputPane.OutputString(message);
185205
}
186206
}
187207
}

0 commit comments

Comments
 (0)