Skip to content

Commit d091d55

Browse files
author
Greg Galloway
committed
adding detection of which extensions (SSIS, SSAS, SSRS) are installed and ensuring BI Developer Extensions handles it gracefully when not all are installed
-displaying versions of installed SSDT extensions in BIDS Helper Version window under Tools... Options -labeling each plugin with whether it's SSAS/SSIS/SSRS or General (meaning more than one which saves time and errors during load of plugins -on multi-product features (like Non-Default Properties Report and Smart Diff) moving code into separate functions so that we don't get assembly resolve errors when only SSAS not SSIS is installed or vice versa switching ReportViewer to use local DLLs in BI Developer Extensions install directory since these DLLs only come with SSAS extension fixing bug in Fixed Width Columns plugin to handle when .dtsx wasn't selected in solution explorer upgrading to newer VS extension references and switching BI Developer Extensions to load slightly asyncronously (mainly to avoid a warning in VS2019... further enhancements and testing needed for this)
1 parent 6e94883 commit d091d55

125 files changed

Lines changed: 787 additions & 72299 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

BidsHelperPackage.cs

Lines changed: 175 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Linq;
1616
using Microsoft.VisualStudio;
1717
using BIDSHelper.Core.Logger;
18+
using Task = System.Threading.Tasks.Task;
1819

1920
namespace BIDSHelper
2021
{
@@ -43,17 +44,17 @@ public enum enumIDEMode
4344
/// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
4445
/// </para>
4546
/// </remarks>
46-
[ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82")]
47+
[ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82", PackageAutoLoadFlags.BackgroundLoad)]
4748
//[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
48-
[PackageRegistration(UseManagedResourcesOnly = true)]
49+
[PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
4950
[InstalledProductRegistration("#110", "#112", VersionInfo.Version, IconResourceID = 400)] // Info on this package for Help/About
5051
[Guid(BIDSHelperPackage.PackageGuidString)]
5152
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
5253
[ProvideMenuResource("Menus.ctmenu", 1)]
5354
[ProvideOptionPage(typeof(BIDSHelperOptionsFeatures), "BIDS Helper", "Features", 0, 0, true)]
5455
[ProvideOptionPage(typeof(BIDSHelperPreferencesDialogPage), "BIDS Helper", "Preferences", 0, 0, true)]
5556
[ProvideOptionPage(typeof(BIDSHelperOptionsVersion), "BIDS Helper", "Version", 0, 0, true)]
56-
public sealed class BIDSHelperPackage : Package, IVsDebuggerEvents
57+
public sealed class BIDSHelperPackage : AsyncPackage, IVsDebuggerEvents
5758
{
5859
/// <summary>
5960
/// BidsHelperPackage GUID string.
@@ -75,15 +76,30 @@ public BIDSHelperPackage()
7576
// not sited yet inside Visual Studio environment. The place to do all the other
7677
// initialization is the Initialize method.
7778
}
78-
79+
7980

8081
#region Package Members
8182

8283
/// <summary>
8384
/// Initialization of the package; this method is called right after the package is sited, so this is the place
8485
/// where you can put all the initialization code that rely on services provided by VisualStudio.
8586
/// </summary>
86-
protected override void Initialize()
87+
protected override async Task InitializeAsync(System.Threading.CancellationToken cancellationToken, IProgress<ServiceProgressData> progress)
88+
//protected override void Initialize()
89+
{
90+
// runs in the background thread and doesn't affect the responsiveness of the UI thread.
91+
//await Task.Delay(100);
92+
93+
// Switches to the UI thread in order to consume some services used in command initialization
94+
await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
95+
96+
97+
98+
OriginalInitialize();
99+
100+
}
101+
102+
private void OriginalInitialize()
87103
{
88104
bool bQuitting = false;
89105
base.Initialize();
@@ -96,6 +112,67 @@ protected override void Initialize()
96112
Log.LogLevel = LogLevels.Warning;
97113
#endif
98114
Log.Debug("BIDSHelper Package Initialize Starting");
115+
116+
117+
//var bidsHelperPath = new System.IO.FileInfo(typeof(BIDSHelperPackage).Assembly.Location);
118+
119+
//#pragma warning disable 0618 //ignore the fact this is an obsolete method
120+
// AppDomain.CurrentDomain.AppendPrivatePath(bidsHelperPath.DirectoryName);
121+
// AppDomain.CurrentDomain.SetupInformation.ApplicationBase = bidsHelperPath.DirectoryName;
122+
//#pragma warning restore 0618
123+
124+
//(AppDomain.CurrentDomain.SetupInformation.PrivateBinPath + ";" ?? "") +
125+
/*
126+
* VS2019
127+
* Microsoft Reporting Services Projects (by Microsoft) v2.5.6 717ad572-c4b7-435c-c166-c2969777f718
128+
Microsoft Analysis Services Projects (by Microsoft) v2.8.11 04a86fc2-dbd5-4222-848e-911638e487fe
129+
130+
VS2017
131+
Microsoft Reporting Services Projects (by Microsoft) v2.5.6 717ad572-c4b7-435c-c166-c2969777f718
132+
Microsoft Integration Services Projects (by Microsoft) v2.1 D1B09713-C12E-43CC-9EF4-6562298285AB
133+
Microsoft Analysis Services Projects (by Microsoft) v2.8.11 04a86fc2-dbd5-4222-848e-911638e487fe
134+
135+
*/
136+
try
137+
{
138+
System.IServiceProvider serviceProvider = this as System.IServiceProvider;
139+
Microsoft.VisualStudio.ExtensionManager.IVsExtensionManager em =
140+
(Microsoft.VisualStudio.ExtensionManager.IVsExtensionManager)serviceProvider.GetService(
141+
typeof(Microsoft.VisualStudio.ExtensionManager.SVsExtensionManager));
142+
143+
string result = "";
144+
foreach (Microsoft.VisualStudio.ExtensionManager.IInstalledExtension i in em.GetInstalledExtensions())
145+
{
146+
try
147+
{
148+
Microsoft.VisualStudio.ExtensionManager.IExtensionHeader h = i.Header;
149+
if (!h.SystemComponent)
150+
{
151+
if (h.Name == "Microsoft Reporting Services Projects" || string.Compare(h.Identifier, "717ad572-c4b7-435c-c166-c2969777f718", true) == 0)
152+
{
153+
SSRSExtensionVersion = h.Version;
154+
Log.Debug("SSRS extension v" + h.Version + " is installed");
155+
}
156+
else if (h.Name == "Microsoft Integration Services Projects" || string.Compare(h.Identifier, "D1B09713-C12E-43CC-9EF4-6562298285AB", true) == 0)
157+
{
158+
SSISExtensionVersion = h.Version;
159+
Log.Debug("SSIS extension v" + h.Version + " is installed");
160+
}
161+
else if (h.Name == "Microsoft Analysis Services Projects" || string.Compare(h.Identifier, "04a86fc2-dbd5-4222-848e-911638e487fe", true) == 0)
162+
{
163+
SSASExtensionVersion = h.Version;
164+
Log.Debug("SSAS extension v" + h.Version + " is installed");
165+
}
166+
result += h.Name + " (by " + h.Author + ") v" + h.Version + " " + h.Identifier + " " + h.MoreInfoUrl + System.Environment.NewLine;
167+
}
168+
}
169+
catch { }
170+
}
171+
Log.Debug(result);
172+
}
173+
catch { }
174+
175+
99176
string sAddInTypeName = string.Empty;
100177
try
101178
{
@@ -128,9 +205,20 @@ protected override void Initialize()
128205
catch (ReflectionTypeLoadException loadEx)
129206
{
130207
types = loadEx.Types; //if some types can't be loaded (possibly because SSIS SSDT isn't installed, just SSAS?) then proceed with the types that work
131-
pluginExceptions.Add(loadEx);
132-
Log.Exception("Problem loading BIDS Helper types list", loadEx);
208+
//pluginExceptions.Add(loadEx); //in testing it appears that this does return the complete list of types so there's no need to display this exception to the user, I don't think since we will individually load plugins below and log exceptions
209+
//Log.Exception("Problem loading BIDS Helper types list", loadEx);
210+
//Log.Error(FormatLoaderException(loadEx));
133211
}
212+
Log.Debug($"Found {types.Length} types");
213+
214+
//can be used for debugging which types couldn't be loaded above
215+
//for (int i = 0; i < types.Length; i++)
216+
//{
217+
// if (types[i] == null)
218+
// Log.Error("types[" + i + "] is null");
219+
// else
220+
// Log.Debug("types[" + i + "]\t" + types[i].FullName);
221+
//}
134222

135223
foreach (Type t in types)
136224
{
@@ -141,6 +229,37 @@ protected override void Initialize()
141229
&& (!t.IsAbstract))
142230
{
143231
sAddInTypeName = t.Name;
232+
233+
//new... only load SSIS to test this works
234+
//load any not marked
235+
var categoryAttribute = t.GetCustomAttributes(typeof(FeatureCategory), true).FirstOrDefault() as FeatureCategory;
236+
if (categoryAttribute != null)
237+
{
238+
if (SSISExtensionVersion == null && categoryAttribute.Category == BIDSFeatureCategories.SSIS)
239+
{
240+
Log.Verbose(string.Format("Skipping Plugin: {0}", sAddInTypeName));
241+
continue;
242+
}
243+
else if (SSASExtensionVersion == null && (categoryAttribute.Category == BIDSFeatureCategories.SSASMulti || categoryAttribute.Category == BIDSFeatureCategories.SSASTabular))
244+
{
245+
Log.Verbose(string.Format("Skipping Plugin: {0}", sAddInTypeName));
246+
continue;
247+
}
248+
else if (SSRSExtensionVersion == null && categoryAttribute.Category == BIDSFeatureCategories.SSRS)
249+
{
250+
Log.Verbose(string.Format("Skipping Plugin: {0}", sAddInTypeName));
251+
continue;
252+
}
253+
}
254+
else
255+
{
256+
Log.Verbose(string.Format("Warning: Plugin FeatureCategory not set: {0}", sAddInTypeName));
257+
}
258+
259+
260+
261+
262+
144263
Log.Verbose(string.Format("Loading Plugin: {0}", sAddInTypeName));
145264

146265
BIDSHelperPluginBase feature;
@@ -173,41 +292,7 @@ protected override void Initialize()
173292
string sException = "";
174293
foreach (Exception pluginEx in pluginExceptions)
175294
{
176-
sException += string.Format("BIDS Helper encountered an error when Visual Studio started:\r\n{0}\r\n{1}"
177-
, pluginEx.Message
178-
, pluginEx.StackTrace);
179-
180-
Exception innerEx = pluginEx.InnerException;
181-
while (innerEx != null)
182-
{
183-
sException += string.Format("\r\nInner exception:\r\n{0}\r\n{1}"
184-
, innerEx.Message
185-
, innerEx.StackTrace);
186-
innerEx = innerEx.InnerException;
187-
}
188-
189-
ReflectionTypeLoadException ex = pluginEx as ReflectionTypeLoadException;
190-
if (ex == null) ex = pluginEx.InnerException as ReflectionTypeLoadException;
191-
if (ex != null)
192-
{
193-
System.Text.StringBuilder sb = new System.Text.StringBuilder();
194-
foreach (Exception exSub in ex.LoaderExceptions)
195-
{
196-
sb.AppendLine();
197-
sb.AppendLine(exSub.Message);
198-
System.IO.FileNotFoundException exFileNotFound = exSub as System.IO.FileNotFoundException;
199-
if (exFileNotFound != null)
200-
{
201-
if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
202-
{
203-
sb.AppendLine("Fusion Log:");
204-
sb.AppendLine(exFileNotFound.FusionLog);
205-
}
206-
}
207-
sb.AppendLine();
208-
}
209-
sException += sb.ToString();
210-
}
295+
sException += FormatLoaderException(pluginEx);
211296
}
212297
AddInLoadException = new Exception(sException);
213298
}
@@ -244,6 +329,51 @@ protected override void Initialize()
244329

245330
}
246331

332+
public static string FormatLoaderException(Exception pluginEx)
333+
{
334+
string sException = "";
335+
sException += string.Format("BIDS Helper encountered an error when Visual Studio started:\r\n{0}\r\n{1}"
336+
, pluginEx.Message
337+
, pluginEx.StackTrace);
338+
339+
Exception innerEx = pluginEx.InnerException;
340+
while (innerEx != null)
341+
{
342+
sException += string.Format("\r\nInner exception:\r\n{0}\r\n{1}"
343+
, innerEx.Message
344+
, innerEx.StackTrace);
345+
innerEx = innerEx.InnerException;
346+
}
347+
348+
ReflectionTypeLoadException ex = pluginEx as ReflectionTypeLoadException;
349+
if (ex == null) ex = pluginEx.InnerException as ReflectionTypeLoadException;
350+
if (ex != null)
351+
{
352+
System.Text.StringBuilder sb = new System.Text.StringBuilder();
353+
foreach (Exception exSub in ex.LoaderExceptions)
354+
{
355+
sb.AppendLine();
356+
sb.AppendLine(exSub.GetType().FullName);
357+
sb.AppendLine(exSub.Message);
358+
sb.AppendLine(exSub.StackTrace);
359+
System.IO.FileNotFoundException exFileNotFound = exSub as System.IO.FileNotFoundException;
360+
if (exFileNotFound != null)
361+
{
362+
if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
363+
{
364+
sb.AppendLine("Fusion Log:");
365+
sb.AppendLine(exFileNotFound.FusionLog);
366+
}
367+
sb.AppendLine(string.Format("Source: {0}", exFileNotFound.Source));
368+
sb.AppendLine(string.Format("TargetSite: {0}", exFileNotFound.TargetSite));
369+
}
370+
sb.AppendLine();
371+
}
372+
sException += sb.ToString();
373+
}
374+
return sException;
375+
}
376+
247377
// private bool SwitchVsixManifest()
248378
// {
249379
//#if SQL2019
@@ -604,6 +734,9 @@ public int OnModeChange(DBGMODE mode)
604734

605735
public static Exception AddInLoadException = null;
606736
private uint debugEventCookie;
737+
public static Version SSISExtensionVersion = null;
738+
public static Version SSASExtensionVersion = null;
739+
public static Version SSRSExtensionVersion = null;
607740

608741
internal System.IServiceProvider ServiceProvider { get { return (System.IServiceProvider)this; } }
609742

Core/Options/BIDSHelperOptionsVersionCheckPage.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ private void BIDSHelperOptionsVersionCheckPage_Load(object sender, EventArgs e)
129129
this.lblLocalVersion.Text += string.Format(CultureInfo.InvariantCulture, " (Debug Build {0:yyyy-MM-dd HH:mm:ss})", buildDateTime);
130130
#endif
131131

132+
this.lblSqlVersion.Text += string.Format("\r\nSSDT Extensions Installed: SSAS ({0}), SSIS ({1}), SSRS ({2})",
133+
(BIDSHelperPackage.SSASExtensionVersion == null ? "N/A" : BIDSHelperPackage.SSASExtensionVersion.ToString()),
134+
(BIDSHelperPackage.SSISExtensionVersion == null ? "N/A" : BIDSHelperPackage.SSISExtensionVersion.ToString()),
135+
(BIDSHelperPackage.SSRSExtensionVersion == null ? "N/A" : BIDSHelperPackage.SSRSExtensionVersion.ToString()));
136+
132137
// First check we have a valid instance, the add-in may be disabled.
133138
if (VersionCheckPlugin.Instance == null)
134139
{

Core/Options/BIDSHelperPreferencesDialogPage.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,18 @@ protected override IWin32Window Window
2222
{
2323
get
2424
{
25-
page = new BIDSHelperPreferencesPage();
26-
page.OptionsPage = this;
27-
page.Initialize();
28-
return page;
25+
try
26+
{
27+
page = new BIDSHelperPreferencesPage();
28+
page.OptionsPage = this;
29+
page.Initialize();
30+
return page;
31+
}
32+
catch (Exception ex)
33+
{
34+
MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace);
35+
return null;
36+
}
2937
}
3038
}
3139

0 commit comments

Comments
 (0)