From f9c5721f219449bf288e19e9924072a885f5d826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Mal=C3=ADk?= Date: Wed, 19 Jun 2019 09:10:37 +0200 Subject: [PATCH 1/2] Implement async package instead of package --- HangFixer/HangFixer.csproj | 11 +- HangFixer/HangFixerPackage.cs | 343 ++++++++++++++++++---------------- 2 files changed, 186 insertions(+), 168 deletions(-) diff --git a/HangFixer/HangFixer.csproj b/HangFixer/HangFixer.csproj index c5ee4ee..2a1798c 100644 --- a/HangFixer/HangFixer.csproj +++ b/HangFixer/HangFixer.csproj @@ -2,7 +2,7 @@ MobileEssentials MobileEssentials.HangFixer - net46 + net472 MobileEssentials.HangFixer.vsix true HangFixer.snk @@ -29,7 +29,12 @@ - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/HangFixer/HangFixerPackage.cs b/HangFixer/HangFixerPackage.cs index 41a5ade..36e6e9e 100644 --- a/HangFixer/HangFixerPackage.cs +++ b/HangFixer/HangFixerPackage.cs @@ -1,166 +1,179 @@ -using Microsoft.VisualStudio.Shell; -using Microsoft.VisualStudio.Shell.Interop; -using System; -using System.Runtime.InteropServices; -using Microsoft.VisualStudio; -using System.IO; - -namespace MobileEssentials -{ - [ProvideBindingPath] - [PackageRegistration (UseManagedResourcesOnly = true)] - [Guid ("0553379B-5124-48B6-80B0-09AF3A331CDD")] - [ProvideAutoLoad (SolutionOpening_string)] - public sealed class HangFixerPackage : Package, IVsSolutionLoadEvents, IVsSolutionEvents - { - /// Specifies a context in which a solution is being opened. - public const string SolutionOpening_string = "{D2567162-F94F-4091-8798-A096E61B8B50}"; - - - uint cookie; - string flagFile; - - protected override void Initialize () - { - base.Initialize (); - - var solution = (IVsSolution2)GetService(typeof(SVsSolution)); - ErrorHandler.ThrowOnFailure (solution.AdviseSolutionEvents (this, out cookie)); - } - - // Order of callbacks is: - // OnBeforeOpenSolution > OnAfterOpenSolution > OnBeforeBackgroundSolutionLoadBegins > OnAfterBackgroundSolutionLoadComplete - // The last two will only happen if background solution load is enabled. - // Therefore, we will setup the flag file on both befores, and clear it on both afters. - public int OnBeforeOpenSolution (string pszSolutionFilename) - { - // If flag file exists, delete .vs and .suo, since it means we tried loading - // before, and we failed. - // This happens only once for a given solution, so it's safe to assume this - // is the "main" entry point event. - flagFile = Path.ChangeExtension (pszSolutionFilename, ".tmp"); - - if (File.Exists (flagFile)) { - var vsDir = Path.Combine(Path.GetDirectoryName(pszSolutionFilename), ".vs"); - if (Directory.Exists (vsDir)) { - try { - Directory.Delete (vsDir, true); - } catch (IOException) { - // Never fail, no matter what. - } - } - foreach (var suoFile in Directory.EnumerateFiles (Path.GetDirectoryName (pszSolutionFilename), "*.suo")) { - try { - File.Delete (suoFile); - } catch (IOException) { - // Never fail, no matter what. - } - } - } - - // Written outside the if, so that we always get the - // timestamp of the current solution load attempt. - File.WriteAllText (flagFile, "Visual Studio Hang Fixer"); - - // TODO: create the flag file - return VSConstants.S_OK; - } - - public int OnAfterOpenSolution (object pUnkReserved, int fNewSolution) - { - // Load was successfull, clear the flag file. - ClearFlagFile (); - return VSConstants.S_OK; - } - - public int OnBeforeBackgroundSolutionLoadBegins () - { - // The OnAfterOpenSolution is called even when pending - // background solution load is pending (which is optional - // depending on user settings). So we write the flag file - // again to get the timestamp of the current background - // solution load attempt. - File.WriteAllText (flagFile, "Visual Studio Hang Fixer"); - return VSConstants.S_OK; - } - - public int OnAfterBackgroundSolutionLoadComplete () - { - // Load was successfull, clear the flag file. - ClearFlagFile (); - return VSConstants.S_OK; - } - - void ClearFlagFile () - { - if (File.Exists (flagFile)) { - File.Delete (flagFile); - } - } - - #region Unused - - public int OnAfterCloseSolution (object pUnkReserved) - { - return VSConstants.S_OK; - } - - public int OnAfterLoadProject (IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) - { - return VSConstants.S_OK; - } - - public int OnAfterLoadProjectBatch (bool fIsBackgroundIdleBatch) - { - return VSConstants.S_OK; - } - - public int OnAfterOpenProject (IVsHierarchy pHierarchy, int fAdded) - { - return VSConstants.S_OK; - } - - public int OnBeforeCloseProject (IVsHierarchy pHierarchy, int fRemoved) - { - return VSConstants.S_OK; - } - - public int OnBeforeCloseSolution (object pUnkReserved) - { - return VSConstants.S_OK; - } - - public int OnBeforeLoadProjectBatch (bool fIsBackgroundIdleBatch) - { - return VSConstants.S_OK; - } - - public int OnBeforeUnloadProject (IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy) - { - return VSConstants.S_OK; - } - - public int OnQueryBackgroundLoadProjectBatch (out bool pfShouldDelayLoadToNextIdle) - { - pfShouldDelayLoadToNextIdle = false; - return VSConstants.S_OK; - } - - public int OnQueryCloseProject (IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) - { - return VSConstants.S_OK; - } - - public int OnQueryCloseSolution (object pUnkReserved, ref int pfCancel) - { - return VSConstants.S_OK; - } - - public int OnQueryUnloadProject (IVsHierarchy pRealHierarchy, ref int pfCancel) - { - return VSConstants.S_OK; - } - - #endregion - } +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace MobileEssentials +{ + [ProvideBindingPath] + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Guid("0553379B-5124-48B6-80B0-09AF3A331CDD")] + [ProvideAutoLoad(SolutionOpening_string, PackageAutoLoadFlags.BackgroundLoad)] + public sealed class HangFixerPackage : AsyncPackage, IVsSolutionLoadEvents, IVsSolutionEvents + { + /// Specifies a context in which a solution is being opened. + public const string SolutionOpening_string = "{D2567162-F94F-4091-8798-A096E61B8B50}"; + + private string flagFile; + + protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + IVsSolution2 solution = (IVsSolution2)await GetServiceAsync(typeof(SVsSolution)); + Assumes.Present(solution); + + //System.Windows.Threading.Dispatcher.VerifyAccess(); + ErrorHandler.ThrowOnFailure(solution.AdviseSolutionEvents(this, out _)); + await base.InitializeAsync(cancellationToken, progress); + } + + // Order of callbacks is: + // OnBeforeOpenSolution > OnAfterOpenSolution > OnBeforeBackgroundSolutionLoadBegins > OnAfterBackgroundSolutionLoadComplete + // The last two will only happen if background solution load is enabled. + // Therefore, we will setup the flag file on both befores, and clear it on both afters. + public int OnBeforeOpenSolution(string pszSolutionFilename) + { + // If flag file exists, delete .vs and .suo, since it means we tried loading + // before, and we failed. + // This happens only once for a given solution, so it's safe to assume this + // is the "main" entry point event. + flagFile = Path.ChangeExtension(pszSolutionFilename, ".tmp"); + + if (File.Exists(flagFile)) + { + string vsDir = Path.Combine(Path.GetDirectoryName(pszSolutionFilename), ".vs"); + if (Directory.Exists(vsDir)) + { + try + { + Directory.Delete(vsDir, true); + } + catch (IOException) + { + // Never fail, no matter what. + } + } + foreach (string suoFile in Directory.EnumerateFiles(Path.GetDirectoryName(pszSolutionFilename), "*.suo")) + { + try + { + File.Delete(suoFile); + } + catch (IOException) + { + // Never fail, no matter what. + } + } + } + + // Written outside the if, so that we always get the + // timestamp of the current solution load attempt. + File.WriteAllText(flagFile, "Visual Studio Hang Fixer"); + + // TODO: create the flag file + return VSConstants.S_OK; + } + + public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution) + { + // Load was successfull, clear the flag file. + ClearFlagFile(); + return VSConstants.S_OK; + } + + public int OnBeforeBackgroundSolutionLoadBegins() + { + // The OnAfterOpenSolution is called even when pending + // background solution load is pending (which is optional + // depending on user settings). So we write the flag file + // again to get the timestamp of the current background + // solution load attempt. + File.WriteAllText(flagFile, "Visual Studio Hang Fixer"); + return VSConstants.S_OK; + } + + public int OnAfterBackgroundSolutionLoadComplete() + { + // Load was successfull, clear the flag file. + ClearFlagFile(); + return VSConstants.S_OK; + } + + private void ClearFlagFile() + { + if (File.Exists(flagFile)) + { + File.Delete(flagFile); + } + } + + #region Unused + + public int OnAfterCloseSolution(object pUnkReserved) + { + return VSConstants.S_OK; + } + + public int OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) + { + return VSConstants.S_OK; + } + + public int OnAfterLoadProjectBatch(bool fIsBackgroundIdleBatch) + { + return VSConstants.S_OK; + } + + public int OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded) + { + return VSConstants.S_OK; + } + + public int OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved) + { + return VSConstants.S_OK; + } + + public int OnBeforeCloseSolution(object pUnkReserved) + { + return VSConstants.S_OK; + } + + public int OnBeforeLoadProjectBatch(bool fIsBackgroundIdleBatch) + { + return VSConstants.S_OK; + } + + public int OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy) + { + return VSConstants.S_OK; + } + + public int OnQueryBackgroundLoadProjectBatch(out bool pfShouldDelayLoadToNextIdle) + { + pfShouldDelayLoadToNextIdle = false; + return VSConstants.S_OK; + } + + public int OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) + { + return VSConstants.S_OK; + } + + public int OnQueryCloseSolution(object pUnkReserved, ref int pfCancel) + { + return VSConstants.S_OK; + } + + public int OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel) + { + return VSConstants.S_OK; + } + + #endregion + } } \ No newline at end of file From e82008cee5b719964af3506b609d07d58339ee4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Mal=C3=ADk?= Date: Wed, 19 Jun 2019 09:12:39 +0200 Subject: [PATCH 2/2] Update version minor --- HangFixer/source.extension.vsixmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HangFixer/source.extension.vsixmanifest b/HangFixer/source.extension.vsixmanifest index 3776179..dd7d076 100644 --- a/HangFixer/source.extension.vsixmanifest +++ b/HangFixer/source.extension.vsixmanifest @@ -1,7 +1,7 @@ - + Visual Studio Hang Fixer Fixes hangs that happen when opening a solution with a corrupt or invalid .vs directory or .suo file. https://github.com/MobileEssentials/HangFixer