Skip to content

Commit ab19de0

Browse files
feat(output): add GUID-based shared Output pane support
Adds overloads to create/retrieve Output window panes using a caller-supplied GUID, enabling multiple extensions to share a single pane. Updates ExceptionExtensions to always use the well-known GUID for the "Extensions" pane, ensuring idempotency and preventing duplicates. Refactors error handling and removes redundant pane creation logic.
1 parent 97d8b04 commit ab19de0

3 files changed

Lines changed: 45 additions & 14 deletions

File tree

src/toolkit/Community.VisualStudio.Toolkit.Shared/ExtensionMethods/ExceptionExtensions.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,17 @@ private static async Task EnsurePaneAsync()
203203
{
204204
if (_pane == null)
205205
{
206-
// Try and get the Extensions pane and if it doesn't exist then create it.
207-
_pane = await VS.Windows.GetOutputWindowPaneAsync(_extensionsPaneGuid);
208-
209-
if (_pane == null)
206+
try
207+
{
208+
// Always create the pane using the well-known GUID so that all extensions using
209+
// this toolkit share a single "Extensions" pane instead of each creating their own.
210+
// CreatePane in VS is idempotent for a given GUID, so this returns the existing
211+
// pane if one has already been registered under this GUID.
212+
_pane = await VS.Windows.CreateOutputWindowPaneAsync(_paneTitle, _extensionsPaneGuid);
213+
}
214+
catch (Exception ex)
210215
{
211-
try
212-
{
213-
_pane = await VS.Windows.CreateOutputWindowPaneAsync(_paneTitle);
214-
}
215-
catch (Exception ex)
216-
{
217-
Diagnostics.Debug.WriteLine(ex);
218-
}
216+
Diagnostics.Debug.WriteLine(ex);
219217
}
220218
}
221219

src/toolkit/Community.VisualStudio.Toolkit.Shared/Helpers/OutputWindowPane.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,30 @@ public string Name
104104
/// <param name="name">The name (title) of the new pane.</param>
105105
/// <param name="lazyCreate">Whether to lazily create the pane upon first write.</param>
106106
/// <returns>A new OutputWindowPane.</returns>
107-
public static async Task<OutputWindowPane> CreateAsync(string name, bool lazyCreate = true)
107+
public static Task<OutputWindowPane> CreateAsync(string name, bool lazyCreate = true)
108+
=> CreateAsync(name, Guid.NewGuid(), lazyCreate);
109+
110+
/// <summary>
111+
/// Creates a new Output window pane with the given name and a caller-supplied GUID,
112+
/// or returns the existing pane if one with that GUID has already been registered.
113+
/// </summary>
114+
/// <remarks>
115+
/// Use this overload when multiple components or extensions need to share a single pane.
116+
/// By providing a stable, well-known GUID, every caller will end up writing to the same
117+
/// pane instead of each one creating a new pane with the same name.
118+
/// </remarks>
119+
/// <param name="name">The name (title) of the pane.</param>
120+
/// <param name="guid">The stable unique identifier of the pane.</param>
121+
/// <param name="lazyCreate">Whether to lazily create the pane upon first write.</param>
122+
/// <returns>A new OutputWindowPane.</returns>
123+
public static async Task<OutputWindowPane> CreateAsync(string name, Guid guid, bool lazyCreate = true)
108124
{
109125
if (string.IsNullOrEmpty(name))
110126
{
111127
throw new ArgumentException(nameof(name));
112128
}
113129

114-
OutputWindowPane pane = new(name, Guid.NewGuid());
130+
OutputWindowPane pane = new(name, guid);
115131

116132
if (!lazyCreate)
117133
{

src/toolkit/Community.VisualStudio.Toolkit.Shared/Windows/Windows.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,23 @@ public enum VSOutputWindowPane
3939
public Task<OutputWindowPane> CreateOutputWindowPaneAsync(string name, bool lazyCreate = true)
4040
=> OutputWindowPane.CreateAsync(name, lazyCreate);
4141

42+
/// <summary>
43+
/// Creates a new Output window pane with the given name and a caller-supplied GUID,
44+
/// or returns the existing pane if one with that GUID has already been registered.
45+
/// The pane can be created now or lazily upon the first write to it.
46+
/// </summary>
47+
/// <remarks>
48+
/// Use this overload when multiple components or extensions need to share a single pane.
49+
/// By providing a stable, well-known GUID, every caller will end up writing to the same
50+
/// pane instead of each one creating a new pane with the same name.
51+
/// </remarks>
52+
/// <param name="name">The name (title) of the pane.</param>
53+
/// <param name="guid">The stable unique identifier of the pane.</param>
54+
/// <param name="lazyCreate">Whether to lazily create the pane upon first write.</param>
55+
/// <returns>A new OutputWindowPane.</returns>
56+
public Task<OutputWindowPane> CreateOutputWindowPaneAsync(string name, Guid guid, bool lazyCreate = true)
57+
=> OutputWindowPane.CreateAsync(name, guid, lazyCreate);
58+
4259
/// <summary>
4360
/// Gets an existing Visual Studio Output window pane (General, Build, Debug).
4461
/// If the General pane does not already exist then it will be created, but that is not the case

0 commit comments

Comments
 (0)