diff --git a/src/extension/VSProject.cs b/src/extension/VSProject.cs index 9ce33e9..3659c99 100644 --- a/src/extension/VSProject.cs +++ b/src/extension/VSProject.cs @@ -46,13 +46,15 @@ public class VSProject : IProject /// /// VS Project extentions /// - private static readonly string[] PROJECT_EXTENSIONS = { ".csproj", ".vbproj", ".vjsproj", ".vcproj", ".fsproj" }; - + private static readonly string[] PROJECT_EXTENSIONS = { ".csproj", ".vbproj", ".vjsproj", ".vcproj", ".fsproj" }; + /// /// VS Solution extension /// private const string SOLUTION_EXTENSION = ".sln"; + private static readonly Regex netFramework = new Regex("^net[1-9]"); + /// /// The XML representation of the project /// @@ -125,10 +127,10 @@ public TestPackage GetTestPackage(string configName) { var config = _configs[name]; package.AddSubPackage(new TestPackage(config.AssemblyPath)); - appbase = config.OutputDirectory; - + appbase = config.OutputDirectory; + break; - } + } } if (appbase != null) @@ -159,8 +161,8 @@ public static bool IsProjectFile(string path) return false; if (path.ToLower().IndexOf("http:") >= 0) - return false; - + return false; + string extension = Path.GetExtension(path); foreach (string validExtension in PROJECT_EXTENSIONS) @@ -184,7 +186,7 @@ public static bool IsSolutionFile(string path) /// private void Load() { - if (!IsProjectFile(ProjectPath)) + if (!IsProjectFile(ProjectPath)) ThrowInvalidFileType(ProjectPath); StreamReader rdr = new StreamReader(ProjectPath, System.Text.Encoding.UTF8); @@ -240,17 +242,42 @@ private void Load() /// is only called for file extensions .csproj. /// /// True if the project was successfully loaded, false otherwise. - private bool TryLoadDotNetCoreProject() + private bool TryLoadDotNetCoreProject() { XmlNode root = _doc.SelectSingleNode("Project"); - if (root != null && SafeAttributeValue(root, "Sdk") != null) + if (root != null && SafeAttributeValue(root, "Sdk") != null) { string targetFramework = _doc.SelectSingleNode("Project/PropertyGroup/TargetFramework").InnerText; XmlNode assemblyNameNode = _doc.SelectSingleNode("Project/PropertyGroup/AssemblyName"); - // Even console apps are dll's even if has value 'EXE' - string assemblyName = assemblyNameNode == null ? $"{Name}.dll" : $"{assemblyNameNode.InnerText}.dll"; + + // Even console apps are dll's even if has value 'EXE', + // if TargetFramework is netcore + string outputType = "dll"; + + if (netFramework.IsMatch(targetFramework)) + { + // When targetting standard .Net framework, the default is still dll, + // however, OutputType is now honoured. + // Also if Sdk = 'Microsoft.NET.Sdk.Web' then OutputType default is exe + string sdk = root.Attributes["Sdk"].Value; + + if (sdk == "Microsoft.NET.Sdk.Web") + { + outputType = "exe"; + } + else + { + XmlNode outputTypeNode = _doc.SelectSingleNode("Project/PropertyGroup/OutputType"); + if (outputTypeNode != null && outputTypeNode.InnerText != "Library") + { + outputType = "exe"; + } + } + } + + string assemblyName = assemblyNameNode == null ? $"{Name}.{outputType}" : $"{assemblyNameNode.InnerText}.{outputType}"; XmlNodeList nodes = _doc.SelectNodes("/Project/PropertyGroup"); @@ -360,7 +387,7 @@ private void LoadMSBuildProject() else assemblyName = assemblyName + ".dll"; - string commonOutputPath = null; + string commonOutputPath = null; var explicitOutputPaths = new Dictionary(); foreach (XmlElement configNode in nodes) @@ -374,20 +401,19 @@ private void LoadMSBuildProject() if (name == null) { - if (outputPathElement != null) + if (outputPathElement != null) commonOutputPath = outputPath; continue; } - - if (outputPathElement != null) - explicitOutputPaths[name] = outputPath; + + if (outputPathElement != null) + explicitOutputPaths[name] = outputPath; if (outputPath == null) outputPath = explicitOutputPaths.ContainsKey(name) ? explicitOutputPaths[name] : commonOutputPath; if (outputPath != null) - _configs[name] = new ProjectConfig(this, name, outputPath.Replace("$(Configuration)", name), assemblyName); - + _configs[name] = new ProjectConfig(this, name, outputPath.Replace("$(Configuration)", name), assemblyName); } } diff --git a/src/tests/VisualStudioProjectLoaderTests.cs b/src/tests/VisualStudioProjectLoaderTests.cs index 3a02134..e52a6d6 100644 --- a/src/tests/VisualStudioProjectLoaderTests.cs +++ b/src/tests/VisualStudioProjectLoaderTests.cs @@ -161,8 +161,18 @@ public void PicksUpCorrectOutputPath(string resourceName, string configuration, } } - [TestCase("netcoreapp1.1-minimal.csproj", "netcoreapp1.1-minimal")] - [TestCase("netcoreapp1.1-with-assembly-name.csproj", "the-assembly-name")] + [TestCase("netcoreapp1.1-minimal.csproj", "netcoreapp1.1-minimal.dll")] + [TestCase("netcoreapp1.1-with-assembly-name.csproj", "the-assembly-name.dll")] + [TestCase("netcoreapp2.0-minimal-dll.csproj", "netcoreapp2.0-minimal-dll.dll")] + [TestCase("netcoreapp2.0-minimal-exe.csproj", "netcoreapp2.0-minimal-exe.dll")] + [TestCase("netcoreapp2.0-minimal-web.csproj", "netcoreapp2.0-minimal-web.dll")] + [TestCase("netcoreapp2.0-with-assembly-name-exe.csproj", "the-assembly-name.dll")] + [TestCase("netcorefmwk-minimal-exe.csproj", "netcorefmwk-minimal-exe.exe")] + [TestCase("netcorefmwk-minimal-web.csproj", "netcorefmwk-minimal-web.exe")] + [TestCase("netcorefmwk-with-assembly-name-dll.csproj", "the-assembly-name.dll")] + [TestCase("netcorefmwk-with-assembly-name-exe.csproj", "the-assembly-name.exe")] + [TestCase("netstd2.0-minimal-dll.csproj", "netstd2.0-minimal-dll.dll")] + [TestCase("netstd2.0-minimal-exe.csproj", "netstd2.0-minimal-exe.dll")] public void PicksUpCorrectAssemblyName(string resourceName, string expectedAssemblyName) { using (TestResource file = new TestResource(resourceName)) @@ -173,7 +183,7 @@ public void PicksUpCorrectAssemblyName(string resourceName, string expectedAssem { TestPackage package = project.GetTestPackage(config); - Assert.That(Path.GetFileNameWithoutExtension(package.SubPackages[0].FullName) == expectedAssemblyName); + Assert.That(Path.GetFileName(package.SubPackages[0].FullName) == expectedAssemblyName); } } } diff --git a/src/tests/resources/netcoreapp2.0-minimal-dll.csproj b/src/tests/resources/netcoreapp2.0-minimal-dll.csproj new file mode 100644 index 0000000..509d9cb --- /dev/null +++ b/src/tests/resources/netcoreapp2.0-minimal-dll.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp2.0 + + + diff --git a/src/tests/resources/netcoreapp2.0-minimal-exe.csproj b/src/tests/resources/netcoreapp2.0-minimal-exe.csproj new file mode 100644 index 0000000..8e047a0 --- /dev/null +++ b/src/tests/resources/netcoreapp2.0-minimal-exe.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.0 + + + diff --git a/src/tests/resources/netcoreapp2.0-minimal-web.csproj b/src/tests/resources/netcoreapp2.0-minimal-web.csproj new file mode 100644 index 0000000..90af93e --- /dev/null +++ b/src/tests/resources/netcoreapp2.0-minimal-web.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.0 + + + + + + + + + + + diff --git a/src/tests/resources/netcoreapp2.0-with-assembly-name-exe.csproj b/src/tests/resources/netcoreapp2.0-with-assembly-name-exe.csproj new file mode 100644 index 0000000..a3b21ce --- /dev/null +++ b/src/tests/resources/netcoreapp2.0-with-assembly-name-exe.csproj @@ -0,0 +1,11 @@ + + + + WinExe + netcoreapp2.1 + + + the-assembly-name + + + diff --git a/src/tests/resources/netcorefmwk-minimal-exe.csproj b/src/tests/resources/netcorefmwk-minimal-exe.csproj new file mode 100644 index 0000000..aae2487 --- /dev/null +++ b/src/tests/resources/netcorefmwk-minimal-exe.csproj @@ -0,0 +1,8 @@ + + + + Exe + net461 + + + diff --git a/src/tests/resources/netcorefmwk-minimal-web.csproj b/src/tests/resources/netcorefmwk-minimal-web.csproj new file mode 100644 index 0000000..c6b6567 --- /dev/null +++ b/src/tests/resources/netcorefmwk-minimal-web.csproj @@ -0,0 +1,15 @@ + + + + net461 + + + + + + + + + + + diff --git a/src/tests/resources/netcorefmwk-with-assembly-name-dll.csproj b/src/tests/resources/netcorefmwk-with-assembly-name-dll.csproj new file mode 100644 index 0000000..0a49358 --- /dev/null +++ b/src/tests/resources/netcorefmwk-with-assembly-name-dll.csproj @@ -0,0 +1,11 @@ + + + + net461 + + Library + + the-assembly-name + + + diff --git a/src/tests/resources/netcorefmwk-with-assembly-name-exe.csproj b/src/tests/resources/netcorefmwk-with-assembly-name-exe.csproj new file mode 100644 index 0000000..ecf81fe --- /dev/null +++ b/src/tests/resources/netcorefmwk-with-assembly-name-exe.csproj @@ -0,0 +1,11 @@ + + + + WinExe + net461 + the-assembly-name + + + + + diff --git a/src/tests/resources/netstd2.0-minimal-dll.csproj b/src/tests/resources/netstd2.0-minimal-dll.csproj new file mode 100644 index 0000000..72764a6 --- /dev/null +++ b/src/tests/resources/netstd2.0-minimal-dll.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/src/tests/resources/netstd2.0-minimal-exe.csproj b/src/tests/resources/netstd2.0-minimal-exe.csproj new file mode 100644 index 0000000..7c5d6f5 --- /dev/null +++ b/src/tests/resources/netstd2.0-minimal-exe.csproj @@ -0,0 +1,10 @@ + + + + netstandard2.0 + + Exe + + + + diff --git a/src/tests/vs-project-loader.tests.csproj b/src/tests/vs-project-loader.tests.csproj index 6d5587e..3f3d071 100644 --- a/src/tests/vs-project-loader.tests.csproj +++ b/src/tests/vs-project-loader.tests.csproj @@ -115,15 +115,33 @@ + + + + + + + + + + + + + + + + + + - \ No newline at end of file