From 7cf41e1438ceab293353bcd818f82fc3ad2e043c Mon Sep 17 00:00:00 2001 From: Rich Chiodo Date: Tue, 13 Jul 2021 14:50:01 -0700 Subject: [PATCH] Handle different exceptions that can occur and cause VS crashes (#6604) * Handle different exceptions that can occur * Review feedback, let other package managers have a chance --- .../Project/ConfigureTestFrameworkInfoBar.cs | 26 +++++++++++----- .../Product/PythonTools/PythonToolsService.cs | 2 +- .../Interpreter/PythonWorkspaceContext.cs | 31 ++++++++++++++++--- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Python/Product/PythonTools/PythonTools/Project/ConfigureTestFrameworkInfoBar.cs b/Python/Product/PythonTools/PythonTools/Project/ConfigureTestFrameworkInfoBar.cs index eb7d590bf8..3ee050c81a 100644 --- a/Python/Product/PythonTools/PythonTools/Project/ConfigureTestFrameworkInfoBar.cs +++ b/Python/Product/PythonTools/PythonTools/Project/ConfigureTestFrameworkInfoBar.cs @@ -111,19 +111,29 @@ private void ShowInfoBar(string infoBarMessage, List acceptAct private async Task InstallPyTestAsync() { var packageManagers = _infoBarData.InterpreterOptionsService.GetPackageManagers(_infoBarData.InterpreterFactory); + string failureMessage = null; foreach (var packageManager in packageManagers) { - bool pytestInstalled = await packageManager.InstallAsync( - new PackageSpec("pytest"), - new VsPackageManagerUI(Site), - CancellationToken.None - ); - - if (pytestInstalled) { - return true; + try { + bool pytestInstalled = await packageManager.InstallAsync( + new PackageSpec("pytest"), + new VsPackageManagerUI(Site), + CancellationToken.None + ); + + if (pytestInstalled) { + return true; + } + } catch (InvalidOperationException e) { + failureMessage = e.Message; } } + if (!String.IsNullOrEmpty(failureMessage)) { + // Something couldn't be installed. + Create(new InfoBarModel(failureMessage)); + } + return false; } diff --git a/Python/Product/PythonTools/PythonToolsService.cs b/Python/Product/PythonTools/PythonToolsService.cs index 2a45c580bd..ba3bd5432a 100644 --- a/Python/Product/PythonTools/PythonToolsService.cs +++ b/Python/Product/PythonTools/PythonToolsService.cs @@ -375,7 +375,7 @@ internal Dictionary GetFullEnvironment(LaunchConfiguration confi => LaunchConfigurationUtils.GetFullEnvironment(config, _container, UIThread); internal IEnumerable GetGlobalPythonSearchPaths(InterpreterConfiguration interpreter) { - if (!GeneralOptions.ClearGlobalPythonPath) { + if (!GeneralOptions.ClearGlobalPythonPath && interpreter != null) { string pythonPath = Environment.GetEnvironmentVariable(interpreter.PathEnvironmentVariable) ?? string.Empty; return pythonPath .Split(Path.PathSeparator) diff --git a/Python/Product/VSInterpreters/Interpreter/PythonWorkspaceContext.cs b/Python/Product/VSInterpreters/Interpreter/PythonWorkspaceContext.cs index f00a7bd5e0..2d5865b87d 100644 --- a/Python/Product/VSInterpreters/Interpreter/PythonWorkspaceContext.cs +++ b/Python/Product/VSInterpreters/Interpreter/PythonWorkspaceContext.cs @@ -205,16 +205,15 @@ public IEnumerable EnumerateUserFiles(Predicate predicate) { .Where(x => !string.IsNullOrEmpty(x.InterpreterPath)) .Where(x => PathUtils.IsSubpathOf(_workspace.Location, x.InterpreterPath)) .ToList(); - foreach (var file in Directory.EnumerateFiles(_workspace.Location).Where(x => predicate(x))) { + foreach (var file in EnumerateFilesSafe(_workspace.Location).Where(x => predicate(x))) { yield return file; } - foreach (var topLevelDirectory in Directory.EnumerateDirectories(_workspace.Location)) { + foreach (var topLevelDirectory in EnumerateDirectoriesSafe(_workspace.Location)) { if (!workspaceInterpreterConfigs.Any(x => PathUtils.IsSameDirectory(x.GetPrefixPath(), topLevelDirectory)) && !PathUtils.IsSameDirectory(topLevelDirectory, workspaceCacheDirPath) ) { - foreach (var file in Directory - .EnumerateFiles(topLevelDirectory, "*", SearchOption.AllDirectories) + foreach (var file in EnumerateFilesSafe(topLevelDirectory, "*", SearchOption.AllDirectories) .Where(x => predicate(x)) ) { yield return file; @@ -263,6 +262,30 @@ private void RefreshCurrentFactory() { } } + private IEnumerable EnumerateDirectoriesSafe(string location) { + try { + return EnumerateDirectoriesSafe(location); + } catch (SystemException) { + return Enumerable.Empty(); + } + } + + private IEnumerable EnumerateFilesSafe(string location) { + try { + return EnumerateFilesSafe(location); + } catch (SystemException) { + return Enumerable.Empty(); + } + } + + private IEnumerable EnumerateFilesSafe(string location, string pattern, SearchOption option) { + try { + return EnumerateFilesSafe(location, pattern, option); + } catch (SystemException) { + return Enumerable.Empty(); + } + } + private static IPythonInterpreterFactory GetFactory(string interpreter, IWorkspace workspace, IInterpreterRegistryService registryService) { IPythonInterpreterFactory factory = null; if (interpreter != null && registryService != null) {