diff --git a/IntegrationTests.testsettings b/IntegrationTests.testsettings
new file mode 100644
index 0000000..fb61707
--- /dev/null
+++ b/IntegrationTests.testsettings
@@ -0,0 +1,14 @@
+
+
+ This test run configuration uses the VS IDE host type in the test run.
+
+
+
+
+
+
+
diff --git a/UnitTests.testsettings b/UnitTests.testsettings
new file mode 100644
index 0000000..f9cefbd
--- /dev/null
+++ b/UnitTests.testsettings
@@ -0,0 +1,9 @@
+
+
+
+ This test run configuration is used for running the unit tests
+
diff --git a/VSPackageInstall/GlobalSuppressions.cs b/VSPackageInstall/GlobalSuppressions.cs
new file mode 100644
index 0000000..a893f9d
--- /dev/null
+++ b/VSPackageInstall/GlobalSuppressions.cs
@@ -0,0 +1,11 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project. Project-level
+// suppressions either have no target or are given a specific target
+// and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Error List, point to "Suppress Message(s)", and click "In Project
+// Suppression File". You do not need to add suppressions to this
+// file manually.
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")]
diff --git a/VSPackageInstall/Guids.cs b/VSPackageInstall/Guids.cs
new file mode 100644
index 0000000..5d457be
--- /dev/null
+++ b/VSPackageInstall/Guids.cs
@@ -0,0 +1,15 @@
+// Guids.cs
+// MUST match guids.h
+using System;
+
+namespace VitaliiGanzha.VSPackageInstall
+{
+ static class GuidList
+ {
+ public const string guidVSPackageInstallPkgString = "a527a9c1-ec2f-46a0-a6e3-371859c5845b";
+ public const string guidVSPackageInstallCmdSetString = "4fddc919-41be-47b6-ae59-7125c75d1f1e";
+ public const string guidToolWindowPersistanceString = "a6862923-42ae-438f-ac76-7a68be1011e3";
+
+ public static readonly Guid guidVSPackageInstallCmdSet = new Guid(guidVSPackageInstallCmdSetString);
+ };
+}
\ No newline at end of file
diff --git a/VSPackageInstall/Key.snk b/VSPackageInstall/Key.snk
new file mode 100644
index 0000000..6a24fe5
Binary files /dev/null and b/VSPackageInstall/Key.snk differ
diff --git a/VSPackageInstall/MyControl.xaml b/VSPackageInstall/MyControl.xaml
new file mode 100644
index 0000000..5761443
--- /dev/null
+++ b/VSPackageInstall/MyControl.xaml
@@ -0,0 +1,17 @@
+
+
+
+ VS Ding
+
+
+
+
diff --git a/VSPackageInstall/MyControl.xaml.cs b/VSPackageInstall/MyControl.xaml.cs
new file mode 100644
index 0000000..efbb549
--- /dev/null
+++ b/VSPackageInstall/MyControl.xaml.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace VitaliiGanzha.VSPackageInstall
+{
+ ///
+ /// Interaction logic for MyControl.xaml
+ ///
+ public partial class MyControl : UserControl
+ {
+ public MyControl()
+ {
+ InitializeComponent();
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions")]
+ private void button1_Click(object sender, RoutedEventArgs e)
+ {
+ MessageBox.Show(string.Format(System.Globalization.CultureInfo.CurrentUICulture, "We are inside {0}.button1_Click()", this.ToString()),
+ "VS Ding");
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/VSPackageInstall/MyToolWindow.cs b/VSPackageInstall/MyToolWindow.cs
new file mode 100644
index 0000000..db78918
--- /dev/null
+++ b/VSPackageInstall/MyToolWindow.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Windows;
+using System.Runtime.InteropServices;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Shell;
+
+namespace VitaliiGanzha.VSPackageInstall
+{
+ ///
+ /// This class implements the tool window exposed by this package and hosts a user control.
+ ///
+ /// In Visual Studio tool windows are composed of a frame (implemented by the shell) and a pane,
+ /// usually implemented by the package implementer.
+ ///
+ /// This class derives from the ToolWindowPane class provided from the MPF in order to use its
+ /// implementation of the IVsUIElementPane interface.
+ ///
+ [Guid("a6862923-42ae-438f-ac76-7a68be1011e3")]
+ public class MyToolWindow : ToolWindowPane
+ {
+ ///
+ /// Standard constructor for the tool window.
+ ///
+ public MyToolWindow() :
+ base(null)
+ {
+ // Set the window title reading it from the resources.
+ this.Caption = Resources.ToolWindowTitle;
+ // Set the image that will appear on the tab of the window frame
+ // when docked with an other window
+ // The resource ID correspond to the one defined in the resx file
+ // while the Index is the offset in the bitmap strip. Each image in
+ // the strip being 16x16.
+ this.BitmapResourceID = 301;
+ this.BitmapIndex = 1;
+
+ // This is the user control hosted by the tool window; Note that, even if this class implements IDisposable,
+ // we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on
+ // the object returned by the Content property.
+ base.Content = new MyControl();
+ }
+ }
+}
diff --git a/VSPackageInstall/PkgCmdID.cs b/VSPackageInstall/PkgCmdID.cs
new file mode 100644
index 0000000..2498f9e
--- /dev/null
+++ b/VSPackageInstall/PkgCmdID.cs
@@ -0,0 +1,13 @@
+// PkgCmdID.cs
+// MUST match PkgCmdID.h
+using System;
+
+namespace VitaliiGanzha.VSPackageInstall
+{
+ static class PkgCmdIDList
+ {
+ public const uint cmdidVsDing = 0x100;
+ public const uint cmdidVsDingWnd = 0x101;
+
+ };
+}
\ No newline at end of file
diff --git a/VSPackageInstall/Properties/AssemblyInfo.cs b/VSPackageInstall/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..51c3ff4
--- /dev/null
+++ b/VSPackageInstall/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("VSPackageInstall")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Vitalii Ganzha")]
+[assembly: AssemblyProduct("VSPackageInstall")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: CLSCompliant(false)]
+[assembly: NeutralResourcesLanguage("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: InternalsVisibleTo("VSPackageInstall_IntegrationTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004bcbc34c62abe4c7cbb70dd208ebb4958e5f0fa40d49b5cb7745114737e7deba8e9227e32bb0c06fba88912c428184c837e96865ef4f98d7302d5f9f184a93906e2fdd69f9defe190ad7605078c48a780222cd33b3655512d71febdf8bfcf755ccb9037b9369939cd85bcc0b1ef12938bd1b6802f9284e657dd7d386555209b5")]
+[assembly: InternalsVisibleTo("VSPackageInstall_UnitTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004bcbc34c62abe4c7cbb70dd208ebb4958e5f0fa40d49b5cb7745114737e7deba8e9227e32bb0c06fba88912c428184c837e96865ef4f98d7302d5f9f184a93906e2fdd69f9defe190ad7605078c48a780222cd33b3655512d71febdf8bfcf755ccb9037b9369939cd85bcc0b1ef12938bd1b6802f9284e657dd7d386555209b5")]
diff --git a/VSPackageInstall/Resources.Designer.cs b/VSPackageInstall/Resources.Designer.cs
new file mode 100644
index 0000000..2bd9a14
--- /dev/null
+++ b/VSPackageInstall/Resources.Designer.cs
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.42
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace VitaliiGanzha.VSPackageInstall {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VitaliiGanzha.VSPackageInstall.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Can not create tool window..
+ ///
+ internal static string CanNotCreateWindow {
+ get {
+ return ResourceManager.GetString("CanNotCreateWindow", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to My Tool Window.
+ ///
+ internal static string ToolWindowTitle {
+ get {
+ return ResourceManager.GetString("ToolWindowTitle", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/VSPackageInstall/Resources.resx b/VSPackageInstall/Resources.resx
new file mode 100644
index 0000000..c89ac58
--- /dev/null
+++ b/VSPackageInstall/Resources.resx
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Can not create tool window.
+
+
+ VS Ding
+
+
\ No newline at end of file
diff --git a/VSPackageInstall/Resources/Images.png b/VSPackageInstall/Resources/Images.png
new file mode 100644
index 0000000..bf17e6b
Binary files /dev/null and b/VSPackageInstall/Resources/Images.png differ
diff --git a/VSPackageInstall/Resources/Package.ico b/VSPackageInstall/Resources/Package.ico
new file mode 100644
index 0000000..449296f
Binary files /dev/null and b/VSPackageInstall/Resources/Package.ico differ
diff --git a/VSPackageInstall/VSPackage.resx b/VSPackageInstall/VSPackage.resx
new file mode 100644
index 0000000..18a7594
--- /dev/null
+++ b/VSPackageInstall/VSPackage.resx
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ VSPackageInstall
+
+
+ Visual Studio sound notifications
+
+
+ Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Resources\Images.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/VSPackageInstall/VSPackageInstall.csproj b/VSPackageInstall/VSPackageInstall.csproj
new file mode 100644
index 0000000..67a5a9e
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall.csproj
@@ -0,0 +1,193 @@
+
+
+
+ 12.0
+ 12.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ {20191d13-7cc1-4f9b-9cb8-42f22ace4ca6}
+ {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Properties
+ VitaliiGanzha.VSPackageInstall
+ VSPackageInstall
+ True
+ Key.snk
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}
+ 8
+ 0
+ 0
+ primary
+ False
+ False
+
+
+ {26AD1324-4B7C-44BC-84F8-B86AED45729F}
+ 10
+ 0
+ 0
+ primary
+ False
+ False
+
+
+ {1A31287A-4D7D-413E-8E32-3B374931BD89}
+ 8
+ 0
+ 0
+ primary
+ False
+ False
+
+
+ {2CE2370E-D744-4936-A090-3FFFE667B0E1}
+ 9
+ 0
+ 0
+ primary
+ False
+ False
+
+
+ {1CBA492E-7263-47BB-87FE-639000619B15}
+ 8
+ 0
+ 0
+ primary
+ False
+ False
+
+
+ {00020430-0000-0000-C000-000000000046}
+ 2
+ 0
+ 0
+ primary
+ False
+ False
+
+
+
+
+ MyControl.xaml
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ true
+ VSPackage
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+ Menus.ctmenu
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+ true
+
+
+
+
+
diff --git a/VSPackageInstall/VSPackageInstall.vsct b/VSPackageInstall/VSPackageInstall.vsct
new file mode 100644
index 0000000..a1070ce
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall.vsct
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VSPackageInstall/VSPackageInstallPackage.cs b/VSPackageInstall/VSPackageInstallPackage.cs
new file mode 100644
index 0000000..156ffa7
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstallPackage.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.ComponentModel.Design;
+using EnvDTE;
+using EnvDTE80;
+using Microsoft.Win32;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.OLE.Interop;
+using Microsoft.VisualStudio.Shell;
+
+namespace VitaliiGanzha.VSPackageInstall
+{
+ ///
+ /// This is the class that implements the package exposed by this assembly.
+ ///
+ /// 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.
+ ///
+ // This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
+ // a package.
+ [PackageRegistration(UseManagedResourcesOnly = true)]
+ // This attribute is used to register the information needed to show this package
+ // in the Help/About dialog of Visual Studio.
+ [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
+ // This attribute is needed to let the shell know that this package exposes some menus.
+ [ProvideMenuResource("Menus.ctmenu", 1)]
+ // This attribute registers a tool window exposed by this package.
+ [ProvideToolWindow(typeof(MyToolWindow))]
+ [Guid(GuidList.guidVSPackageInstallPkgString)]
+ public sealed class VSPackageInstallPackage : Package
+ {
+ private DTE2 applicationObject;
+ private AddIn addInInstance;
+
+ ///
+ /// Default constructor of the package.
+ /// 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.
+ ///
+ public VSPackageInstallPackage()
+ {
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
+ }
+
+ ///
+ /// This function is called when the user clicks the menu item that shows the
+ /// tool window. See the Initialize method to see how the menu item is associated to
+ /// this function using the OleMenuCommandService service and the MenuCommand class.
+ ///
+ private void ShowToolWindow(object sender, EventArgs e)
+ {
+ // Get the instance number 0 of this tool window. This window is single instance so this instance
+ // is actually the only one.
+ // The last flag is set to true so that if the tool window does not exists it will be created.
+ ToolWindowPane window = this.FindToolWindow(typeof(MyToolWindow), 0, true);
+ if ((null == window) || (null == window.Frame))
+ {
+ throw new NotSupportedException(Resources.CanNotCreateWindow);
+ }
+ IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
+ Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Overridden Package Implementation
+ #region Package Members
+
+ ///
+ /// 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.
+ ///
+ protected override void Initialize()
+ {
+ try
+ {
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
+ base.Initialize();
+
+ // Add our command handlers for menu (commands must exist in the .vsct file)
+ OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+ if (null != mcs)
+ {
+ // Create the command for the menu item.
+ CommandID menuCommandID = new CommandID(GuidList.guidVSPackageInstallCmdSet, (int)PkgCmdIDList.cmdidVsDing);
+ MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+ mcs.AddCommand(menuItem);
+ // Create the command for the tool window
+ CommandID toolwndCommandID = new CommandID(GuidList.guidVSPackageInstallCmdSet, (int)PkgCmdIDList.cmdidVsDingWnd);
+ MenuCommand menuToolWin = new MenuCommand(ShowToolWindow, toolwndCommandID);
+ mcs.AddCommand(menuToolWin);
+ }
+
+ applicationObject = (DTE2)GetService(typeof(DTE));
+ applicationObject.Events.BuildEvents.OnBuildDone += BuildEventsOnOnBuildDone;
+ }
+ catch (Exception e)
+ {
+ File.WriteAllText(@"c:\temp\test.txt", e.Message);
+ }
+
+ }
+
+ private void BuildEventsOnOnBuildDone(vsBuildScope scope, vsBuildAction action)
+ {
+ System.Media.SystemSounds.Asterisk.Play();
+ }
+
+ #endregion
+
+ ///
+ /// This function is the callback used to execute a command when the a menu item is clicked.
+ /// See the Initialize method to see how the menu item is associated to this function using
+ /// the OleMenuCommandService service and the MenuCommand class.
+ ///
+ private void MenuItemCallback(object sender, EventArgs e)
+ {
+ // Show a Message Box to prove we were here
+ IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell));
+ Guid clsid = Guid.Empty;
+ int result;
+ Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
+ 0,
+ ref clsid,
+ "VSPackageInstall",
+ string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.ToString()),
+ string.Empty,
+ 0,
+ OLEMSGBUTTON.OLEMSGBUTTON_OK,
+ OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
+ OLEMSGICON.OLEMSGICON_INFO,
+ 0, // false
+ out result));
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/DialogboxPurger.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/DialogboxPurger.cs
new file mode 100644
index 0000000..9061a9f
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/DialogboxPurger.cs
@@ -0,0 +1,359 @@
+
+namespace Microsoft.VsSDK.IntegrationTestLibrary
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using Microsoft.VisualStudio.Shell.Interop;
+ using Microsoft.VisualStudio.Shell;
+
+ ///
+ /// This class is responsible to close dialog boxes that pop up during different VS Calls
+ ///
+ internal class DialogBoxPurger : IDisposable
+ {
+ ///
+ /// The default number of milliseconds to wait for the threads to signal to terminate.
+ ///
+ private const int DefaultMillisecondsToWait = 3500;
+
+ ///
+ /// Object used for synchronization between thread calls.
+ ///
+ internal static volatile object Mutex = new object();
+
+ ///
+ /// The IVsUIShell. This cannot be queried on the working thread from the service provider. Must be done in the main thread.!!
+ ///
+ private IVsUIShell uiShell;
+
+ ///
+ /// The button to "press" on the dialog.
+ ///
+ private int buttonAction;
+
+ ///
+ /// Thread signales to the calling thread that it is done.
+ ///
+ private bool exitThread = false;
+
+ ///
+ /// Calling thread signales to this thread to die.
+ ///
+ private AutoResetEvent threadDone = new AutoResetEvent(false);
+
+ ///
+ /// The queued thread started.
+ ///
+ private AutoResetEvent threadStarted = new AutoResetEvent(false);
+
+ ///
+ /// The result of the dialogbox closing for all the dialog boxes. That is if there are two of them and one fails this will be false.
+ ///
+ private bool dialogBoxCloseResult = false;
+
+ ///
+ /// The expected text to see on the dialog box. If set the thread will continue finding the dialog box with this text.
+ ///
+ private string expectedDialogBoxText = String.Empty;
+
+ ///
+ /// The number of the same dialog boxes to wait for.
+ /// This is for scenarios when two dialog boxes with the same text are popping up.
+ ///
+ private int numberOfDialogsToWaitFor = 1;
+
+ ///
+ /// Has the object been disposed.
+ ///
+ private bool isDisposed;
+
+ ///
+ /// Overloaded ctor.
+ ///
+ /// The botton to "press" on the dialog box.
+ /// The number of dialog boxes with the same message to wait for. This is the situation when the same action pops up two of the same dialog boxes
+ /// The expected dialog box message to check for.
+ internal DialogBoxPurger(int buttonAction, int numberOfDialogsToWaitFor, string expectedDialogMesssage)
+ {
+ this.buttonAction = buttonAction;
+ this.numberOfDialogsToWaitFor = numberOfDialogsToWaitFor;
+ this.expectedDialogBoxText = expectedDialogMesssage;
+ }
+
+ ///
+ /// Overloaded ctor.
+ ///
+ /// The botton to "press" on the dialog box.
+ /// The number of dialog boxes with the same message to wait for. This is the situation when the same action pops up two of the same dialog boxes
+ internal DialogBoxPurger(int buttonAction, int numberOfDialogsToWaitFor)
+ {
+ this.buttonAction = buttonAction;
+ this.numberOfDialogsToWaitFor = numberOfDialogsToWaitFor;
+ }
+
+ ///
+ /// Overloaded ctor.
+ ///
+ /// The botton to "press" on the dialog box.
+ /// The expected dialog box message to check for.
+ internal DialogBoxPurger(int buttonAction, string expectedDialogMesssage)
+ {
+ this.buttonAction = buttonAction;
+ this.expectedDialogBoxText = expectedDialogMesssage;
+ }
+
+ ///
+ /// Overloaded ctor.
+ ///
+ /// The botton to "press" on the dialog box.
+ internal DialogBoxPurger(int buttonAction)
+ {
+ this.buttonAction = buttonAction;
+ }
+
+ ///
+ #region IDisposable Members
+
+ void IDisposable.Dispose()
+ {
+ if (this.isDisposed)
+ {
+ return;
+ }
+
+ this.WaitForDialogThreadToTerminate();
+
+ this.isDisposed = true;
+ }
+
+ ///
+ /// Spawns a thread that will start listening to dialog boxes.
+ ///
+ internal void Start()
+ {
+ // We ask for the uishell here since we cannot do that on the therad that we will spawn.
+ IVsUIShell uiShell = Package.GetGlobalService(typeof(SVsUIShell)) as IVsUIShell;
+
+ if (uiShell == null)
+ {
+ throw new InvalidOperationException("Could not get the uiShell from the serviceProvider");
+ }
+
+ this.uiShell = uiShell;
+
+ System.Threading.Thread thread = new System.Threading.Thread(new ThreadStart(this.HandleDialogBoxes));
+ thread.Start();
+
+ // We should never deadlock here, hence do not use the lock. Wait to be sure that the thread started.
+ this.threadStarted.WaitOne(3500, false);
+ }
+
+ ///
+ /// Waits for the dialog box close thread to terminate. If the thread does not signal back within millisecondsToWait that it is shutting down,
+ /// then it will tell to the thread to do it.
+ ///
+ internal bool WaitForDialogThreadToTerminate()
+ {
+ return this.WaitForDialogThreadToTerminate(DefaultMillisecondsToWait);
+ }
+
+ ///
+ /// Waits for the dialog box close thread to terminate. If the thread does not signal back within millisecondsToWait that it is shutting down,
+ /// then it will tell to the thread to do it.
+ ///
+ /// The number milliseconds to wait for until the dialog purger thread is signaled to terminate. This is just for safe precaution that we do not hang.
+ /// The result of the dialog boxes closing
+ internal bool WaitForDialogThreadToTerminate(int numberOfMillisecondsToWait)
+ {
+ bool signaled = false;
+
+ // We give millisecondsToWait sec to bring up and close the dialog box.
+ signaled = this.threadDone.WaitOne(numberOfMillisecondsToWait, false);
+
+ // Kill the thread since a timeout occured.
+ if (!signaled)
+ {
+ lock (Mutex)
+ {
+ // Set the exit thread to true. Next time the thread will kill itselfes if it sees
+ this.exitThread = true;
+ }
+
+ // Wait for the thread to finish. We should never deadlock here.
+ this.threadDone.WaitOne();
+ }
+
+ return this.dialogBoxCloseResult;
+ }
+
+ ///
+ /// This is the thread method.
+ ///
+ private void HandleDialogBoxes()
+ {
+ // No synchronization numberOfDialogsToWaitFor since it is readonly
+ IntPtr[] hwnds = new IntPtr[this.numberOfDialogsToWaitFor];
+ bool[] dialogBoxCloseResults = new bool[this.numberOfDialogsToWaitFor];
+
+ try
+ {
+ // Signal that we started
+ lock (Mutex)
+ {
+ this.threadStarted.Set();
+ }
+
+ // The loop will be exited either if a message is send by the caller thread or if we found the dialog. If a message box text is specified the loop will not exit until the dialog is found.
+ bool stayInLoop = true;
+ int dialogBoxesToWaitFor = 1;
+
+ while (stayInLoop)
+ {
+ int hwndIndex = dialogBoxesToWaitFor - 1;
+
+ // We need to lock since the caller might set context to null.
+ lock (Mutex)
+ {
+ if (this.exitThread)
+ {
+ break;
+ }
+
+ // We protect the shell too from reentrency.
+ this.uiShell.GetDialogOwnerHwnd(out hwnds[hwndIndex]);
+
+ }
+
+ if (hwnds[hwndIndex] != IntPtr.Zero)
+ {
+ StringBuilder windowClassName = new StringBuilder(256);
+ NativeMethods.GetClassName(hwnds[hwndIndex], windowClassName, windowClassName.Capacity);
+
+ // The #32770 is the class name of a messagebox dialog.
+ if (windowClassName.ToString().Contains("#32770"))
+ {
+ IntPtr unmanagedMemoryLocation = IntPtr.Zero;
+ string dialogBoxText = String.Empty;
+ try
+ {
+ unmanagedMemoryLocation = Marshal.AllocHGlobal(10 * 1024);
+ NativeMethods.EnumChildWindows(hwnds[hwndIndex], new NativeMethods.CallBack(FindMessageBoxString), unmanagedMemoryLocation);
+ dialogBoxText = Marshal.PtrToStringUni(unmanagedMemoryLocation);
+ }
+ finally
+ {
+ if (unmanagedMemoryLocation != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(unmanagedMemoryLocation);
+ }
+ }
+
+ lock (Mutex)
+ {
+
+ // Since this is running on the main thread be sure that we close the dialog.
+ bool dialogCloseResult = false;
+ if (this.buttonAction != 0)
+ {
+ dialogCloseResult = NativeMethods.EndDialog(hwnds[hwndIndex], this.buttonAction);
+ }
+
+ // Check if we have found the right dialog box.
+ if (String.IsNullOrEmpty(this.expectedDialogBoxText) || (!String.IsNullOrEmpty(dialogBoxText) && String.Compare(this.expectedDialogBoxText, dialogBoxText.Trim(), StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ dialogBoxCloseResults[hwndIndex] = dialogCloseResult;
+ if (dialogBoxesToWaitFor++ >= this.numberOfDialogsToWaitFor)
+ {
+ stayInLoop = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ //Let the main thread run a possible close command.
+ System.Threading.Thread.Sleep(2000);
+
+ foreach (IntPtr hwnd in hwnds)
+ {
+ // At this point the dialog should be closed, if not attempt to close it.
+ if (hwnd != IntPtr.Zero)
+ {
+ NativeMethods.SendMessage(hwnd, NativeMethods.WM_CLOSE, 0, new IntPtr(0));
+ }
+ }
+
+ lock (Mutex)
+ {
+ // Be optimistic.
+ this.dialogBoxCloseResult = true;
+
+ for (int i = 0; i < dialogBoxCloseResults.Length; i++)
+ {
+ if (!dialogBoxCloseResults[i])
+ {
+ this.dialogBoxCloseResult = false;
+ break;
+ }
+ }
+
+ this.threadDone.Set();
+ }
+ }
+ }
+
+ ///
+ /// Finds a messagebox string on a messagebox.
+ ///
+ /// The windows handle of the dialog
+ /// A pointer to the memorylocation the string will be written to
+ /// True if found.
+ private static bool FindMessageBoxString(IntPtr hwnd, IntPtr unmanagedMemoryLocation)
+ {
+ StringBuilder sb = new StringBuilder(512);
+ NativeMethods.GetClassName(hwnd, sb, sb.Capacity);
+
+ if (sb.ToString().ToLower().Contains("static"))
+ {
+ StringBuilder windowText = new StringBuilder(2048);
+ NativeMethods.GetWindowText(hwnd, windowText, windowText.Capacity);
+
+ if (windowText.Length > 0)
+ {
+ IntPtr stringAsPtr = IntPtr.Zero;
+ try
+ {
+ stringAsPtr = Marshal.StringToHGlobalAnsi(windowText.ToString());
+ char[] stringAsArray = windowText.ToString().ToCharArray();
+
+ // Since unicode characters are copied check if we are out of the allocated length.
+ // If not add the end terminating zero.
+ if ((2 * stringAsArray.Length) + 1 < 2048)
+ {
+ Marshal.Copy(stringAsArray, 0, unmanagedMemoryLocation, stringAsArray.Length);
+ Marshal.WriteInt32(unmanagedMemoryLocation, 2 * stringAsArray.Length, 0);
+ }
+ }
+ finally
+ {
+ if (stringAsPtr != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(stringAsPtr);
+ }
+ }
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ #endregion
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/NativeMethods.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/NativeMethods.cs
new file mode 100644
index 0000000..8007567
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/NativeMethods.cs
@@ -0,0 +1,154 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+namespace Microsoft.VsSDK.IntegrationTestLibrary
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using Microsoft.VisualStudio.Shell.Interop;
+
+ ///
+ /// Defines pinvoked utility methods and internal VS Constants
+ ///
+ internal static class NativeMethods
+ {
+ internal delegate bool CallBack(IntPtr hwnd, IntPtr lParam);
+
+ // Declare two overloaded SendMessage functions
+ [DllImport("user32.dll")]
+ internal static extern UInt32 SendMessage(IntPtr hWnd, UInt32 Msg,
+ UInt32 wParam, IntPtr lParam);
+
+ [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern bool PeekMessage([In, Out] ref Microsoft.VisualStudio.OLE.Interop.MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove);
+
+ [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern bool TranslateMessage([In, Out] ref Microsoft.VisualStudio.OLE.Interop.MSG msg);
+
+ [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern int DispatchMessage([In] ref Microsoft.VisualStudio.OLE.Interop.MSG msg);
+
+ [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool attach);
+
+ [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
+
+ [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern uint GetCurrentThreadId();
+
+ [DllImport("user32")]
+ internal static extern int EnumChildWindows(IntPtr hwnd, CallBack x, IntPtr y);
+
+ [DllImport("user32")]
+ internal static extern bool IsWindowVisible(IntPtr hDlg);
+
+ [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
+ internal static extern IntPtr SetFocus(IntPtr hWnd);
+
+ [DllImport("user32")]
+ internal static extern int GetClassName(IntPtr hWnd,
+ StringBuilder className,
+ int stringLength);
+ [DllImport("user32")]
+ internal static extern int GetWindowText(IntPtr hWnd, StringBuilder className, int stringLength);
+
+
+ [DllImport("user32")]
+ internal static extern bool EndDialog(IntPtr hDlg, int result);
+
+ [DllImport("Kernel32")]
+ internal static extern long GetLastError();
+
+ internal const int QS_KEY = 0x0001,
+ QS_MOUSEMOVE = 0x0002,
+ QS_MOUSEBUTTON = 0x0004,
+ QS_POSTMESSAGE = 0x0008,
+ QS_TIMER = 0x0010,
+ QS_PAINT = 0x0020,
+ QS_SENDMESSAGE = 0x0040,
+ QS_HOTKEY = 0x0080,
+ QS_ALLPOSTMESSAGE = 0x0100,
+ QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON,
+ QS_INPUT = QS_MOUSE | QS_KEY,
+ QS_ALLEVENTS = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY,
+ QS_ALLINPUT = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE;
+
+ internal const int Facility_Win32 = 7;
+
+ internal const int WM_CLOSE = 0x0010;
+
+ internal const int
+ S_FALSE = 0x00000001,
+ S_OK = 0x00000000,
+
+ IDOK = 1,
+ IDCANCEL = 2,
+ IDABORT = 3,
+ IDRETRY = 4,
+ IDIGNORE = 5,
+ IDYES = 6,
+ IDNO = 7,
+ IDCLOSE = 8,
+ IDHELP = 9,
+ IDTRYAGAIN = 10,
+ IDCONTINUE = 11;
+
+ internal static long HResultFromWin32(long error)
+ {
+ if (error <= 0)
+ {
+ return error;
+ }
+
+ return ((error & 0x0000FFFF) | (Facility_Win32 << 16) | 0x80000000);
+ }
+
+ ///
+ /// Please use this "approved" method to compare file names.
+ ///
+ public static bool IsSamePath(string file1, string file2)
+ {
+ if (file1 == null || file1.Length == 0)
+ {
+ return (file2 == null || file2.Length == 0);
+ }
+
+ Uri uri1 = null;
+ Uri uri2 = null;
+
+ try
+ {
+ if (!Uri.TryCreate(file1, UriKind.Absolute, out uri1) || !Uri.TryCreate(file2, UriKind.Absolute, out uri2))
+ {
+ return false;
+ }
+
+ if (uri1 != null && uri1.IsFile && uri2 != null && uri2.IsFile)
+ {
+ return 0 == String.Compare(uri1.LocalPath, uri2.LocalPath, StringComparison.OrdinalIgnoreCase);
+ }
+
+ return file1 == file2;
+ }
+ catch (UriFormatException e)
+ {
+ System.Diagnostics.Trace.WriteLine("Exception " + e.Message);
+ }
+
+ return false;
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/Utils.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/Utils.cs
new file mode 100644
index 0000000..1fa9deb
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/IntegrationTest Library/Utils.cs
@@ -0,0 +1,401 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Reflection;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel.Design;
+using System.Runtime.InteropServices;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Shell;
+using EnvDTE;
+using EnvDTE80;
+using Microsoft.Win32;
+using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using Microsoft.VisualStudio;
+
+namespace Microsoft.VsSDK.IntegrationTestLibrary
+{
+ ///
+ ///
+ public class TestUtils
+ {
+
+ #region Methods: Handling embedded resources
+ ///
+ /// Gets the embedded file identified by the resource name, and converts the
+ /// file into a string.
+ ///
+ /// In VS, is DefaultNamespace.FileName?
+ ///
+ public static string GetEmbeddedStringResource(Assembly assembly, string resourceName)
+ {
+ string result = null;
+
+ // Use the .NET procedure for loading a file embedded in the assembly
+ Stream stream = assembly.GetManifestResourceStream(resourceName);
+ if (stream != null)
+ {
+ // Convert bytes to string
+ byte[] fileContentsAsBytes = new byte[stream.Length];
+ stream.Read(fileContentsAsBytes, 0, (int)stream.Length);
+ result = Encoding.Default.GetString(fileContentsAsBytes);
+ }
+ else
+ {
+ // Embedded resource not found - list available resources
+ Debug.WriteLine("Unable to find the embedded resource file '" + resourceName + "'.");
+ Debug.WriteLine(" Available resources:");
+ foreach (string aResourceName in assembly.GetManifestResourceNames())
+ {
+ Debug.WriteLine(" " + aResourceName);
+ }
+ }
+
+ return result;
+ }
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void WriteEmbeddedResourceToFile(Assembly assembly, string embeddedResourceName, string fileName)
+ {
+ // Get file contents
+ string fileContents = GetEmbeddedStringResource(assembly, embeddedResourceName);
+ if (fileContents == null)
+ throw new ApplicationException("Failed to get embedded resource '" + embeddedResourceName + "' from assembly '" + assembly.FullName);
+
+ // Write to file
+ StreamWriter sw = new StreamWriter(fileName);
+ sw.Write(fileContents);
+ sw.Close();
+ }
+
+ ///
+ /// Writes an embedded resource to a file.
+ ///
+ /// The name of the assembly that the embedded resource is defined.
+ /// The name of the embedded resource.
+ /// The file to write the embedded resource's content.
+ public static void WriteEmbeddedResourceToBinaryFile(Assembly assembly, string embeddedResourceName, string fileName)
+ {
+ // Get file contents
+ Stream stream = assembly.GetManifestResourceStream(embeddedResourceName);
+ if (stream == null)
+ throw new InvalidOperationException("Failed to get embedded resource '" + embeddedResourceName + "' from assembly '" + assembly.FullName);
+
+ // Write to file
+ BinaryWriter sw = null;
+ FileStream fs = null;
+ try
+ {
+ byte[] fileContentsAsBytes = new byte[stream.Length];
+ stream.Read(fileContentsAsBytes, 0, (int)stream.Length);
+
+ FileMode mode = FileMode.CreateNew;
+ if (File.Exists(fileName))
+ {
+ mode = FileMode.Truncate;
+ }
+
+ fs = new FileStream(fileName, mode);
+
+ sw = new BinaryWriter(fs);
+ sw.Write(fileContentsAsBytes);
+ }
+ finally
+ {
+ if (fs != null)
+ {
+ fs.Close();
+ }
+ if (sw != null)
+ {
+ sw.Close();
+ }
+ }
+ }
+
+ #endregion
+
+ #region Methods: Handling temporary files and directories
+ ///
+ /// Returns the first available file name on the form
+ /// [baseFileName]i.[extension]
+ /// where [i] starts at 1 and increases until there is an available file name
+ /// in the given directory. Also creates an empty file with that name to mark
+ /// that file as occupied.
+ ///
+ /// Directory that the file should live in.
+ ///
+ /// may be null, in which case the .[extension] part
+ /// is not added.
+ /// Full file name.
+ public static string GetNewFileName(string directory, string baseFileName, string extension)
+ {
+ // Get the new file name
+ string fileName = GetNewFileOrDirectoryNameWithoutCreatingAnything(directory, baseFileName, extension);
+
+ // Create an empty file to mark it as taken
+ StreamWriter sw = new StreamWriter(fileName);
+
+ sw.Write("");
+ sw.Close();
+ return fileName;
+ }
+ ///
+ /// Returns the first available directory name on the form
+ /// [baseDirectoryName]i
+ /// where [i] starts at 1 and increases until there is an available directory name
+ /// in the given directory. Also creates the directory to mark it as occupied.
+ ///
+ /// Directory that the file should live in.
+ ///
+ /// Full directory name.
+ public static string GetNewDirectoryName(string directory, string baseDirectoryName)
+ {
+ // Get the new file name
+ string directoryName = GetNewFileOrDirectoryNameWithoutCreatingAnything(directory, baseDirectoryName, null);
+
+ // Create an empty directory to make it as occupied
+ Directory.CreateDirectory(directoryName);
+
+ return directoryName;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static string GetNewFileOrDirectoryNameWithoutCreatingAnything(string directory, string baseFileName, string extension)
+ {
+ // - get a file name that we can use
+ string fileName;
+ int i = 1;
+
+ string fullFileName = null;
+ while (true)
+ {
+ // construct next file name
+ fileName = baseFileName + i;
+ if (extension != null)
+ fileName += '.' + extension;
+
+ // check if that file exists in the directory
+ fullFileName = Path.Combine(directory, fileName);
+
+ if (!File.Exists(fullFileName) && !Directory.Exists(fullFileName))
+ break;
+ else
+ i++;
+ }
+
+ return fullFileName;
+ }
+ #endregion
+
+ #region Methods: Handling solutions
+ ///
+ /// Closes the currently open solution (if any), and creates a new solution with the given name.
+ ///
+ /// Name of new solution.
+ public void CreateEmptySolution(string directory, string solutionName)
+ {
+ CloseCurrentSolution(__VSSLNSAVEOPTIONS.SLNSAVEOPT_NoSave);
+
+ string solutionDirectory = GetNewDirectoryName(directory, solutionName);
+
+ // Create and force save solution
+ IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution));
+ solutionService.CreateSolution(solutionDirectory, solutionName, (uint)__VSCREATESOLUTIONFLAGS.CSF_SILENT);
+ solutionService.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0);
+ DTE dte = VsIdeTestHostContext.Dte;
+ Assert.AreEqual(solutionName + ".sln", Path.GetFileName(dte.Solution.FileName), "Newly created solution has wrong Filename");
+ }
+
+ public void CloseCurrentSolution(__VSSLNSAVEOPTIONS saveoptions)
+ {
+ // Get solution service
+ IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution));
+
+ // Close already open solution
+ solutionService.CloseSolutionElement((uint)saveoptions, null, 0);
+ }
+
+ public void ForceSaveSolution()
+ {
+ // Get solution service
+ IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution));
+
+ // Force-save the solution
+ solutionService.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, null, 0);
+ }
+
+ ///
+ /// Get current number of open project in solution
+ ///
+ ///
+ public int ProjectCount()
+ {
+ // Get solution service
+ IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution));
+ object projectCount;
+ solutionService.GetProperty((int)__VSPROPID.VSPROPID_ProjectCount, out projectCount);
+ return (int)projectCount;
+ }
+ #endregion
+
+ #region Methods: Handling projects
+ ///
+ /// Creates a project.
+ ///
+ /// Name of new project.
+ /// Name of project template to use
+ /// language
+ /// New project.
+ public void CreateProjectFromTemplate(string projectName, string templateName, string language, bool exclusive)
+ {
+ DTE dte = (DTE)VsIdeTestHostContext.ServiceProvider.GetService(typeof(DTE));
+
+ Solution2 sol = dte.Solution as Solution2;
+ string projectTemplate = sol.GetProjectTemplate(templateName, language);
+
+ // - project name and directory
+ string solutionDirectory = Directory.GetParent(dte.Solution.FullName).FullName;
+ string projectDirectory = GetNewDirectoryName(solutionDirectory, projectName);
+
+ dte.Solution.AddFromTemplate(projectTemplate, projectDirectory, projectName, false);
+ }
+ #endregion
+
+ #region Methods: Handling project items
+ ///
+ /// Create a new item in the project
+ ///
+ /// the parent collection for the new item
+ ///
+ ///
+ ///
+ ///
+ public ProjectItem AddNewItemFromVsTemplate(ProjectItems parent, string templateName, string language, string name)
+ {
+ if (parent == null)
+ throw new ArgumentException("project");
+ if (name == null)
+ throw new ArgumentException("name");
+
+ DTE dte = (DTE)VsIdeTestHostContext.ServiceProvider.GetService(typeof(DTE));
+
+ Solution2 sol = dte.Solution as Solution2;
+
+ string filename = sol.GetProjectItemTemplate(templateName, language);
+
+ parent.AddFromTemplate(filename, name);
+
+ return parent.Item(name);
+ }
+
+ ///
+ /// Save an open document.
+ ///
+ /// for filebased documents this is the full path to the document
+ public void SaveDocument(string documentMoniker)
+ {
+ // Get document cookie and hierarchy for the file
+ IVsRunningDocumentTable runningDocumentTableService = (IVsRunningDocumentTable)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsRunningDocumentTable));
+ uint docCookie;
+ IntPtr docData;
+ IVsHierarchy hierarchy;
+ uint itemId;
+ runningDocumentTableService.FindAndLockDocument(
+ (uint)Microsoft.VisualStudio.Shell.Interop._VSRDTFLAGS.RDT_NoLock,
+ documentMoniker,
+ out hierarchy,
+ out itemId,
+ out docData,
+ out docCookie);
+
+ // Save the document
+ IVsSolution solutionService = (IVsSolution)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution));
+ solutionService.SaveSolutionElement((uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_ForceSave, hierarchy, docCookie);
+ }
+
+ public void CloseInEditorWithoutSaving(string fullFileName)
+ {
+ // Get the RDT service
+ IVsRunningDocumentTable runningDocumentTableService = (IVsRunningDocumentTable)VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsRunningDocumentTable));
+ Assert.IsNotNull(runningDocumentTableService, "Failed to get the Running Document Table Service");
+
+ // Get our document cookie and hierarchy for the file
+ uint docCookie;
+ IntPtr docData;
+ IVsHierarchy hierarchy;
+ uint itemId;
+ runningDocumentTableService.FindAndLockDocument(
+ (uint)Microsoft.VisualStudio.Shell.Interop._VSRDTFLAGS.RDT_NoLock,
+ fullFileName,
+ out hierarchy,
+ out itemId,
+ out docData,
+ out docCookie);
+
+ // Get the SolutionService
+ IVsSolution solutionService = VsIdeTestHostContext.ServiceProvider.GetService(typeof(IVsSolution)) as IVsSolution;
+ Assert.IsNotNull(solutionService, "Failed to get IVsSolution service");
+
+ // Close the document
+ solutionService.CloseSolutionElement(
+ (uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_NoSave,
+ hierarchy,
+ docCookie);
+ }
+ #endregion
+
+ #region Methods: Handling Toolwindows
+ public bool CanFindToolwindow(Guid persistenceGuid)
+ {
+ IVsUIShell uiShellService = VsIdeTestHostContext.ServiceProvider.GetService(typeof(SVsUIShell)) as IVsUIShell;
+ Assert.IsNotNull(uiShellService);
+ IVsWindowFrame windowFrame;
+ int hr = uiShellService.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fFindFirst, ref persistenceGuid, out windowFrame);
+ Assert.IsTrue(hr == VSConstants.S_OK);
+
+ return (windowFrame != null);
+ }
+ #endregion
+
+ #region Methods: Loading packages
+ public IVsPackage LoadPackage(Guid packageGuid)
+ {
+ IVsShell shellService = (IVsShell)VsIdeTestHostContext.ServiceProvider.GetService(typeof(SVsShell));
+ IVsPackage package;
+ shellService.LoadPackage(ref packageGuid, out package);
+ Assert.IsNotNull(package, "Failed to load package");
+ return package;
+ }
+ #endregion
+
+ ///
+ /// Executes a Command (menu item) in the given context
+ ///
+ public void ExecuteCommand(CommandID cmd)
+ {
+ object Customin = null;
+ object Customout = null;
+ string guidString = cmd.Guid.ToString("B").ToUpper();
+ int cmdId = cmd.ID;
+ DTE dte = VsIdeTestHostContext.Dte;
+ dte.Commands.Raise(guidString, cmdId, ref Customin, ref Customout);
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/Key.snk b/VSPackageInstall/VSPackageInstall_IntegrationTests/Key.snk
new file mode 100644
index 0000000..6a24fe5
Binary files /dev/null and b/VSPackageInstall/VSPackageInstall_IntegrationTests/Key.snk differ
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/MenuItemTest.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/MenuItemTest.cs
new file mode 100644
index 0000000..8d22566
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/MenuItemTest.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Globalization;
+using System.ComponentModel.Design;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.OLE.Interop;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VsSDK.IntegrationTestLibrary;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+
+namespace VSPackageInstall_IntegrationTests
+{
+ [TestClass()]
+ public class MenuItemTest
+ {
+ private delegate void ThreadInvoker();
+
+ private TestContext testContextInstance;
+
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get
+ {
+ return testContextInstance;
+ }
+ set
+ {
+ testContextInstance = value;
+ }
+ }
+
+ ///
+ ///A test for lauching the command and closing the associated dialogbox
+ ///
+ [TestMethod()]
+ [HostType("VS IDE")]
+ public void LaunchCommand()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+ CommandID menuItemCmd = new CommandID(VitaliiGanzha.VSPackageInstall.GuidList.guidVSPackageInstallCmdSet, (int)VitaliiGanzha.VSPackageInstall.PkgCmdIDList.cmdidVsDing);
+
+ // Create the DialogBoxListener Thread.
+ string expectedDialogBoxText = string.Format(CultureInfo.CurrentCulture, "{0}\n\nInside {1}.MenuItemCallback()", "VSPackageInstall", "VitaliiGanzha.VSPackageInstall.VSPackageInstallPackage");
+ DialogBoxPurger purger = new DialogBoxPurger(NativeMethods.IDOK, expectedDialogBoxText);
+
+ try
+ {
+ purger.Start();
+
+ TestUtils testUtils = new TestUtils();
+ testUtils.ExecuteCommand(menuItemCmd);
+ }
+ finally
+ {
+ Assert.IsTrue(purger.WaitForDialogThreadToTerminate(), "The dialog box has not shown");
+ }
+ });
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/PackageTest.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/PackageTest.cs
new file mode 100644
index 0000000..62e9689
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/PackageTest.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Shell;
+using EnvDTE;
+
+namespace VSPackageInstall_IntegrationTests
+{
+ ///
+ /// Integration test for package validation
+ ///
+ [TestClass]
+ public class PackageTest
+ {
+ private delegate void ThreadInvoker();
+
+ private TestContext testContextInstance;
+
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get
+ {
+ return testContextInstance;
+ }
+ set
+ {
+ testContextInstance = value;
+ }
+ }
+
+ [TestMethod]
+ [HostType("VS IDE")]
+ public void PackageLoadTest()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+
+ //Get the Shell Service
+ IVsShell shellService = VsIdeTestHostContext.ServiceProvider.GetService(typeof(SVsShell)) as IVsShell;
+ Assert.IsNotNull(shellService);
+
+ //Validate package load
+ IVsPackage package;
+ Guid packageGuid = new Guid(VitaliiGanzha.VSPackageInstall.GuidList.guidVSPackageInstallPkgString);
+ Assert.IsTrue(0 == shellService.LoadPackage(ref packageGuid, out package));
+ Assert.IsNotNull(package, "Package failed to load");
+
+ });
+ }
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/CPPProjectTests.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/CPPProjectTests.cs
new file mode 100644
index 0000000..d146f65
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/CPPProjectTests.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VsSDK.IntegrationTestLibrary;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using EnvDTE;
+using System.IO;
+
+namespace VSPackageInstall_IntegrationTests.IntegrationTests
+{
+ [TestClass]
+ public class CPPProjectTests
+ {
+ #region fields
+ private delegate void ThreadInvoker();
+ private TestContext _testContext;
+ #endregion
+
+ #region properties
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get { return _testContext; }
+ set { _testContext = value; }
+ }
+ #endregion
+
+ #region ctors
+ public CPPProjectTests()
+ {
+ }
+ #endregion
+
+ #region Additional test attributes
+ //
+ // You can use the following additional attributes as you write your tests:
+ //
+ // Use ClassInitialize to run code before running the first test in the class
+ // [ClassInitialize()]
+ // public static void MyClassInitialize(TestContext testContext) { }
+ //
+ // Use ClassCleanup to run code after all tests in a class have run
+ // [ClassCleanup()]
+ // public static void MyClassCleanup() { }
+ //
+ // Use TestInitialize to run code before running each test
+ // [TestInitialize()]
+ // public void MyTestInitialize() { }
+ //
+ // Use TestCleanup to run code after each test has run
+ // [TestCleanup()]
+ // public void MyTestCleanup() { }
+ //
+ #endregion
+
+ [HostType("VS IDE")]
+ [TestMethod]
+ public void CPPWinformsApplication()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+ //Solution and project creation parameters
+ string solutionName = "CPPWinApp";
+ string projectName = "CPPWinApp";
+
+ //Template parameters
+ string projectType = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";
+ string projectTemplateName = Path.Combine("vcNet", "mc++appwiz.vsz");
+
+ string itemTemplateName = "newc++file.cpp";
+ string newFileName = "Test.cpp";
+
+ DTE dte = (DTE)VsIdeTestHostContext.ServiceProvider.GetService(typeof(DTE));
+
+ TestUtils testUtils = new TestUtils();
+
+ testUtils.CreateEmptySolution(TestContext.TestDir, solutionName);
+ Assert.AreEqual(0, testUtils.ProjectCount());
+
+ //Add new CPP Windows application project to existing solution
+ string solutionDirectory = Directory.GetParent(dte.Solution.FullName).FullName;
+ string projectDirectory = TestUtils.GetNewDirectoryName(solutionDirectory, projectName);
+ string projectTemplatePath = Path.Combine(dte.Solution.get_TemplatePath(projectType), projectTemplateName);
+ Assert.IsTrue(File.Exists(projectTemplatePath), string.Format("Could not find template file: {0}", projectTemplatePath));
+ dte.Solution.AddFromTemplate(projectTemplatePath, projectDirectory, projectName, false);
+
+ //Verify that the new project has been added to the solution
+ Assert.AreEqual(1, testUtils.ProjectCount());
+
+ //Get the project
+ Project project = dte.Solution.Item(1);
+ Assert.IsNotNull(project);
+ Assert.IsTrue(string.Compare(project.Name, projectName, StringComparison.InvariantCultureIgnoreCase) == 0);
+
+ //Verify Adding new code file to project
+ string newItemTemplatePath = Path.Combine(dte.Solution.ProjectItemsTemplatePath(projectType), itemTemplateName);
+ Assert.IsTrue(File.Exists(newItemTemplatePath));
+ ProjectItem item = project.ProjectItems.AddFromTemplate(newItemTemplatePath, newFileName);
+ Assert.IsNotNull(item);
+
+ });
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/CSharpProjectTests.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/CSharpProjectTests.cs
new file mode 100644
index 0000000..0d34ad0
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/CSharpProjectTests.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VsSDK.IntegrationTestLibrary;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+
+namespace VSPackageInstall_IntegrationTests.IntegrationTests
+{
+ [TestClass]
+ public class CSharpProjectTests
+ {
+ #region fields
+ private delegate void ThreadInvoker();
+ private TestContext _testContext;
+ #endregion
+
+ #region properties
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get { return _testContext; }
+ set { _testContext = value; }
+ }
+ #endregion
+
+ #region ctors
+ public CSharpProjectTests()
+ {
+ }
+ #endregion
+
+ #region Additional test attributes
+ //
+ // You can use the following additional attributes as you write your tests:
+ //
+ // Use ClassInitialize to run code before running the first test in the class
+ // [ClassInitialize()]
+ // public static void MyClassInitialize(TestContext testContext) { }
+ //
+ // Use ClassCleanup to run code after all tests in a class have run
+ // [ClassCleanup()]
+ // public static void MyClassCleanup() { }
+ //
+ // Use TestInitialize to run code before running each test
+ // [TestInitialize()]
+ // public void MyTestInitialize() { }
+ //
+ // Use TestCleanup to run code after each test has run
+ // [TestCleanup()]
+ // public void MyTestCleanup() { }
+ //
+ #endregion
+
+ [TestMethod]
+ [HostType("VS IDE")]
+ public void WinformsApplication()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+ TestUtils testUtils = new TestUtils();
+
+ testUtils.CreateEmptySolution(TestContext.TestDir, "CSWinApp");
+ Assert.AreEqual(0, testUtils.ProjectCount());
+
+ //Create Winforms application project
+ //TestUtils.CreateProjectFromTemplate("MyWindowsApp", "Windows Application", "CSharp", false);
+ //Assert.AreEqual(1, TestUtils.ProjectCount());
+
+ //TODO Verify that we can debug launch the application
+
+ //TODO Set Break point and verify that will hit
+
+ //TODO Verify Adding new project item to project
+
+ });
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/SolutionTests.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/SolutionTests.cs
new file mode 100644
index 0000000..00e4e51
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/SolutionTests.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using EnvDTE;
+using System.IO;
+using Microsoft.VsSDK.IntegrationTestLibrary;
+
+
+namespace VSPackageInstall_IntegrationTests.IntegrationTests
+{
+ [TestClass]
+ public class SolutionTests
+ {
+ #region fields
+ private delegate void ThreadInvoker();
+ private TestContext _testContext;
+ #endregion
+
+ #region properties
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get { return _testContext; }
+ set { _testContext = value; }
+ }
+ #endregion
+
+
+ #region ctors
+ public SolutionTests()
+ {
+ }
+
+ #endregion
+
+ [TestMethod]
+ [HostType("VS IDE")]
+ public void CreateEmptySolution()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+ TestUtils testUtils = new TestUtils();
+ testUtils.CloseCurrentSolution(__VSSLNSAVEOPTIONS.SLNSAVEOPT_NoSave);
+ testUtils.CreateEmptySolution(TestContext.TestDir, "EmptySolution");
+ });
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/VBProjectTests.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/VBProjectTests.cs
new file mode 100644
index 0000000..d9253df
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/SignOff-Tests/VBProjectTests.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VsSDK.IntegrationTestLibrary;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using EnvDTE;
+
+namespace VSPackageInstall_IntegrationTests.IntegrationTests
+{
+ [TestClass]
+ public class VisualBasicProjectTests
+ {
+ #region fields
+ private delegate void ThreadInvoker();
+ private TestContext _testContext;
+ #endregion
+
+ #region properties
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get { return _testContext; }
+ set { _testContext = value; }
+ }
+ #endregion
+
+ #region ctors
+ public VisualBasicProjectTests()
+ {
+ }
+ #endregion
+
+ #region Additional test attributes
+ //
+ // You can use the following additional attributes as you write your tests:
+ //
+ // Use ClassInitialize to run code before running the first test in the class
+ // [ClassInitialize()]
+ // public static void MyClassInitialize(TestContext testContext) { }
+ //
+ // Use ClassCleanup to run code after all tests in a class have run
+ // [ClassCleanup()]
+ // public static void MyClassCleanup() { }
+ //
+ // Use TestInitialize to run code before running each test
+ // [TestInitialize()]
+ // public void MyTestInitialize() { }
+ //
+ // Use TestCleanup to run code after each test has run
+ // [TestCleanup()]
+ // public void MyTestCleanup() { }
+ //
+ #endregion
+
+ [HostType("VS IDE")]
+ [TestMethod]
+ public void VBWinformsApplication()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+ //Solution and project creation parameters
+ string solutionName = "VBWinApp";
+ string projectName = "VBWinApp";
+
+ //Template parameters
+ string language = "VisualBasic";
+ string projectTemplateName = "WindowsApplication.Zip";
+ string itemTemplateName = "CodeFile.zip";
+ string newFileName = "Test.vb";
+
+ DTE dte = (DTE)VsIdeTestHostContext.ServiceProvider.GetService(typeof(DTE));
+
+ TestUtils testUtils = new TestUtils();
+
+ testUtils.CreateEmptySolution(TestContext.TestDir, solutionName);
+ Assert.AreEqual(0, testUtils.ProjectCount());
+
+ //Add new Windows application project to existing solution
+ testUtils.CreateProjectFromTemplate(projectName, projectTemplateName, language, false);
+
+ //Verify that the new project has been added to the solution
+ Assert.AreEqual(1, testUtils.ProjectCount());
+
+ //Get the project
+ Project project = dte.Solution.Item(1);
+ Assert.IsNotNull(project);
+ Assert.IsTrue(string.Compare(project.Name, projectName, StringComparison.InvariantCultureIgnoreCase) == 0);
+
+ //Verify Adding new code file to project
+ ProjectItem newCodeFileItem = testUtils.AddNewItemFromVsTemplate(project.ProjectItems, itemTemplateName, language, newFileName);
+ Assert.IsNotNull(newCodeFileItem, "Could not create new project item");
+
+ });
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/ToolWindowTest.cs b/VSPackageInstall/VSPackageInstall_IntegrationTests/ToolWindowTest.cs
new file mode 100644
index 0000000..ef5e460
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/ToolWindowTest.cs
@@ -0,0 +1,56 @@
+using System;
+using System.ComponentModel.Design;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.OLE.Interop;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VsSDK.IntegrationTestLibrary;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+
+namespace VSPackageInstall_IntegrationTests
+{
+
+ [TestClass()]
+ public class ToolWindowTest
+ {
+ private delegate void ThreadInvoker();
+
+ private TestContext testContextInstance;
+
+ ///
+ ///Gets or sets the test context which provides
+ ///information about and functionality for the current test run.
+ ///
+ public TestContext TestContext
+ {
+ get
+ {
+ return testContextInstance;
+ }
+ set
+ {
+ testContextInstance = value;
+ }
+ }
+
+ ///
+ ///A test for showing the toolwindow
+ ///
+ [TestMethod()]
+ [HostType("VS IDE")]
+ public void ShowToolWindow()
+ {
+ UIThreadInvoker.Invoke((ThreadInvoker)delegate()
+ {
+ CommandID toolWindowCmd = new CommandID(VitaliiGanzha.VSPackageInstall.GuidList.guidVSPackageInstallCmdSet, (int)VitaliiGanzha.VSPackageInstall.PkgCmdIDList.cmdidVsDingWnd);
+
+ TestUtils testUtils = new TestUtils();
+ testUtils.ExecuteCommand(toolWindowCmd);
+
+ Assert.IsTrue(testUtils.CanFindToolwindow(new Guid(VitaliiGanzha.VSPackageInstall.GuidList.guidToolWindowPersistanceString)));
+
+ });
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_IntegrationTests/VSPackageInstall_IntegrationTests.csproj b/VSPackageInstall/VSPackageInstall_IntegrationTests/VSPackageInstall_IntegrationTests.csproj
new file mode 100644
index 0000000..e6bf3bb
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_IntegrationTests/VSPackageInstall_IntegrationTests.csproj
@@ -0,0 +1,91 @@
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ {77A542CC-52C0-4387-B57B-63AF5F597EA1}
+ Library
+ Properties
+ VSPackageInstall_IntegrationTests
+ VSPackageInstall_IntegrationTests
+ v4.5
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ Key.snk
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}
+ VSPackageInstall
+
+
+
+
+
\ No newline at end of file
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/Key.snk b/VSPackageInstall/VSPackageInstall_UnitTests/Key.snk
new file mode 100644
index 0000000..6a24fe5
Binary files /dev/null and b/VSPackageInstall/VSPackageInstall_UnitTests/Key.snk differ
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/MenuItemTests/MenuItemCallback.cs b/VSPackageInstall/VSPackageInstall_UnitTests/MenuItemTests/MenuItemCallback.cs
new file mode 100644
index 0000000..b5aac3f
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/MenuItemTests/MenuItemCallback.cs
@@ -0,0 +1,80 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Reflection;
+using System.ComponentModel.Design;
+using Microsoft.VsSDK.UnitTestLibrary;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.Shell;
+using VitaliiGanzha.VSPackageInstall;
+
+namespace VSPackageInstall_UnitTests.MenuItemTests
+{
+ [TestClass()]
+ public class MenuItemTest
+ {
+ ///
+ /// Verify that a new menu command object gets added to the OleMenuCommandService.
+ /// This action takes place In the Initialize method of the Package object
+ ///
+ [TestMethod]
+ public void InitializeMenuCommand()
+ {
+ // Create the package
+ IVsPackage package = new VSPackageInstallPackage() as IVsPackage;
+ Assert.IsNotNull(package, "The object does not implement IVsPackage");
+
+ // Create a basic service provider
+ OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();
+
+ // Site the package
+ Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");
+
+ //Verify that the menu command can be found
+ CommandID menuCommandID = new CommandID(VitaliiGanzha.VSPackageInstall.GuidList.guidVSPackageInstallCmdSet, (int)VitaliiGanzha.VSPackageInstall.PkgCmdIDList.cmdidVsDing);
+ System.Reflection.MethodInfo info = typeof(Package).GetMethod("GetService", BindingFlags.Instance | BindingFlags.NonPublic);
+ Assert.IsNotNull(info);
+ OleMenuCommandService mcs = info.Invoke(package, new object[] { (typeof(IMenuCommandService)) }) as OleMenuCommandService;
+ Assert.IsNotNull(mcs.FindCommand(menuCommandID));
+ }
+
+ [TestMethod]
+ public void MenuItemCallback()
+ {
+ // Create the package
+ IVsPackage package = new VSPackageInstallPackage() as IVsPackage;
+ Assert.IsNotNull(package, "The object does not implement IVsPackage");
+
+ // Create a basic service provider
+ OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();
+
+ // Create a UIShell service mock and proffer the service so that it can called from the MenuItemCallback method
+ BaseMock uishellMock = UIShellServiceMock.GetUiShellInstance();
+ serviceProvider.AddService(typeof(SVsUIShell), uishellMock, true);
+
+ // Site the package
+ Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");
+
+ //Invoke private method on package class and observe that the method does not throw
+ System.Reflection.MethodInfo info = package.GetType().GetMethod("MenuItemCallback", BindingFlags.Instance | BindingFlags.NonPublic);
+ Assert.IsNotNull(info, "Failed to get the private method MenuItemCallback throug refplection");
+ info.Invoke(package, new object[] { null, null });
+
+ //Clean up services
+ serviceProvider.RemoveService(typeof(SVsUIShell));
+
+ }
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/MenuItemTests/UIShellServiceMock.cs b/VSPackageInstall/VSPackageInstall_UnitTests/MenuItemTests/UIShellServiceMock.cs
new file mode 100644
index 0000000..2d9b464
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/MenuItemTests/UIShellServiceMock.cs
@@ -0,0 +1,76 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VsSDK.UnitTestLibrary;
+
+namespace VSPackageInstall_UnitTests
+{
+ static class UIShellServiceMock
+ {
+ private static GenericMockFactory uiShellFactory;
+
+ #region UiShell Getters
+ ///
+ /// Returns an IVsUiShell that does not implement any methods
+ ///
+ ///
+ internal static BaseMock GetUiShellInstance()
+ {
+ if (uiShellFactory == null)
+ {
+ uiShellFactory = new GenericMockFactory("UiShell", new Type[] { typeof(IVsUIShell), typeof(IVsUIShellOpenDocument) });
+ }
+ BaseMock uiShell = uiShellFactory.GetInstance();
+ return uiShell;
+ }
+
+ ///
+ /// Get an IVsUiShell that implements SetWaitCursor, SaveDocDataToFile, ShowMessageBox
+ ///
+ /// uishell mock
+ internal static BaseMock GetUiShellInstance0()
+ {
+ BaseMock uiShell = GetUiShellInstance();
+ string name = string.Format("{0}.{1}", typeof(IVsUIShell).FullName, "SetWaitCursor");
+ uiShell.AddMethodCallback(name, new EventHandler(SetWaitCursorCallBack));
+
+ name = string.Format("{0}.{1}", typeof(IVsUIShell).FullName, "SaveDocDataToFile");
+ uiShell.AddMethodCallback(name, new EventHandler(SaveDocDataToFileCallBack));
+
+ name = string.Format("{0}.{1}", typeof(IVsUIShell).FullName, "ShowMessageBox");
+ uiShell.AddMethodCallback(name, new EventHandler(ShowMessageBoxCallBack));
+ return uiShell;
+ }
+ #endregion
+
+ #region Callbacks
+ private static void SetWaitCursorCallBack(object caller, CallbackArgs arguments)
+ {
+ arguments.ReturnValue = VSConstants.S_OK;
+ }
+
+ private static void SaveDocDataToFileCallBack(object caller, CallbackArgs arguments)
+ {
+ arguments.ReturnValue = VSConstants.S_OK;
+ }
+
+ private static void ShowMessageBoxCallBack(object caller, CallbackArgs arguments)
+ {
+ arguments.ReturnValue = VSConstants.S_OK;
+ arguments.SetParameter(10, (int)System.Windows.Forms.DialogResult.Yes);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/MyToolWindow.cs b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/MyToolWindow.cs
new file mode 100644
index 0000000..23e98ae
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/MyToolWindow.cs
@@ -0,0 +1,58 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Reflection;
+using Microsoft.VsSDK.UnitTestLibrary;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using VitaliiGanzha.VSPackageInstall;
+
+namespace VSPackageInstall_UnitTests.MyToolWindowTest
+{
+ ///
+ ///This is a test class for MyToolWindowTest and is intended
+ ///to contain all MyToolWindowTest Unit Tests
+ ///
+ [TestClass()]
+ public class MyToolWindowTest
+ {
+
+ ///
+ ///MyToolWindow Constructor test
+ ///
+ [TestMethod()]
+ public void MyToolWindowConstructorTest()
+ {
+
+ MyToolWindow target = new MyToolWindow();
+ Assert.IsNotNull(target, "Failed to create an instance of MyToolWindow");
+
+ MethodInfo method = target.GetType().GetMethod("get_Content", BindingFlags.Public | BindingFlags.Instance);
+ Assert.IsNotNull(method.Invoke(target, null), "MyControl object was not instantiated");
+
+ }
+
+ ///
+ ///Verify the Content property is valid.
+ ///
+ [TestMethod()]
+ public void WindowPropertyTest()
+ {
+ MyToolWindow target = new MyToolWindow();
+ Assert.IsNotNull(target.Content, "Content property was null");
+ }
+
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/ShowToolWindow.cs b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/ShowToolWindow.cs
new file mode 100644
index 0000000..bc7e9c5
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/ShowToolWindow.cs
@@ -0,0 +1,77 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Reflection;
+using Microsoft.VsSDK.UnitTestLibrary;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VSSDK.Tools.VsIdeTesting;
+using VitaliiGanzha.VSPackageInstall;
+
+namespace VSPackageInstall_UnitTests.MyToolWindowTest
+{
+ [TestClass()]
+ public class ShowToolWindowTest
+ {
+
+ [TestMethod()]
+ public void ValidateToolWindowShown()
+ {
+ IVsPackage package = new VSPackageInstallPackage() as IVsPackage;
+
+ // Create a basic service provider
+ OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();
+
+ //Add uishell service that knows how to create a toolwindow
+ BaseMock uiShellService = UIShellServiceMock.GetUiShellInstanceCreateToolWin();
+ serviceProvider.AddService(typeof(SVsUIShell), uiShellService, false);
+
+ // Site the package
+ Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");
+
+ MethodInfo method = typeof(VSPackageInstallPackage).GetMethod("ShowToolWindow", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ object result = method.Invoke(package, new object[] { null, null });
+ }
+
+ [TestMethod()]
+ [ExpectedException(typeof(InvalidOperationException), "Did not throw expected exception when windowframe object was null")]
+ public void ShowToolwindowNegativeTest()
+ {
+ IVsPackage package = new VSPackageInstallPackage() as IVsPackage;
+
+ // Create a basic service provider
+ OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();
+
+ //Add uishell service that knows how to create a toolwindow
+ BaseMock uiShellService = UIShellServiceMock.GetUiShellInstanceCreateToolWinReturnsNull();
+ serviceProvider.AddService(typeof(SVsUIShell), uiShellService, false);
+
+ // Site the package
+ Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");
+
+ MethodInfo method = typeof(VSPackageInstallPackage).GetMethod("ShowToolWindow", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ //Invoke thows TargetInvocationException, but we want it's inner Exception thrown by ShowToolWindow, InvalidOperationException.
+ try
+ {
+ object result = method.Invoke(package, new object[] { null, null });
+ }
+ catch (Exception e)
+ {
+ throw e.InnerException;
+ }
+ }
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/UIShellServiceMock.cs b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/UIShellServiceMock.cs
new file mode 100644
index 0000000..404dfb6
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/UIShellServiceMock.cs
@@ -0,0 +1,84 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VsSDK.UnitTestLibrary;
+
+namespace VSPackageInstall_UnitTests.MyToolWindowTest
+{
+ static class UIShellServiceMock
+ {
+ private static GenericMockFactory uiShellFactory;
+
+ #region UiShell Getters
+ ///
+ /// Returns an IVsUiShell that does not implement any methods
+ ///
+ ///
+ internal static BaseMock GetUiShellInstance()
+ {
+ if (uiShellFactory == null)
+ {
+ uiShellFactory = new GenericMockFactory("UiShell", new Type[] { typeof(IVsUIShell), typeof(IVsUIShellOpenDocument) });
+ }
+ BaseMock uiShell = uiShellFactory.GetInstance();
+ return uiShell;
+ }
+
+ ///
+ /// Get an IVsUiShell that implement CreateToolWindow
+ ///
+ /// uishell mock
+ internal static BaseMock GetUiShellInstanceCreateToolWin()
+ {
+ BaseMock uiShell = GetUiShellInstance();
+ string name = string.Format("{0}.{1}", typeof(IVsUIShell).FullName, "CreateToolWindow");
+ uiShell.AddMethodCallback(name, new EventHandler(CreateToolWindowCallBack));
+
+ return uiShell;
+ }
+
+ ///
+ /// Get an IVsUiShell that implement CreateToolWindow (negative test)
+ ///
+ /// uishell mock
+ internal static BaseMock GetUiShellInstanceCreateToolWinReturnsNull()
+ {
+ BaseMock uiShell = GetUiShellInstance();
+ string name = string.Format("{0}.{1}", typeof(IVsUIShell).FullName, "CreateToolWindow");
+ uiShell.AddMethodCallback(name, new EventHandler(CreateToolWindowNegativeTestCallBack));
+
+ return uiShell;
+ }
+ #endregion
+
+ #region Callbacks
+ private static void CreateToolWindowCallBack(object caller, CallbackArgs arguments)
+ {
+ arguments.ReturnValue = VSConstants.S_OK;
+
+ // Create the output mock object for the frame
+ IVsWindowFrame frame = WindowFrameMock.GetBaseFrame();
+ arguments.SetParameter(9, frame);
+ }
+
+ private static void CreateToolWindowNegativeTestCallBack(object caller, CallbackArgs arguments)
+ {
+ arguments.ReturnValue = VSConstants.S_OK;
+
+ //set the windowframe object to null
+ arguments.SetParameter(9, null);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/WindowFrameMock.cs b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/WindowFrameMock.cs
new file mode 100644
index 0000000..90d190c
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/MyToolWindowTest/WindowFrameMock.cs
@@ -0,0 +1,39 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.VsSDK.UnitTestLibrary;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.Shell.Interop;
+
+namespace VSPackageInstall_UnitTests.MyToolWindowTest
+{
+ class WindowFrameMock
+ {
+ const string propertiesName = "properties";
+
+ private static GenericMockFactory frameFactory = null;
+
+ ///
+ /// Return a IVsWindowFrame without any special implementation
+ ///
+ ///
+ internal static IVsWindowFrame GetBaseFrame()
+ {
+ if (frameFactory == null)
+ frameFactory = new GenericMockFactory("WindowFrame", new Type[] { typeof(IVsWindowFrame), typeof(IVsWindowFrame2) });
+ IVsWindowFrame frame = (IVsWindowFrame)frameFactory.GetInstance();
+ return frame;
+ }
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/PackageTest.cs b/VSPackageInstall/VSPackageInstall_UnitTests/PackageTest.cs
new file mode 100644
index 0000000..bcf1b0a
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/PackageTest.cs
@@ -0,0 +1,56 @@
+/***************************************************************************
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+This code is licensed under the Visual Studio SDK license terms.
+THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+***************************************************************************/
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Reflection;
+using Microsoft.VsSDK.UnitTestLibrary;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using VitaliiGanzha.VSPackageInstall;
+
+namespace VSPackageInstall_UnitTests
+{
+ [TestClass()]
+ public class PackageTest
+ {
+ [TestMethod()]
+ public void CreateInstance()
+ {
+ VSPackageInstallPackage package = new VSPackageInstallPackage();
+ }
+
+ [TestMethod()]
+ public void IsIVsPackage()
+ {
+ VSPackageInstallPackage package = new VSPackageInstallPackage();
+ Assert.IsNotNull(package as IVsPackage, "The object does not implement IVsPackage");
+ }
+
+ [TestMethod()]
+ public void SetSite()
+ {
+ // Create the package
+ IVsPackage package = new VSPackageInstallPackage() as IVsPackage;
+ Assert.IsNotNull(package, "The object does not implement IVsPackage");
+
+ // Create a basic service provider
+ OleServiceProvider serviceProvider = OleServiceProvider.CreateOleServiceProviderWithBasicServices();
+
+ // Site the package
+ Assert.AreEqual(0, package.SetSite(serviceProvider), "SetSite did not return S_OK");
+
+ // Unsite the package
+ Assert.AreEqual(0, package.SetSite(null), "SetSite(null) did not return S_OK");
+ }
+ }
+}
diff --git a/VSPackageInstall/VSPackageInstall_UnitTests/VSPackageInstall_UnitTests.csproj b/VSPackageInstall/VSPackageInstall_UnitTests/VSPackageInstall_UnitTests.csproj
new file mode 100644
index 0000000..76429a2
--- /dev/null
+++ b/VSPackageInstall/VSPackageInstall_UnitTests/VSPackageInstall_UnitTests.csproj
@@ -0,0 +1,84 @@
+
+
+
+ Debug
+ AnyCPU
+ 2.0
+ {E620FC0C-6208-4216-9899-47DF43578E4C}
+ Library
+ Properties
+ VSPackageInstall_UnitTests
+ VSPackageInstall_UnitTests
+ v4.5
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ Key.snk
+
+
+ true
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}
+ VSPackageInstall
+
+
+
+
\ No newline at end of file
diff --git a/VSPackageInstall/source.extension.vsixmanifest b/VSPackageInstall/source.extension.vsixmanifest
new file mode 100644
index 0000000..94e6d18
--- /dev/null
+++ b/VSPackageInstall/source.extension.vsixmanifest
@@ -0,0 +1,18 @@
+
+
+
+
+ VSPackageInstall
+ Visual Studio sound notifications
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VsDingExtension.sln b/VsDingExtension.sln
new file mode 100644
index 0000000..8d4d4f1
--- /dev/null
+++ b/VsDingExtension.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VsDingExtension", "VsDingExtension\VsDingExtension.csproj", "{54C786E5-FD14-4036-92AE-E9F25B71534B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackageInstall", "VSPackageInstall\VSPackageInstall.csproj", "{20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackageInstall_IntegrationTests", "VSPackageInstall\VSPackageInstall_IntegrationTests\VSPackageInstall_IntegrationTests.csproj", "{77A542CC-52C0-4387-B57B-63AF5F597EA1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5BD9D4DB-8683-4698-8D24-01EE7306F73A}"
+ ProjectSection(SolutionItems) = preProject
+ IntegrationTests.testsettings = IntegrationTests.testsettings
+ UnitTests.testsettings = UnitTests.testsettings
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackageInstall_UnitTests", "VSPackageInstall\VSPackageInstall_UnitTests\VSPackageInstall_UnitTests.csproj", "{E620FC0C-6208-4216-9899-47DF43578E4C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {54C786E5-FD14-4036-92AE-E9F25B71534B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {54C786E5-FD14-4036-92AE-E9F25B71534B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {54C786E5-FD14-4036-92AE-E9F25B71534B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {54C786E5-FD14-4036-92AE-E9F25B71534B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {20191D13-7CC1-4F9B-9CB8-42F22ACE4CA6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77A542CC-52C0-4387-B57B-63AF5F597EA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77A542CC-52C0-4387-B57B-63AF5F597EA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77A542CC-52C0-4387-B57B-63AF5F597EA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77A542CC-52C0-4387-B57B-63AF5F597EA1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E620FC0C-6208-4216-9899-47DF43578E4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E620FC0C-6208-4216-9899-47DF43578E4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E620FC0C-6208-4216-9899-47DF43578E4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E620FC0C-6208-4216-9899-47DF43578E4C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal