diff --git a/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/MSBuildTestAppWithCorruptedLaunchSettings.csproj b/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/MSBuildTestAppWithCorruptedLaunchSettings.csproj
new file mode 100644
index 000000000..79bceb82d
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/MSBuildTestAppWithCorruptedLaunchSettings.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+ Exe
+ netcoreapp2.0
+ win7-x64;win7-x86;osx.10.12-x64;ubuntu.14.04-x64;ubuntu.16.04-x64;ubuntu.16.10-x64;centos.7-x64;rhel.7-x64;debian.8-x64;fedora.24-x64;opensuse.42.1-x64
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/NuGet.Config b/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/NuGet.Config
new file mode 100644
index 000000000..b283135ce
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/Program.cs b/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/Program.cs
new file mode 100644
index 000000000..042e99826
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithCorruptedLaunchSettings/Program.cs
@@ -0,0 +1,26 @@
+// 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 MSBuildTestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ if (args.Length > 0)
+ {
+ Console.WriteLine("echo args:" + string.Join(";", args));
+ }
+ string message = Environment.GetEnvironmentVariable("Message");
+
+ if (string.IsNullOrEmpty(message))
+ {
+ message = "(NO MESSAGE)";
+ }
+
+ Console.WriteLine(message);
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/MSBuildTestAppWithLaunchSettings.csproj b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/MSBuildTestAppWithLaunchSettings.csproj
new file mode 100644
index 000000000..79bceb82d
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/MSBuildTestAppWithLaunchSettings.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+ Exe
+ netcoreapp2.0
+ win7-x64;win7-x86;osx.10.12-x64;ubuntu.14.04-x64;ubuntu.16.04-x64;ubuntu.16.10-x64;centos.7-x64;rhel.7-x64;debian.8-x64;fedora.24-x64;opensuse.42.1-x64
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/NuGet.Config b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/NuGet.Config
new file mode 100644
index 000000000..b283135ce
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/Program.cs b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/Program.cs
new file mode 100644
index 000000000..042e99826
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettings/Program.cs
@@ -0,0 +1,26 @@
+// 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 MSBuildTestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ if (args.Length > 0)
+ {
+ Console.WriteLine("echo args:" + string.Join(";", args));
+ }
+ string message = Environment.GetEnvironmentVariable("Message");
+
+ if (string.IsNullOrEmpty(message))
+ {
+ message = "(NO MESSAGE)";
+ }
+
+ Console.WriteLine(message);
+ }
+ }
+}
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/MSBuildTestAppWithLaunchSettingsWithoutDefault.csproj b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/MSBuildTestAppWithLaunchSettingsWithoutDefault.csproj
new file mode 100644
index 000000000..79bceb82d
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/MSBuildTestAppWithLaunchSettingsWithoutDefault.csproj
@@ -0,0 +1,14 @@
+
+
+
+
+ Exe
+ netcoreapp2.0
+ win7-x64;win7-x86;osx.10.12-x64;ubuntu.14.04-x64;ubuntu.16.04-x64;ubuntu.16.10-x64;centos.7-x64;rhel.7-x64;debian.8-x64;fedora.24-x64;opensuse.42.1-x64
+
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/NuGet.Config b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/NuGet.Config
new file mode 100644
index 000000000..b283135ce
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/Program.cs b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/Program.cs
new file mode 100644
index 000000000..042e99826
--- /dev/null
+++ b/TestAssets/TestProjects/MSBuildTestAppWithLaunchSettingsWithoutDefault/Program.cs
@@ -0,0 +1,26 @@
+// 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 MSBuildTestApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ if (args.Length > 0)
+ {
+ Console.WriteLine("echo args:" + string.Join(";", args));
+ }
+ string message = Environment.GetEnvironmentVariable("Message");
+
+ if (string.IsNullOrEmpty(message))
+ {
+ message = "(NO MESSAGE)";
+ }
+
+ Console.WriteLine(message);
+ }
+ }
+}
diff --git a/src/dotnet/commands/dotnet-run/LaunchSettings/LaunchSettingsManager.cs b/src/dotnet/commands/dotnet-run/LaunchSettings/LaunchSettingsManager.cs
index 64fba9446..6f76fa5b1 100644
--- a/src/dotnet/commands/dotnet-run/LaunchSettings/LaunchSettingsManager.cs
+++ b/src/dotnet/commands/dotnet-run/LaunchSettings/LaunchSettingsManager.cs
@@ -44,6 +44,12 @@ namespace Microsoft.DotNet.Tools.Run.LaunchSettings
else
{
profileObject = profilesObject[profileName] as JObject;
+
+ if (profileObject == null)
+ {
+ runAfterLaunch = null;
+ return false;
+ }
}
if (profileObject == null)
diff --git a/test/dotnet-run.Tests/GivenDotnetRunRunsCsProj.cs b/test/dotnet-run.Tests/GivenDotnetRunRunsCsProj.cs
index 8ce1730be..49cf9c3fe 100644
--- a/test/dotnet-run.Tests/GivenDotnetRunRunsCsProj.cs
+++ b/test/dotnet-run.Tests/GivenDotnetRunRunsCsProj.cs
@@ -2,6 +2,7 @@
// 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;
@@ -200,5 +201,267 @@ namespace Microsoft.DotNet.Cli.Run.Tests
.Pass()
.And.HaveStdOutContaining("echo args:foo;bar;baz");
}
+
+ [Fact]
+ public void ItGivesAnErrorWhenAttemptingToUseALaunchProfileThatDoesNotExistWhenThereIsNoLaunchSettingsFile()
+ {
+ var testAppName = "MSBuildTestApp";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput("--launch-profile test")
+ .Should().Pass()
+ .And.HaveStdOutContaining("Hello World!")
+ .And.HaveStdErrContaining("The specified launch profile could not be located.");
+ }
+
+ [Fact]
+ public void ItUsesLaunchProfileOfTheSpecifiedName()
+ {
+ var testAppName = "MSBuildTestAppWithLaunchSettings";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ var cmd = new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput("--launch-profile Second");
+
+ cmd.Should().Pass()
+ .And.HaveStdOutContaining("Second");
+
+ cmd.StdErr.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void ItDefaultsToTheFirstUsableLaunchProfile()
+ {
+ var testAppName = "MSBuildTestAppWithLaunchSettings";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ var cmd = new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput();
+
+ cmd.Should().Pass()
+ .And.HaveStdOutContaining("First");
+
+ cmd.StdErr.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void ItGivesAnErrorWhenTheLaunchProfileNotFound()
+ {
+ var testAppName = "MSBuildTestAppWithLaunchSettings";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput("--launch-profile Third")
+ .Should().Pass()
+ .And.HaveStdOutContaining("(NO MESSAGE)")
+ .And.HaveStdErrContaining("The launch profile \"Third\" could not be applied.");
+ }
+
+ [Fact]
+ public void ItGivesAnErrorWhenTheLaunchProfileCanNotBeHandled()
+ {
+ var testAppName = "MSBuildTestAppWithLaunchSettings";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput("--launch-profile \"IIS Express\"")
+ .Should().Pass()
+ .And.HaveStdOutContaining("(NO MESSAGE)")
+ .And.HaveStdErrContaining("The launch profile \"IIS Express\" could not be applied.");
+ }
+
+ [Fact]
+ public void ItSkipsLaunchProfilesWhenTheSwitchIsSupplied()
+ {
+ var testAppName = "MSBuildTestAppWithLaunchSettings";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ var cmd = new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput("--no-launch-profile");
+
+ cmd.Should().Pass()
+ .And.HaveStdOutContaining("(NO MESSAGE)");
+
+ cmd.StdErr.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void ItSkipsLaunchProfilesWhenTheSwitchIsSuppliedWithoutErrorWhenThereAreNoLaunchSettings()
+ {
+ var testAppName = "MSBuildTestApp";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ var cmd = new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput("--no-launch-profile");
+
+ cmd.Should().Pass()
+ .And.HaveStdOutContaining("Hello World!");
+
+ cmd.StdErr.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void ItSkipsLaunchProfilesWhenThereIsNoUsableDefault()
+ {
+ var testAppName = "MSBuildTestAppWithLaunchSettingsWithoutDefault";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ var cmd = new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput();
+
+ cmd.Should().Pass()
+ .And.HaveStdOutContaining("(NO MESSAGE)")
+ .And.HaveStdErrContaining("The launch profile \"(Default)\" could not be applied.");
+ }
+
+ [Fact]
+ public void ItPrintsAnErrorWhenLaunchSettingsArCorrupted()
+ {
+ var testAppName = "MSBuildTestAppWithCorruptedLaunchSettings";
+ var testInstance = TestAssets.Get(testAppName)
+ .CreateInstance()
+ .WithSourceFiles();
+
+ var testProjectDirectory = testInstance.Root.FullName;
+
+ new RestoreCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute("/p:SkipInvalidConfigurations=true")
+ .Should().Pass();
+
+ new BuildCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .Execute()
+ .Should().Pass();
+
+ var cmd = new RunCommand()
+ .WithWorkingDirectory(testProjectDirectory)
+ .ExecuteWithCapturedOutput();
+
+ cmd.Should().Pass()
+ .And.HaveStdOutContaining("(NO MESSAGE)")
+ .And.HaveStdErrContaining("The launch profile \"(Default)\" could not be applied.");
+ }
}
}