Auto-generate main method from referenced assembly

  • It's just Microsoft.NET.Test.Sdk making build fail.
  • Adding <GenerateProgramFile>false</GenerateProgramFile> into <PropertyGroup> makes it compile and work anyway.
  • But adding another class with static void Main to the application makes build fail again regardless <GenerateProgramFile>.
  • In your example build fails because Microsoft.NET.Test.Sdk adds some auto-generated code to your application before compilation. That code is in ...\.nuget\packages\microsoft.net.test.sdk\16.2.0\build\netcoreapp1.0\Microsoft.NET.Test.Sdk.Program.cs. It's a class with another Main:

// <auto-generated> This file has been auto generated. </auto-generated>
using System;
[Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
class AutoGeneratedProgram {static void Main(string[] args){}}

BTW: it's absolutely legal to have Main method in another assembly. You just cannot have 2 Mains in one exe. But you can have any number of them in dll like this:

public class Class1
{
    public static void Main() { }

    public static void Main(string[] args) { }
}

public class Class2
{
    public static void Main() { }

    public static void Main(string[] args) { }
}

It compiles.


Update:

I found the solution. It's all about installing nuget, not just adding a reference.

  1. Create a .NET Core Class Library and name it MyCoreLib.
  2. Add MyCoreClass.

namespace MyCoreLib
{
    public static class MyCoreClass
    {
        public static void Initialize()
        {
            System.Console.WriteLine("Initialized from 'MyCoreLib'");
        }
    }
}

  1. Build the library.
  2. Create the following file structure:

├───nuget
└───src
    │   MyCoreLib.nuspec
    │
    ├───build
    │   └───netcoreapp2.1
    │           ForcedEntryPoint.cs
    │           MyCoreLib.targets
    │
    └───lib
        └───netcoreapp2.1
                MyCoreLib.dll

MyCoreLib.nuspec

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata>
    <id>MyCoreLib</id>
    <version>1.0.0</version>
    <authors>MyCoreLib</authors>
    <owners>MyCoreLib</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Some description here</description>
    <dependencies>
      <group targetFramework=".NETCoreApp2.1" />
    </dependencies>
  </metadata>
</package>

ForcedEntryPoint.cs

//╔════════════════════════════════════╗
//║ This code was added automatically. ║
//║    Do not change or remove it.     ║
//╚════════════════════════════════════╝
public static class ForcedEntryPoint
{
    public static void Main(string[] args)
    {
        MyCoreLib.MyCoreClass.Initialize();
    }
}

MyCoreLib.targets

<Project InitialTargets="ForceEntryPoint" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <PropertyGroup>
    <ForcedEntryPoint Condition="'$(ForcedEntryPoint)' == ''">$(MSBuildThisFileDirectory)ForcedEntryPoint$(DefaultLanguageSourceExtension)</ForcedEntryPoint>
    <ForceEntryPoint Condition="'$(ForceEntryPoint)' == ''">true</ForceEntryPoint>
  </PropertyGroup>
  <Target Name="ForceEntryPoint" Condition="'$(ForceEntryPoint)' == 'true'">
    <ItemGroup>
      <Compile Include="$(ForcedEntryPoint)"/>
    </ItemGroup>
  </Target>
</Project>

  1. Use NuGet Commandline to build a package like this:

D:\nugetwalkthrough\nuget>D:\nugetwalkthrough\nuget.exe pack D:\nugetwalkthrough\src\MyCoreLib.nuspec

  1. Create a .NET Core Console App and make sure it works.
  2. Install the created package.
  3. Try to run the application and get error:

    CS0017 Program has more than one entry point defined. Compile with /main to specify the type that contains the entry point.

  4. Remove the Main method from the application, run it and see it prints Initialized from 'MyCoreLib'.
  5. Put the Main method back to the application and change the project file so that <PropertyGroup> contains <ForceEntryPoint>false</ForceEntryPoint>
  6. Now it compiles and prints Hello World! from its own Main method.
  7. Changing <ForceEntryPoint> to true makes it use another entry point (not that one of the application) again.

I think you should learn how to make multiple project under same solution. So helloworld is main project. Then create new test project helloworld.test as test project use Add a reference to NUnit there. now all will work fine you can change your start up project to helloworld.test and debug or run it from visual studio or command line. Anyway I never saw a test project inside main project in professional coding. May be for testing we comment main method and run test case. Test project is also Executable.