Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Conversation

jcansdale
Copy link
Collaborator

@jcansdale jcansdale commented Oct 18, 2018

Check that only one binding path is active and warn when extra binding paths might cause issues.

What this PR does

  • Find list of BindingPaths in Visual Studio configuration using ShellSettingsManager
  • Check for duplicate binding paths that could load GitHub.VisualStudio.dll
  • Show warning dialog when extra binding paths might cause issues
  • Offer instructions how to resolve this issue (link here)
  • Only execute on DEBUG builds (no need to run in production)

How to test

  1. Install GitHub for Visual Studio from Marketplace
  2. Load GitHub for Visual Studio solution
  3. Launch and install extension
  4. Click View > Other Windows > GitHub
  5. Expect the following to appear in the log
    image
  6. Click Yes and follow instructions
  7. Repeat from 2. and check that no dialog appears

xmldoc

/// <summary>
/// This a workaround for extensions that define a ProvideBindingPath attribute and
/// install for AllUsers.
/// </summary>
/// <remarks>
/// Extensions that are installed for AllUsers, will also be installed for all
/// instances of Visual Studio - including the experimental (Exp) instance which
/// is used in development. This isn't a problem so long as all features that
/// exist in the AllUsers extension, also exist in the extension that is being
/// developed.
///
/// When an extension uses the ProvideBindingPath attribute, the binding path for
/// the AllUsers extension gets installed at the same time as the one in development.
/// This doesn't matter when an assembly is strong named and is loaded using its
/// full name (including version number). When an assembly is loaded using its
/// simple name, assemblies from the AllUsers extension can end up loaded at the
/// same time as the extension being developed. This can happen when an assembly
/// is loaded from XAML or an .imagemanifest.
///
/// This is a workaround for that issue. The <see cref="FindRedundantBindingPaths(List{string}, string)" />
/// method will check to see if a reference assembly could be loaded from an alternative
/// binding path. It will return any alternative paths that is finds.
/// </remarks>

Fixes #1995

Check that only one binding path is active and remove and extra binding
paths that would cause issues.
@jcansdale jcansdale requested a review from donokuda October 18, 2018 10:49
@jcansdale jcansdale force-pushed the fixes/1995-too-many-binding-paths branch from aff0975 to 9196e0c Compare October 19, 2018 08:58
This is a helper class and not fundamental to GitHub for Visual Studio.
Make RationalizeBindingPaths return false when an assembly has already
been loaded from an alternative location.
Make FindBindingPaths return empty when not running inside Visual
Studio.
@codecov
Copy link

codecov bot commented Oct 19, 2018

Codecov Report

Merging #1996 into master will decrease coverage by 1.47%.
The diff coverage is 23.52%.

@@            Coverage Diff             @@
##           master    #1996      +/-   ##
==========================================
- Coverage    41.7%   40.22%   -1.48%     
==========================================
  Files         373      406      +33     
  Lines       16126    17377    +1251     
  Branches     2211     2393     +182     
==========================================
+ Hits         6725     6990     +265     
- Misses       8890     9859     +969     
- Partials      511      528      +17
Impacted Files Coverage Δ
src/GitHub.VisualStudio/GitHubPackage.cs 0% <0%> (ø)
...c/GitHub.VisualStudio/Helpers/BindingPathHelper.cs 25% <25%> (ø)
...nlineReviews/Services/PullRequestSessionManager.cs 82.23% <0%> (-1.02%) ⬇️
...c/GitHub.InlineReviews/Tags/InlineCommentTagger.cs 79.64% <0%> (-0.89%) ⬇️
...nlineReviews/Services/PullRequestSessionService.cs 16.7% <0%> (-0.41%) ⬇️
...rc/GitHub.VisualStudio/Commands/OpenLinkCommand.cs 0% <0%> (ø)
...Hub.VisualStudio/Commands/ShowGitHubPaneCommand.cs 0% <0%> (ø)
...o/Commands/GoToSolutionOrPullRequestFileCommand.cs 0% <0%> (ø)
src/GitHub.VisualStudio/Services/UsageTracker.cs 92.53% <0%> (ø)
... and 28 more

This doesn't need to run in production.
@jcansdale jcansdale force-pushed the fixes/1995-too-many-binding-paths branch from 24dfe51 to fed313c Compare October 19, 2018 12:01
Copy link
Contributor

@grokys grokys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is using reflection to change private state of code we don't own, which sounds to me like a recipe for disaster down the line. Even though it's only doing it in debug builds, it's quite possibly something that will come back to bite us and cause hours of debugging.

@madskristensen @AArnott does this sound like something we should be doing?

@jcansdale
Copy link
Collaborator Author

jcansdale commented Oct 19, 2018

👋 @sharwell @josetr,

I wondered if you had any thoughts on this or have any suggestions for a cleaner fix?

Do you know if it's possible to completely disable an AllUsers extension in the Exp instance without impacting the regular instance?

@AArnott
Copy link

AArnott commented Oct 19, 2018

Thanks for checking. I'm pretty sure we really wouldn't want this to ever ship to customers. As for your own debugging experience, I guess that's up to you as I can't speak to how unstable this would make your code.

@Michael-Eng FYI

Separate the code that reads and the code that mutates.
Simply detect wrong binding path and offer to show info rather than
attempt to fix.
Use ShellSettingsManager instead of reflection to find BindingPaths.
CA was failing because InitializeAsync wasn't awaiting anything on a
non-DEBUG build.
@jcansdale
Copy link
Collaborator Author

jcansdale commented Oct 22, 2018

@grokys here's a non-hacky version for you that doesn't use reflection. 😉

There is a new feature in Visual Studio 2017 that lets you disable AllUsers extensions in just the experimental instance. I'd recommend doing this for NCrunch and any other AllUsers extensions you might have installed (less symbols to load when debugging).

Copy link
Contributor

@grokys grokys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much happier with this ;) Just one question but LGTM!

/// method will check to see if a reference assembly could be loaded from an alternative
/// binding path. It will return any alternative paths that is finds.
/// </remarks>
public static class BindingPathUtilities
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class only seems to be used by BindingPathHelper - can these methods just be put there?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was just painful to write units tests that target, GitHub.VisualStudio because of the compile time! Now that it's stable, I've merged into BindingPathHelper as suggested. 👍

Merge BindingPathUtilities into BindingPathHelper.
Explicitly specify CultureInfo.CurrentCulture.
Make class BindingPathHelper static.
@jcansdale jcansdale merged commit 6c1e811 into master Oct 24, 2018
@jcansdale jcansdale deleted the fixes/1995-too-many-binding-paths branch October 24, 2018 11:13
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Extension fails in development when normal version is installed
3 participants