diff --git a/TestAssets/NonRestoredTestProjects/AppThrowingException/App/AppThrowingException.csproj b/TestAssets/NonRestoredTestProjects/AppThrowingException/App/AppThrowingException.csproj
new file mode 100644
index 000000000..366798fca
--- /dev/null
+++ b/TestAssets/NonRestoredTestProjects/AppThrowingException/App/AppThrowingException.csproj
@@ -0,0 +1,22 @@
+
+
+
+ Exe
+ netcoreapp1.0
+ dotnet-throwingtool
+ $(AssemblyName)
+
+
+
+
+ $(ProjectRuntimeConfigFilePath)
+
+
+
+
+
+ 1.0.3
+
+
+
+
diff --git a/TestAssets/NonRestoredTestProjects/AppThrowingException/App/Program.cs b/TestAssets/NonRestoredTestProjects/AppThrowingException/App/Program.cs
new file mode 100644
index 000000000..5d9d13152
--- /dev/null
+++ b/TestAssets/NonRestoredTestProjects/AppThrowingException/App/Program.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace AppThrowing
+{
+ class MyException : Exception
+ {
+ static void Main(string[] args)
+ {
+ throw new MyException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/AppDependingOnOtherAsTool.csproj b/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/AppDependingOnOtherAsTool.csproj
new file mode 100644
index 000000000..04b137131
--- /dev/null
+++ b/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/AppDependingOnOtherAsTool.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ netcoreapp1.0
+
+
+
+
+ 1.0.3
+
+
+
+
+
+ 1.0.0
+
+
+
+
diff --git a/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/NuGet.Config b/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/NuGet.Config
new file mode 100644
index 000000000..97af9d3d0
--- /dev/null
+++ b/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/Program.cs b/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/Program.cs
new file mode 100644
index 000000000..846370cce
--- /dev/null
+++ b/TestAssets/NonRestoredTestProjects/AppThrowingException/AppDependingOnOtherAsTool/Program.cs
@@ -0,0 +1,8 @@
+using System;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ }
+}
diff --git a/src/Microsoft.DotNet.Cli.Utils/ExceptionExtensions.cs b/src/Microsoft.DotNet.Cli.Utils/ExceptionExtensions.cs
new file mode 100644
index 000000000..68743b1d8
--- /dev/null
+++ b/src/Microsoft.DotNet.Cli.Utils/ExceptionExtensions.cs
@@ -0,0 +1,15 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+
+namespace Microsoft.DotNet.Cli.Utils.ExceptionExtensions
+{
+ internal static class ExceptionExtensions
+ {
+ public static void ReportAsWarning(this Exception e)
+ {
+ Reporter.Verbose.WriteLine($"Warning: Ignoring exception: {e.ToString().Yellow()}");
+ }
+ }
+}
diff --git a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
index f64042329..2f2353cbe 100644
--- a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
+++ b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
@@ -88,6 +88,20 @@ namespace Microsoft.DotNet.Tools.Common
}
}
+ public static bool TryDeleteDirectory(string directoryPath)
+ {
+ try
+ {
+ Directory.Delete(directoryPath, true);
+
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
///
/// Returns childItem relative to directory, with Path.DirectorySeparatorChar as separator
///
diff --git a/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs
index 7d41c16db..e5ed6ddf4 100644
--- a/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs
+++ b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs
@@ -6,3 +6,4 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Cli.Utils.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
+[assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectJsonMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
diff --git a/src/Microsoft.DotNet.InternalAbstractions/FileWrapper.cs b/src/Microsoft.DotNet.InternalAbstractions/FileWrapper.cs
index 01f579b84..9a71ba5d2 100644
--- a/src/Microsoft.DotNet.InternalAbstractions/FileWrapper.cs
+++ b/src/Microsoft.DotNet.InternalAbstractions/FileWrapper.cs
@@ -36,15 +36,9 @@ namespace Microsoft.Extensions.EnvironmentAbstractions
public void CreateEmptyFile(string path)
{
- try
+ using (File.Create(path))
{
- var emptyFile = File.Create(path);
- if (emptyFile != null)
- {
- emptyFile.Dispose();
- }
}
- catch { }
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.DotNet.ProjectJsonMigration/ProjectMigrator.cs b/src/Microsoft.DotNet.ProjectJsonMigration/ProjectMigrator.cs
index 98f7e4cf4..eee159c59 100644
--- a/src/Microsoft.DotNet.ProjectJsonMigration/ProjectMigrator.cs
+++ b/src/Microsoft.DotNet.ProjectJsonMigration/ProjectMigrator.cs
@@ -3,12 +3,13 @@
using System;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using Microsoft.Build.Construction;
using Microsoft.DotNet.Internal.ProjectModel;
using Microsoft.DotNet.Internal.ProjectModel.Graph;
using Microsoft.DotNet.Cli;
-using System.Linq;
-using System.IO;
+using Microsoft.DotNet.Cli.Utils.ExceptionExtensions;
using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.ProjectJsonMigration.Rules;
using Microsoft.DotNet.Tools.Common;
@@ -87,14 +88,22 @@ namespace Microsoft.DotNet.ProjectJsonMigration
try
{
File.Delete(Path.Combine(rootsettings.ProjectDirectory, "project.json"));
- } catch {}
+ }
+ catch (Exception e)
+ {
+ e.ReportAsWarning();
+ }
foreach (var projectDependency in projectDependencies)
{
try
{
File.Delete(projectDependency.ProjectFilePath);
- } catch { }
+ }
+ catch (Exception e)
+ {
+ e.ReportAsWarning();
+ }
}
}
diff --git a/src/dotnet-archive/Program.cs b/src/dotnet-archive/Program.cs
index 0c8a1be39..3376bf47e 100644
--- a/src/dotnet-archive/Program.cs
+++ b/src/dotnet-archive/Program.cs
@@ -90,21 +90,7 @@ namespace Microsoft.DotNet.Tools.Archive
return 0;
});
- try
- {
- return app.Execute(args);
- }
- catch (Exception ex)
- {
-#if DEBUG
- //Reporter.Error.WriteLine(ex.ToString());
- Console.WriteLine(ex.ToString());
-#else
- // Reporter.Error.WriteLine(ex.Message);
- Console.WriteLine(ex.Message);
-#endif
- return 1;
- }
+ return app.Execute(args);
}
}
}
diff --git a/src/dotnet/MulticoreJitActivator.cs b/src/dotnet/MulticoreJitActivator.cs
index e51a4e5dc..a22bb39ab 100644
--- a/src/dotnet/MulticoreJitActivator.cs
+++ b/src/dotnet/MulticoreJitActivator.cs
@@ -4,6 +4,7 @@
using System;
using System.Runtime.Loader;
using Microsoft.DotNet.Cli.Utils;
+using Microsoft.DotNet.Cli.Utils.ExceptionExtensions;
using Microsoft.DotNet.Tools.Common;
namespace Microsoft.DotNet.Cli
@@ -51,8 +52,9 @@ namespace Microsoft.DotNet.Cli
return true;
}
- catch (Exception)
+ catch (Exception e)
{
+ e.ReportAsWarning();
return false;
}
}
diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs
index a28b0bc37..faefe0a31 100644
--- a/src/dotnet/Program.cs
+++ b/src/dotnet/Program.cs
@@ -82,22 +82,6 @@ namespace Microsoft.DotNet.Cli
return 1;
}
- catch (Exception ex)
- {
-#if DEBUG
- Reporter.Error.WriteLine(ex.ToString());
-#else
- if (Reporter.IsVerbose)
- {
- Reporter.Error.WriteLine(ex.ToString());
- }
- else
- {
- Reporter.Error.WriteLine(ex.Message);
- }
-#endif
- return 1;
- }
finally
{
if (PerfTrace.Enabled)
diff --git a/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs b/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs
index a814acd82..9a61d3a3e 100644
--- a/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs
+++ b/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs
@@ -309,7 +309,7 @@ namespace Microsoft.DotNet.Tools.Migrate
if (!projects.Any())
{
- throw new Exception("Unable to find any projects in global.json");
+ throw new GracefulException("Unable to find any projects in global.json");
}
}
else if (File.Exists(projectArg) &&
@@ -319,7 +319,7 @@ namespace Microsoft.DotNet.Tools.Migrate
if (!projects.Any())
{
- throw new Exception($"Unable to find any projects in {projectArg}");
+ throw new GracefulException($"Unable to find any projects in {projectArg}");
}
}
else if (Directory.Exists(projectArg))
@@ -328,12 +328,12 @@ namespace Microsoft.DotNet.Tools.Migrate
if (!projects.Any())
{
- throw new Exception($"No project.json file found in '{projectArg}'");
+ throw new GracefulException($"No project.json file found in '{projectArg}'");
}
}
else
{
- throw new Exception($"Invalid project argument - '{projectArg}' is not a project.json, global.json, or solution.sln file and a directory named '{projectArg}' doesn't exist.");
+ throw new GracefulException($"Invalid project argument - '{projectArg}' is not a project.json, global.json, or solution.sln file and a directory named '{projectArg}' doesn't exist.");
}
foreach (var project in projects)
@@ -346,7 +346,7 @@ namespace Microsoft.DotNet.Tools.Migrate
{
if (variable == null)
{
- throw new Exception(message);
+ throw new GracefulException(message);
}
}
@@ -359,14 +359,14 @@ namespace Microsoft.DotNet.Tools.Migrate
return projectJson;
}
- throw new Exception($"Unable to find project file at {projectJson}");
+ throw new GracefulException($"Unable to find project file at {projectJson}");
}
private IEnumerable GetProjectsFromGlobalJson(string globalJson)
{
if (!File.Exists(globalJson))
{
- throw new Exception($"Unable to find global settings file at {globalJson}");
+ throw new GracefulException($"Unable to find global settings file at {globalJson}");
}
var searchPaths = ProjectDependencyFinder.GetGlobalPaths(Path.GetDirectoryName(globalJson));
@@ -396,7 +396,7 @@ namespace Microsoft.DotNet.Tools.Migrate
{
if (!File.Exists(slnPath))
{
- throw new Exception($"Unable to find the solution file at {slnPath}");
+ throw new GracefulException($"Unable to find the solution file at {slnPath}");
}
_slnFile = SlnFile.Read(slnPath);
diff --git a/src/dotnet/commands/dotnet-migrate/Program.cs b/src/dotnet/commands/dotnet-migrate/Program.cs
index 86104dd0e..469b29b50 100644
--- a/src/dotnet/commands/dotnet-migrate/Program.cs
+++ b/src/dotnet/commands/dotnet-migrate/Program.cs
@@ -78,16 +78,17 @@ namespace Microsoft.DotNet.Tools.Migrate
{
return app.Execute(args);
}
- catch (Exception ex)
+ catch (GracefulException e)
{
-#if DEBUG
- Reporter.Error.WriteLine(ex.ToString());
-#else
- Reporter.Error.WriteLine(ex.Message);
-#endif
+ Reporter.Error.WriteLine(e.Message);
Reporter.Error.WriteLine(LocalizableStrings.MigrationFailedError);
return 1;
}
+ catch (Exception e)
+ {
+ Reporter.Error.WriteLine(LocalizableStrings.MigrationFailedError);
+ throw e;
+ }
}
}
}
diff --git a/src/dotnet/commands/dotnet-migrate/TemporaryDotnetNewTemplateProject.cs b/src/dotnet/commands/dotnet-migrate/TemporaryDotnetNewTemplateProject.cs
index 3c4b2d39a..12fcbda25 100644
--- a/src/dotnet/commands/dotnet-migrate/TemporaryDotnetNewTemplateProject.cs
+++ b/src/dotnet/commands/dotnet-migrate/TemporaryDotnetNewTemplateProject.cs
@@ -3,6 +3,7 @@ using Microsoft.DotNet.Cli;
using System;
using System.Collections.Generic;
using System.IO;
+using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectJsonMigration;
using Microsoft.Build.Evaluation;
@@ -77,7 +78,7 @@ namespace Microsoft.DotNet.Tools.Migrate
MigrationTrace.Instance.WriteLine(commandResult.StdOut);
MigrationTrace.Instance.WriteLine(commandResult.StdErr);
- throw new Exception($"Failed to run {commandToExecute} in directory: {workingDirectory}");
+ throw new GracefulException($"Failed to run {commandToExecute} in directory: {workingDirectory}");
}
}
}
diff --git a/src/dotnet/commands/dotnet-new/Program.cs b/src/dotnet/commands/dotnet-new/Program.cs
index 0824ae1ed..f221f011d 100644
--- a/src/dotnet/commands/dotnet-new/Program.cs
+++ b/src/dotnet/commands/dotnet-new/Program.cs
@@ -155,19 +155,7 @@ namespace Microsoft.DotNet.Tools.New
return dotnetNew.CreateEmptyProject(language.Name, fullTemplateName);
});
- try
- {
- return app.Execute(args);
- }
- catch (Exception ex)
- {
-#if DEBUG
- Reporter.Error.WriteLine(ex.ToString());
-#else
- Reporter.Error.WriteLine(ex.Message);
-#endif
- return 1;
- }
+ return app.Execute(args);
}
}
}
diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAppThrowingException.cs b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAppThrowingException.cs
new file mode 100644
index 000000000..fb4299442
--- /dev/null
+++ b/test/Microsoft.DotNet.Cli.Utils.Tests/GivenAppThrowingException.cs
@@ -0,0 +1,78 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.IO;
+using FluentAssertions;
+using Microsoft.DotNet.Tools.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.DotNet.Cli.Utils.Tests
+{
+ public class GivenAppThrowingException : TestBase
+ {
+ [Fact]
+ public void ItShowsStackTraceWhenRun()
+ {
+ var root = TestAssets.Get("NonRestoredTestProjects", "AppThrowingException")
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root;
+
+ var appRoot = Path.Combine(root.FullName, "App");
+
+ new RestoreCommand()
+ .WithWorkingDirectory(appRoot)
+ .Execute()
+ .Should().Pass();
+
+ string msg1 = "Unhandled Exception: AppThrowing.MyException: "
+ + "Exception of type 'AppThrowing.MyException' was thrown.";
+ string msg2 = "at AppThrowing.MyException.Main(String[] args)";
+ new RunCommand()
+ .WithWorkingDirectory(appRoot)
+ .ExecuteWithCapturedOutput()
+ .Should().Fail()
+ .And.HaveStdErrContaining(msg1)
+ .And.HaveStdErrContaining(msg2);
+ }
+
+ [Fact]
+ public void ItShowsStackTraceWhenRunAsTool()
+ {
+ var root = TestAssets.Get("NonRestoredTestProjects", "AppThrowingException")
+ .CreateInstance()
+ .WithSourceFiles()
+ .Root;
+
+ var appRoot = Path.Combine(root.FullName, "App");
+
+ new RestoreCommand()
+ .WithWorkingDirectory(appRoot)
+ .Execute()
+ .Should().Pass();
+
+ new PackCommand()
+ .WithWorkingDirectory(appRoot)
+ .Execute("-o ../pkgs")
+ .Should()
+ .Pass();
+
+ var appWithToolDepRoot = Path.Combine(root.FullName, "AppDependingOnOtherAsTool");
+
+ new RestoreCommand()
+ .WithWorkingDirectory(appWithToolDepRoot)
+ .Execute()
+ .Should().Pass();
+
+ string msg1 = "Unhandled Exception: AppThrowing.MyException: "
+ + "Exception of type 'AppThrowing.MyException' was thrown.";
+ string msg2 = "at AppThrowing.MyException.Main(String[] args)";
+ new TestCommand("dotnet")
+ .WithWorkingDirectory(appWithToolDepRoot)
+ .ExecuteWithCapturedOutput("throwingtool")
+ .Should().Fail()
+ .And.HaveStdErrContaining(msg1)
+ .And.HaveStdErrContaining(msg2);
+ }
+ }
+}