diff --git a/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest b/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest
index 16efffb82..e07d7e9df 100644
--- a/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest
+++ b/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest
@@ -1,34 +1,34 @@
-
-
- Google Test Adapter
- Adds support for the C++ unit testing framework Google Tests.
- https://github.com/csoltenborn/GoogleTestAdapter
- LICENSE.txt
- Resources\Icons\Icon.ico
- Resources\Preview.png
- Unit Test, C++, Google Test, GoogleTest, GTest, Test Explorer, Testing
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Google Test Adapter
+ Adds support for the C++ unit testing framework Google Tests.
+ https://github.com/csoltenborn/GoogleTestAdapter
+ LICENSE.txt
+ Resources\Icons\Icon.ico
+ Resources\Preview.png
+ Unit Test, C++, Google Test, GoogleTest, GTest, Test Explorer, Testing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs
new file mode 100644
index 000000000..f5b0b9a80
--- /dev/null
+++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs
@@ -0,0 +1,192 @@
+//------------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.VisualStudio.AsyncPackageHelpers {
+
+ using System;
+ using System.Globalization;
+ using System.IO;
+ using System.ComponentModel;
+ using System.ComponentModel.Design;
+ using Microsoft.VisualStudio.Shell;
+ using Microsoft.VisualStudio.Shell.Interop;
+
+ ///
+ /// This attribute is defined on a package to get it to be registered. It
+ /// is internal because packages are meant to be registered, so it is
+ /// implicit just by having a package in the assembly.
+ ///
+ [AttributeUsage(AttributeTargets.Class, Inherited=true, AllowMultiple=false)]
+ public sealed class AsyncPackageRegistrationAttribute : RegistrationAttribute
+ {
+ private RegistrationMethod registrationMethod = RegistrationMethod.Default;
+ private bool useManagedResources = false;
+ private bool allowsBackgroundLoad = false;
+ private string satellitePath = null;
+
+ ///
+ /// Select between specifying the Codebase entry or the Assembly entry in the registry.
+ /// This can be overriden during registration
+ ///
+ public RegistrationMethod RegisterUsing
+ {
+ get
+ {
+ return registrationMethod;
+ }
+ set
+ {
+ registrationMethod = value;
+ }
+ }
+
+ ///
+ /// For managed resources, there should not be a native ui dll registered.
+ ///
+ public bool UseManagedResourcesOnly
+ {
+ get { return useManagedResources; }
+ set { useManagedResources = value; }
+ }
+
+ ///
+ /// Package is safe to load on a background thread.
+ ///
+ public bool AllowsBackgroundLoading
+ {
+ get { return allowsBackgroundLoad; }
+ set { allowsBackgroundLoad = value; }
+ }
+
+ ///
+ /// To specify a resource dll located in a different location then the default,
+ /// set this property. This can be useful if your package is installed in the GAC.
+ /// If this is not set, the directory where the package is located will be use.
+ ///
+ /// Note that the dll should be located at the following path:
+ /// SatellitePath\lcid\PackageDllNameUI.dll
+ ///
+ public string SatellitePath
+ {
+ get { return satellitePath; }
+ set { satellitePath = value; }
+ }
+
+ private string RegKeyName(RegistrationContext context)
+ {
+ return String.Format(CultureInfo.InvariantCulture, "Packages\\{0}", context.ComponentType.GUID.ToString("B"));
+ }
+
+ ///
+ /// Called to register this attribute with the given context. The context
+ /// contains the location where the registration information should be placed.
+ /// it also contains such as the type being registered, and path information.
+ ///
+ /// This method is called both for registration and unregistration. The difference is
+ /// that unregistering just uses a hive that reverses the changes applied to it.
+ ///
+ ///
+ /// Contains the location where the registration information should be placed.
+ /// It also contains other information such as the type being registered
+ /// and path of the assembly.
+ ///
+ public override void Register(RegistrationContext context) {
+ Type t = context.ComponentType;
+
+ Key packageKey = null;
+ try
+ {
+ packageKey = context.CreateKey(RegKeyName(context));
+
+ //use a friendly description if it exists.
+ DescriptionAttribute attr = TypeDescriptor.GetAttributes(t)[typeof(DescriptionAttribute)] as DescriptionAttribute;
+ if (attr != null && !String.IsNullOrEmpty(attr.Description)) {
+ packageKey.SetValue(string.Empty, attr.Description);
+ }
+ else {
+ packageKey.SetValue(string.Empty, t.Name);
+ }
+
+ packageKey.SetValue("InprocServer32", context.InprocServerPath);
+ packageKey.SetValue("Class", t.FullName);
+
+ // If specified on the command line, let the command line option override
+ if (context.RegistrationMethod != RegistrationMethod.Default)
+ {
+ registrationMethod = context.RegistrationMethod;
+ }
+
+ // Select registration method
+ switch (registrationMethod)
+ {
+ case RegistrationMethod.Assembly:
+ case RegistrationMethod.Default:
+ packageKey.SetValue("Assembly", t.Assembly.FullName);
+ break;
+
+ case RegistrationMethod.CodeBase:
+ packageKey.SetValue("CodeBase", context.CodeBase);
+ break;
+ }
+
+ Key childKey = null;
+ if (!useManagedResources)
+ {
+ try
+ {
+ childKey = packageKey.CreateSubkey("SatelliteDll");
+
+ // Register the satellite dll
+ string satelliteDllPath;
+ if (SatellitePath != null)
+ {
+ // Use provided path
+ satelliteDllPath = context.EscapePath(SatellitePath);
+ }
+ else
+ {
+ // Default to package path
+ satelliteDllPath = context.ComponentPath;
+ }
+ childKey.SetValue("Path", satelliteDllPath);
+ childKey.SetValue("DllName", String.Format(CultureInfo.InvariantCulture, "{0}UI.dll", Path.GetFileNameWithoutExtension(t.Assembly.ManifestModule.Name)));
+ }
+ finally
+ {
+ if (childKey != null)
+ childKey.Close();
+ }
+ }
+
+ if (allowsBackgroundLoad)
+ {
+ packageKey.SetValue("AllowsBackgroundLoad", true);
+ }
+
+ if (typeof(IVsPackageDynamicToolOwner).IsAssignableFrom(context.ComponentType) ||
+ typeof(IVsPackageDynamicToolOwnerEx).IsAssignableFrom(context.ComponentType))
+ {
+ packageKey.SetValue("SupportsDynamicToolOwner", Microsoft.VisualStudio.PlatformUI.Boxes.BooleanTrue);
+ }
+ }
+ finally
+ {
+ if (packageKey != null)
+ packageKey.Close();
+ }
+ }
+
+ ///
+ /// Unregister this package.
+ ///
+ ///
+ public override void Unregister(RegistrationContext context)
+ {
+ context.RemoveKey(RegKeyName(context));
+ }
+
+ }
+}
diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs
new file mode 100644
index 000000000..1fc1376f8
--- /dev/null
+++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.VisualStudio.Shell.Interop;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.Shell;
+
+namespace Microsoft.VisualStudio.AsyncPackageHelpers
+{
+ public static class ExtensionMethods
+ {
+ ///
+ /// Helper method to use async/await with IAsyncServiceProvider implementation
+ ///
+ /// IAsyncServciceProvider instance
+ /// Type of the Visual Studio service requested
+ /// Service object as type of T
+ public static async Task GetServiceAsync(this IAsyncServiceProvider asyncServiceProvider, Type serviceType) where T : class
+ {
+ T returnValue = null;
+
+ await ThreadHelper.JoinableTaskFactory.RunAsync(async () =>
+ {
+ object serviceInstance = null;
+ Guid serviceTypeGuid = serviceType.GUID;
+ serviceInstance = await asyncServiceProvider.QueryServiceAsync(ref serviceTypeGuid);
+
+ // We have to make sure we are on main UI thread before trying to cast as underlying implementation
+ // can be an STA COM object and doing a cast would require calling QueryInterface/AddRef marshaling
+ // to main thread via COM.
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+ returnValue = serviceInstance as T;
+ });
+
+ return returnValue;
+ }
+
+ ///
+ /// Gets if async package is supported in the current instance of Visual Studio
+ ///
+ /// an IServiceProvider instance, usually a Package instance
+ /// true if async packages are supported
+ public static bool IsAsyncPackageSupported(this IServiceProvider serviceProvider)
+ {
+ IAsyncServiceProvider asyncServiceProvider = serviceProvider.GetService(typeof(SAsyncServiceProvider)) as IAsyncServiceProvider;
+ return asyncServiceProvider != null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs
new file mode 100644
index 000000000..cf0f3103a
--- /dev/null
+++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs
@@ -0,0 +1,118 @@
+//------------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation, All rights reserved.
+// This code sample is provided "AS IS" without warranty of any kind,
+// it is not recommended for use in a production environment.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.VisualStudio.AsyncPackageHelpers
+{
+
+ using System;
+ using System.Globalization;
+ using Microsoft.VisualStudio.Shell;
+
+ [Flags]
+ public enum PackageAutoLoadFlags
+ {
+ ///
+ /// Indicates no special auto-load behavior. This is the default flag value if not specified.
+ ///
+ None = 0x0,
+
+ ///
+ /// When set package will not auto load in newer Visual Studio versions with rule based UI contexts
+ ///
+ SkipWhenUIContextRulesActive = 0x1,
+
+ ///
+ /// When set, if the associated package is marked as allowing background loads (via the ),
+ /// then the package will be loaded asynchronously, in the background, when the associated UI context is triggered.
+ ///
+ BackgroundLoad = 0x2
+ }
+
+ ///
+ /// This attribute registers the package as an extender. The GUID passed in determines
+ /// what is being extended. The attributes on a package do not control the behavior of
+ /// the package, but they can be used by registration tools to register the proper
+ /// information with Visual Studio.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ public sealed class ProvideAutoLoadAttribute : RegistrationAttribute
+ {
+
+ private Guid loadGuid = Guid.Empty;
+
+ ///
+ /// Specify that the package should get loaded when this context is active.
+ ///
+ /// Context which should trigger the loading of your package.
+ public ProvideAutoLoadAttribute(string cmdUiContextGuid) : this(cmdUiContextGuid, PackageAutoLoadFlags.None)
+ {
+ }
+
+ ///
+ /// Specify that the package should get loaded when this context is active.
+ ///
+ /// Context which should trigger the loading of your package.
+ public ProvideAutoLoadAttribute(string cmdUiContextGuid, PackageAutoLoadFlags flags = PackageAutoLoadFlags.None)
+ {
+ loadGuid = new Guid(cmdUiContextGuid);
+ Flags = flags;
+ }
+
+ ///
+ /// Context Guid which triggers the loading of the package.
+ ///
+ public Guid LoadGuid
+ {
+ get
+ {
+ return loadGuid;
+ }
+ }
+
+ ///
+ /// Specifies the options for package auto load entry
+ ///
+ public PackageAutoLoadFlags Flags
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// The reg key name of this AutoLoad.
+ ///
+ private string RegKeyName
+ {
+ get
+ {
+ return string.Format(CultureInfo.InvariantCulture, "AutoLoadPackages\\{0}", loadGuid.ToString("B"));
+ }
+ }
+
+ ///
+ /// Called to register this attribute with the given context. The context
+ /// contains the location where the registration information should be placed.
+ /// it also contains such as the type being registered, and path information.
+ ///
+ public override void Register(RegistrationContext context)
+ {
+ using (Key childKey = context.CreateKey(RegKeyName))
+ {
+ childKey.SetValue(context.ComponentType.GUID.ToString("B"), (int)Flags);
+ }
+ }
+
+ ///
+ /// Unregister this AutoLoad specification.
+ ///
+ public override void Unregister(RegistrationContext context)
+ {
+ context.RemoveValue(RegKeyName, context.ComponentType.GUID.ToString("B"));
+ }
+ }
+}
diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs
index e49755ce4..faeff3bbc 100644
--- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs
+++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs
@@ -1,6 +1,10 @@
-// This file has been modified by Microsoft on 9/2017.
+// This file has been modified by Microsoft on 3/2019.
+using GoogleTestAdapter.TestAdapter.Settings;
using GoogleTestAdapter.VsPackage.ReleaseNotes;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.AsyncPackageHelpers;
+using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
@@ -9,15 +13,52 @@
namespace GoogleTestAdapter.VsPackage
{
- [ProvideAutoLoad(UIContextGuids.SolutionExists)]
- public partial class GoogleTestExtensionOptionsPage
+ [AsyncPackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
+ [Microsoft.VisualStudio.AsyncPackageHelpers.ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string, PackageAutoLoadFlags.BackgroundLoad)]
+ [Microsoft.VisualStudio.Shell.ProvideAutoLoad(UIContextGuids.SolutionExists)]
+ public partial class GoogleTestExtensionOptionsPage : Package, IAsyncLoadablePackageInitialize
{
private const string PackageGuidString = "e7c90fcb-0943-4908-9ae8-3b6a9d22ec9e";
private const string OptionsCategoryName = "Google Test Adapter";
+ private bool _isAsyncLoadSupported;
+
+ protected override void Initialize()
+ {
+ base.Initialize();
+
+ _isAsyncLoadSupported = this.IsAsyncPackageSupported();
+ if (!_isAsyncLoadSupported)
+ {
+ var componentModel = (IComponentModel)GetGlobalService(typeof(SComponentModel));
+ _globalRunSettings = componentModel.GetService();
+ DoInitialize();
+ }
+ }
+
+ IVsTask IAsyncLoadablePackageInitialize.Initialize(IAsyncServiceProvider serviceProvider, IProfferAsyncService profferService,
+ IAsyncProgressCallback progressCallback)
+ {
+ if (!_isAsyncLoadSupported)
+ {
+ throw new InvalidOperationException("Async Initialize method should not be called when async load is not supported.");
+ }
+
+ return ThreadHelper.JoinableTaskFactory.RunAsync