StartupObject has different behavior when running from command line than when modifying CSPROJ file

I just stumbled across the StartupObject parameter for MSBuild, which allows for explicit specification of a projects entry point. Based on this question it looks like there are two ways to specify this parameters:

  • In the CSPROJ file for the given project
  • Specifying as an MSBuild property using dotnet CLI.

I’m interested in the second option, so I made a simple console application with two files, First.cs and Second.cs:

First.cs

using System;

internal class First
{
    static void Main(string[] args)
    {
        Console.WriteLine("First");
    }
}

Second

using System;

internal class Second
{
    static void Main(string[] args)
    {
        Console.WriteLine("Second");
    }
}

What I found out is that specifying StartupObject via the dotnet CLI will call the correct startup object only if running from a clean slate:

PS> dotnet run --project=test_multiple_entry -p:StartupObject=First
First
PS> dotnet run --project=test_multiple_entry -p:StartupObject=Second
First
PS> dotnet clean test_multiple_entry
...
PS> dotnet run --project=test_multiple_entry -p:StartupObject=Second
Second

On the other hand, if I actually modify the entry point from the CSPROJ file, no dotnet clean is necessary, and it will automatically go find the correct entry point.

I’m curious as to whether this behavior is intentional? Why does dotnet run not use the correct entry point unless preceded by a dotnet clean? Why does modifying the CSPROJ file directly simply work?

>Solution :

StartupObject is a build property, not a runtime property. When dotnet run sees that a build is required (such as a source file (including the csproj) is newer than the build output, or there’s no build output (after dotnet clean)) then it cascades to dotnet build first, and passes through all the -p arguments to the build.

Leave a Reply