-
Notifications
You must be signed in to change notification settings - Fork 24
/
BidsHelperPackage.cs
406 lines (346 loc) · 18.3 KB
/
BidsHelperPackage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
//------------------------------------------------------------------------------
// <copyright file="BidsHelperPackage.cs" company="Company">
// Copyright (c) Company. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Reflection;
using BIDSHelper.Core;
using BIDSHelper.Core.VsIntegration;
using System.Linq;
using Microsoft.VisualStudio;
using BIDSHelper.Core.Logger;
namespace BIDSHelper
{
public enum enumIDEMode
{
Design = 1,
Debug = 2,
Run = 3
}
/// <summary>
/// This is the class that implements the package exposed by this assembly.
/// </summary>
/// <remarks>
/// <para>
/// The minimum requirement for a class to be considered a valid package for Visual Studio
/// is to implement the IVsPackage interface and register itself with the shell.
/// This package uses the helper classes defined inside the Managed Package Framework (MPF)
/// to do it: it derives from the Package class that provides the implementation of the
/// IVsPackage interface and uses the registration attributes defined in the framework to
/// register itself and its components with the shell. These attributes tell the pkgdef creation
/// utility what data to put into .pkgdef file.
/// </para>
/// <para>
/// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
/// </para>
/// </remarks>
[ProvideAutoLoad("f1536ef8-92ec-443c-9ed7-fdadf150da82")]
//[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", VersionInfo.Version, IconResourceID = 400)] // Info on this package for Help/About
[Guid(BIDSHelperPackage.PackageGuidString)]
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
[ProvideMenuResource("Menus.ctmenu", 1)]
[ProvideOptionPage(typeof(BIDSHelperOptionsFeatures), "BIDS Helper", "Features", 0, 0, true)]
[ProvideOptionPage(typeof(BIDSHelperPreferencesDialogPage), "BIDS Helper", "Preferences", 0, 0, true)]
[ProvideOptionPage(typeof(BIDSHelperOptionsVersion), "BIDS Helper", "Version", 0, 0, true)]
public sealed class BIDSHelperPackage : Package, IVsDebuggerEvents
{
/// <summary>
/// BidsHelperPackage GUID string.
/// </summary>
public const string PackageGuidString = "d3474f10-475f-4a9d-84f6-85bc892ad3b6";
public const string REGISTRY_BASE_PATH = "SOFTWARE\\BIDS Helper";
private static System.Collections.Generic.Dictionary<string, BIDSHelperPluginBase> plugins = new System.Collections.Generic.Dictionary<string, BIDSHelperPluginBase>();
private enumIDEMode _ideMode = enumIDEMode.Design;
/// <summary>
/// Initializes a new instance of the <see cref="BidsHelperPackage"/> class.
/// </summary>
public BIDSHelperPackage()
{
// Inside this method you can place any initialization code that does not require
// any Visual Studio service because at this point the package object is created but
// not sited yet inside Visual Studio environment. The place to do all the other
// initialization is the Initialize method.
}
#region Package Members
/// <summary>
/// Initialization of the package; this method is called right after the package is sited, so this is the place
/// where you can put all the initialization code that rely on services provided by VisualStudio.
/// </summary>
protected override void Initialize()
{
bool bQuitting = false;
base.Initialize();
#if DEBUG
Log = new Core.Logger.OutputLogger(this);
Log.LogLevel = LogLevels.Debug;
#else
Log = new Core.Logger.NullLogger();
Log.LogLevel = LogLevels.Warning;
#endif
Log.Debug("BIDSHelper Package Initialize Starting");
string sAddInTypeName = string.Empty;
try
{
StatusBar = new Core.VsIntegration.StatusBar(this);
StatusBar.Text = "Loading BIDSHelper (" + this.GetType().Assembly.GetName().Version.ToString() + ")...";
VsShell = (IVsShell)this.GetService(typeof(SVsShell));
DTE2 = this.GetService(typeof(Microsoft.VisualStudio.Shell.Interop.SDTE)) as EnvDTE80.DTE2;
DebuggerService.AdviseDebuggerEvents(this, out debugEventCookie);
if (SwitchVsixManifest())
{
bQuitting = true;
RestartVisualStudio();
return;
}
foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
{
if (//typeof(IBIDSHelperPlugin).IsAssignableFrom(t.GetType())
t.GetInterfaces().Contains(typeof(IBIDSHelperPlugin))
&& (!object.ReferenceEquals(t, typeof(IBIDSHelperPlugin)))
&& (!t.IsAbstract))
{
sAddInTypeName = t.Name;
Log.Verbose(string.Format("Loading Plugin: {0}", sAddInTypeName));
BIDSHelperPluginBase feature;
Type[] @params = { typeof(BIDSHelperPackage) };
System.Reflection.ConstructorInfo con;
con = t.GetConstructor(@params);
if (con == null)
{
System.Windows.Forms.MessageBox.Show("Problem loading type " + t.Name + ". No constructor found.");
continue;
}
feature = (BIDSHelperPluginBase)con.Invoke(new object[] { this });
Plugins.Add(feature.FullName, feature);
}
}
#if DENALI
//handle assembly reference problems when the compiled reference doesn't exist in that version of Visual Studio
//doesn't appear to be needed for VS2013
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
#endif
}
catch (Exception ex)
{
//don't show a popup anymore since this exception is viewable in the Version dialog in the Tools menu
if (string.IsNullOrEmpty(sAddInTypeName))
{
AddInLoadException = ex;
Log.Exception("Problem loading BIDS Helper", ex);
//System.Windows.Forms.MessageBox.Show("Problem loading BIDS Helper: " + ex.Message + "\r\n" + ex.StackTrace);
}
else
{
AddInLoadException = new Exception("Problem loading BIDS Helper. Problem type was " + sAddInTypeName + ": " + ex.Message + "\r\n" + ex.StackTrace, ex);
Log.Exception("Problem loading BIDS Helper. Problem type was " + sAddInTypeName , ex);
//System.Windows.Forms.MessageBox.Show("Problem loading BIDS Helper. Problem type was " + sAddInTypeName + ": " + ex.Message + "\r\n" + ex.StackTrace);
}
}
finally
{
if (!bQuitting)
StatusBar.Clear();
}
}
private bool SwitchVsixManifest()
{
#if SQL2017
string sVersion = VersionInfo.SqlServerVersion.ToString();
if (sVersion.StartsWith("13.")) //this DLL is for SQL 2017 but you have SSDT for SQL2016 installed
{
string sFolder = System.IO.Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName;
string sManifestPath = sFolder + "\\extension.vsixmanifest";
string sBackupManifestPath = sFolder + "\\extension2017.vsixmanifest";
string sOtherManifestPath = sFolder + "\\extension2016.vsixmanifest";
string sPkgdef2017Path = sFolder + "\\BidsHelper2017.pkgdef";
string sPkgdef2017BackupPath = sFolder + "\\BidsHelper2017.pkgdef.bak";
string sPkgdef2016Path = sFolder + "\\BidsHelper2016.pkgdef";
string sPkgdef2016BackupPath = sFolder + "\\BidsHelper2016.pkgdef.bak";
if (System.IO.File.Exists(sOtherManifestPath) && System.IO.File.Exists(sPkgdef2016BackupPath) && System.IO.File.Exists(sPkgdef2017Path))
{
//backup the current SQL2017 manifest
System.IO.File.Copy(sManifestPath, sBackupManifestPath, true);
//copy SQL2016 manifest over the current manifest
System.IO.File.Copy(sOtherManifestPath, sManifestPath, true);
if (System.IO.File.Exists(sPkgdef2016Path))
System.IO.File.Delete(sPkgdef2016BackupPath);
else
System.IO.File.Move(sPkgdef2016BackupPath, sPkgdef2016Path);
if (System.IO.File.Exists(sPkgdef2017BackupPath))
System.IO.File.Delete(sPkgdef2017Path);
else
System.IO.File.Move(sPkgdef2017Path, sPkgdef2017BackupPath);
System.Windows.Forms.MessageBox.Show("You have SSDT for SQL Server " + VersionInfo.SqlServerFriendlyVersion + " installed. Please restart Visual Studio so BIDS Helper can reconfigure itself to work properly with that version of SSDT.", "BIDS Helper");
return true;
}
else
{
throw new Exception("You have SSDT for SQL Server " + VersionInfo.SqlServerFriendlyVersion + " installed but we couldn't find BIDS Helper 2016 files!");
}
}
#elif SQL2016
string sVersion = VersionInfo.SqlServerVersion.ToString();
if (sVersion.StartsWith("14.")) //this DLL is for SQL 2016 but you have SSDT for SQL2017 installed
{
string sFolder = System.IO.Directory.GetParent(System.IO.Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName).FullName;
string sManifestPath = sFolder + "\\extension.vsixmanifest";
string sBackupManifestPath = sFolder + "\\extension2016.vsixmanifest";
string sOtherManifestPath = sFolder + "\\extension2017.vsixmanifest";
string sPkgdef2017Path = sFolder + "\\BidsHelper2017.pkgdef";
string sPkgdef2017BackupPath = sFolder + "\\BidsHelper2017.pkgdef.bak";
string sPkgdef2016Path = sFolder + "\\BidsHelper2016.pkgdef";
string sPkgdef2016BackupPath = sFolder + "\\BidsHelper2016.pkgdef.bak";
if (System.IO.File.Exists(sOtherManifestPath) && System.IO.File.Exists(sPkgdef2017BackupPath) && System.IO.File.Exists(sPkgdef2016Path))
{
//backup the current SQL2016 manifest
System.IO.File.Copy(sManifestPath, sBackupManifestPath, true);
//copy SQL2017 manifest over the current manifest
System.IO.File.Copy(sOtherManifestPath, sManifestPath, true);
if (System.IO.File.Exists(sPkgdef2017Path))
System.IO.File.Delete(sPkgdef2017BackupPath);
else
System.IO.File.Move(sPkgdef2017BackupPath, sPkgdef2017Path);
if (System.IO.File.Exists(sPkgdef2016BackupPath))
System.IO.File.Delete(sPkgdef2016Path);
else
System.IO.File.Move(sPkgdef2016Path, sPkgdef2016BackupPath);
System.Windows.Forms.MessageBox.Show("You have SSDT for SQL Server " + VersionInfo.SqlServerFriendlyVersion + " installed. Please restart Visual Studio so BIDS Helper can reconfigure itself to work properly with that version of SSDT.", "BIDS Helper");
return true;
}
else
{
throw new Exception("You have SSDT for SQL Server " + VersionInfo.SqlServerFriendlyVersion + " installed but we couldn't find BIDS Helper 2017 files!");
}
}
#endif
return false;
}
private void RestartVisualStudio()
{
System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
System.Diagnostics.Process newProcess = new System.Diagnostics.Process();
newProcess.StartInfo = new System.Diagnostics.ProcessStartInfo {
FileName = currentProcess.MainModule.FileName,
ErrorDialog = true,
UseShellExecute = true,
Arguments = DTE2.CommandLineArguments
};
newProcess.Start();
EnvDTE.Command command = DTE2.Commands.Item("File.Exit", -1);
if ((command != null) && command.IsAvailable)
{
DTE2.ExecuteCommand("File.Exit", "");
}
else
{
DTE2.Quit();
}
}
#if DENALI
//this isn't necessary in VS2013 apparently
System.Reflection.Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
System.Diagnostics.Debug.WriteLine("AssemblyResolve: " + args.Name);
if (args.Name.StartsWith("Microsoft.AnalysisServices.VSHost,"))
{
//this occurs in SSDTBI from SQL2012 in VS2012... apparently they added a .11 to the end of the assembly name
return Assembly.Load("Microsoft.AnalysisServices.VSHost.11, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91");
}
else if (args.Name.StartsWith("Microsoft.AnalysisServices.MPFProjectBase,"))
{
//this occurs in SSDTBI from SQL2012 in VS2012... apparently they added a .11 to the end of the assembly name
return Assembly.Load("Microsoft.AnalysisServices.MPFProjectBase.11, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91");
}
else
{
return null;
}
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Problem during AssemblyResolve in BIDS Helper:\r\n" + ex.Message + "\r\n" + ex.StackTrace, "BIDS Helper");
return null;
}
}
#endif
public int OnModeChange(DBGMODE mode)
{
mode = mode & ~DBGMODE.DBGMODE_EncMask;
switch (mode)
{
case DBGMODE.DBGMODE_Design:
_ideMode = enumIDEMode.Design;
break;
case DBGMODE.DBGMODE_Break:
_ideMode = enumIDEMode.Debug;
break;
case DBGMODE.DBGMODE_Run:
_ideMode = enumIDEMode.Run;
break;
}
IdeModeChanged?.Invoke(this, _ideMode);
return VSConstants.S_OK;
}
public event EventHandler<enumIDEMode> IdeModeChanged;
public static Exception AddInLoadException = null;
private uint debugEventCookie;
internal System.IServiceProvider ServiceProvider { get { return (System.IServiceProvider)this; } }
internal IVsDebugger DebuggerService
{ get { return (IVsDebugger)ServiceProvider.GetService(typeof(SVsShellDebugger)); } }
public static string PluginRegistryPath(Type t)
{
return RegistryBasePath + "\\" + t.Name;
}
public static string RegistryBasePath
{
get { return REGISTRY_BASE_PATH; }
}
public static System.Collections.Generic.Dictionary<string, BIDSHelperPluginBase> Plugins
{
get { return plugins; }
}
public StatusBar StatusBar { get; private set; }
public EnvDTE80.DTE2 DTE2 { get; private set; }
public IVsShell VsShell { get; private set; }
public enumIDEMode IdeMode { get { return _ideMode; } }
#endregion
public ILog Log { get; private set; }
public void OutputString(string text)
{
const int VISIBLE = 1;
const int DO_NOT_CLEAR_WITH_SOLUTION = 0;
Guid guidBidsHelperDebugPane = new Guid("50C4E395-4E87-48BC-9BAC-7C4CD065F6E8");
Guid guidPane = guidBidsHelperDebugPane;
IVsOutputWindow outputWindow;
IVsOutputWindowPane outputWindowPane = null;
int hr;
// Get the output window
outputWindow = base.GetService(typeof(SVsOutputWindow)) as IVsOutputWindow;
// The General pane is not created by default. We must force its creation
//if (guidPane == Microsoft.VisualStudio.VSConstants.OutputWindowPaneGuid.GeneralPane_guid)
//{
hr = outputWindow.CreatePane(guidPane, "BIDS Helper", VISIBLE, DO_NOT_CLEAR_WITH_SOLUTION);
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);
//}
// Get the pane
hr = outputWindow.GetPane(guidPane, out outputWindowPane);
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);
// Output the text
if (outputWindowPane != null)
{
outputWindowPane.Activate();
outputWindowPane.OutputString(text);
}
}
}
}