diff --git a/Nodejs/Product/Nodejs/NodejsConstants.cs b/Nodejs/Product/Nodejs/NodejsConstants.cs
index 8c53edd2d..ff83ab9bb 100644
--- a/Nodejs/Product/Nodejs/NodejsConstants.cs
+++ b/Nodejs/Product/Nodejs/NodejsConstants.cs
@@ -15,6 +15,7 @@
//*********************************************************//
using System;
+using System.IO;
namespace Microsoft.NodejsTools {
internal class NodejsConstants {
@@ -73,6 +74,33 @@ internal class NodejsConstants {
internal const string NodeToolsProcessIdEnvironmentVariable = "_NTVS_PID";
+ public static string NtvsLocalAppData {
+ get {
+ return Path.Combine(
+ System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData),
+ "Microsoft",
+ "Node.js Tools");
+ }
+ }
+
+ ///
+ /// Path to the private package where NTVS tools are installed.
+ ///
+ public static string ExternalToolsPath {
+ get {
+ return Path.Combine(NtvsLocalAppData, "ExternalTools");
+ }
+
+ }
+ ///
+ /// Path to where NTVS caches Npm data.
+ ///
+ public static string NpmCachePath {
+ get {
+ return Path.Combine(NtvsLocalAppData, "NpmCache");
+ }
+ }
+
///
/// Checks whether a relative and double-backslashed seperated path contains a folder name.
///
diff --git a/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsControl.cs b/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsControl.cs
index 5f78f45ce..5cfb86b6e 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsControl.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsControl.cs
@@ -15,25 +15,20 @@
//*********************************************************//
using System;
+using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using Microsoft.NodejsTools.Project;
using Microsoft.VisualStudio.Shell;
-using Microsoft.VisualStudioTools;
namespace Microsoft.NodejsTools.Options {
public partial class NodejsNpmOptionsControl : UserControl {
-
- private string _npmCachePath;
-
public NodejsNpmOptionsControl() {
InitializeComponent();
}
-
internal void SyncControlWithPageSettings(NodejsNpmOptionsPage page) {
_showOutputWhenRunningNpm.Checked = page.ShowOutputWindowWhenExecutingNpm;
- _npmCachePath = page.NpmCachePath;
_cacheClearedSuccessfully.Visible = false;
}
@@ -42,34 +37,57 @@ internal void SyncPageWithControlSettings(NodejsNpmOptionsPage page) {
}
private void ClearCacheButton_Click(object sender, EventArgs e) {
+ bool didClearNpmCache = TryDeleteCacheDirectory(NodejsConstants.NpmCachePath);
+ bool didClearTools = TryDeleteCacheDirectory(NodejsConstants.ExternalToolsPath);
+
+ if (!didClearNpmCache || !didClearTools) {
+ MessageBox.Show(
+ SR.GetString(SR.CacheDirectoryClearFailedCaption, NodejsConstants.NtvsLocalAppData),
+ SR.GetString(SR.CacheDirectoryClearFailedTitle),
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Information);
+ }
+
+ _cacheClearedSuccessfully.Visible = didClearNpmCache && didClearTools;
+ }
+
+ private static bool TryDeleteCacheDirectory(string cachePath) {
+ if (!Directory.Exists(cachePath)) {
+ return true;
+ }
+
try {
- Directory.Delete(_npmCachePath, true);
- _cacheClearedSuccessfully.Visible = true;
- } catch (DirectoryNotFoundException) {
- // Directory has already been deleted. Do nothing.
- _cacheClearedSuccessfully.Visible = true;
- } catch (IOException exception) {
+ // To handle long paths, nuke the directory contents with robocopy
+ string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+ Directory.CreateDirectory(tempDirectory);
+ var psi = new ProcessStartInfo("cmd.exe", string.Format(@"/C robocopy /mir ""{0}"" ""{1}""", tempDirectory, cachePath)) {
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using (var process = Process.Start(psi)) {
+ process.WaitForExit(10000);
+ }
+
+ // Then delete the directory itself
+ try {
+ Directory.Delete(cachePath, true);
+ } catch (DirectoryNotFoundException) {
+ // noop
+ }
+
+ return !Directory.Exists(cachePath);
+ } catch (IOException) {
// files are in use or path is too long
- MessageBox.Show(
- string.Format("Cannot clear npm cache. {0}", exception.Message),
- "Cannot Clear npm Cache",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information
- );
+ return false;
} catch (Exception exception) {
try {
ActivityLog.LogError(SR.ProductName, exception.ToString());
} catch (InvalidOperationException) {
// Activity Log is unavailable.
}
-
- MessageBox.Show(
- string.Format("Cannot clear npm cache. Try manually deleting the directory: {0}", _npmCachePath),
- "Cannot Clear npm Cache",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information
- );
}
+ return false;
}
}
}
\ No newline at end of file
diff --git a/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsPage.cs b/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsPage.cs
index 6aa9eb4c9..fdd785606 100644
--- a/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsPage.cs
+++ b/Nodejs/Product/Nodejs/Options/NodejsNpmOptionsPage.cs
@@ -14,8 +14,6 @@
//
//*********************************************************//
-using System;
-using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@@ -47,17 +45,6 @@ protected override IWin32Window Window {
///
public bool ShowOutputWindowWhenExecutingNpm { get; set; }
- public string NpmCachePath {
- get {
- return Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "Microsoft",
- "Node.js Tools",
- "NpmCache"
- );
- }
- }
-
///
/// Resets settings back to their defaults. This should be followed by
/// a call to to commit the new
diff --git a/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs b/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs
index d30721835..127223a3c 100644
--- a/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs
+++ b/Nodejs/Product/Nodejs/Project/NodeModulesNode.cs
@@ -138,7 +138,7 @@ public string PathToNpm {
private static INpmController DefaultNpmController(string projectHome, NpmPathProvider pathProvider) {
return NpmControllerFactory.Create(
projectHome,
- NodejsPackage.Instance.NpmOptionsPage.NpmCachePath,
+ NodejsConstants.NpmCachePath,
false,
pathProvider);
}
diff --git a/Nodejs/Product/Nodejs/Project/ProjectResources.cs b/Nodejs/Product/Nodejs/Project/ProjectResources.cs
index b80065269..bb52df5ff 100644
--- a/Nodejs/Product/Nodejs/Project/ProjectResources.cs
+++ b/Nodejs/Product/Nodejs/Project/ProjectResources.cs
@@ -31,6 +31,8 @@ internal class SR : CommonSR {
internal const string CatalogLoadingNoNpm = "CatalogLoadingNoNpm";
internal const string CategoryStatus = "CategoryStatus";
internal const string CategoryVersion = "CategoryVersion";
+ internal const string CacheDirectoryClearFailedTitle = "CacheDirectoryClearFailedTitle";
+ internal const string CacheDirectoryClearFailedCaption = "CacheDirectoryClearFailedCaption";
internal const string ContinueWithoutAzureToolsUpgrade = "ContinueWithoutAzureToolsUpgrade";
internal const string DebuggerConnectionClosed = "DebuggerConnectionClosed";
internal const string DebuggerModuleUpdateFailed = "DebuggerModuleUpdateFailed";
diff --git a/Nodejs/Product/Nodejs/Resources.resx b/Nodejs/Product/Nodejs/Resources.resx
index b72bcd3ec..75e2ae257 100644
--- a/Nodejs/Product/Nodejs/Resources.resx
+++ b/Nodejs/Product/Nodejs/Resources.resx
@@ -556,6 +556,12 @@ We recommend installing the latest version of Microsoft Azure Tools for Visual S
Your version of Microsoft Azure Tools is not supported by Node.js Tools for Visual Studio.
+
+ Could Not Clear Node.js Cache Directory
+
+
+ Could not clear Node.js cache directory. Try manually deleting the directory: {0}
+
&Continue
Some manual steps will be required to configure your project.
diff --git a/Nodejs/Product/Nodejs/TypingsAcquisition.cs b/Nodejs/Product/Nodejs/TypingsAcquisition.cs
index 196566496..f1bf69f3b 100644
--- a/Nodejs/Product/Nodejs/TypingsAcquisition.cs
+++ b/Nodejs/Product/Nodejs/TypingsAcquisition.cs
@@ -35,26 +35,13 @@ internal class TypingsAcquisition {
private static SemaphoreSlim typingsToolGlobalWorkSemaphore = new SemaphoreSlim(1);
- ///
- /// Path the the private package where the typings acquisition tool is installed.
- ///
- private static string NtvsExternalToolsPath {
- get {
- return Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "Microsoft",
- "Node.js Tools",
- "ExternalTools");
- }
- }
-
///
/// Full path to the typings acquisition tool.
///
private static string TypingsToolPath {
get {
return Path.Combine(
- NtvsExternalToolsPath,
+ NodejsConstants.ExternalToolsPath,
"node_modules",
".bin",
TypingsToolExe);
@@ -161,11 +148,11 @@ private async Task EnsureTypingsToolInstalled() {
private async Task InstallTypingsTool() {
_didTryToInstallTypingsTool = true;
- Directory.CreateDirectory(NtvsExternalToolsPath);
+ Directory.CreateDirectory(NodejsConstants.ExternalToolsPath);
// install typings
using (var commander = _npmController.CreateNpmCommander()) {
- return await commander.InstallPackageToFolderByVersionAsync(NtvsExternalToolsPath, TypingsTool, TypingsToolVersion, false);
+ return await commander.InstallPackageToFolderByVersionAsync(NodejsConstants.ExternalToolsPath, TypingsTool, TypingsToolVersion, false);
}
}