diff --git a/Directory.Packages.props b/Directory.Packages.props
index abe2e9e23b4c..1c3a58cfaad6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -18,6 +18,7 @@
     
     
     
+    
     
     
     
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 807d3bca9f87..a6b7ec8cf620 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -96,6 +96,10 @@
       https://github.com/dotnet/dotnet
       1add0c55b8beeb1b1de4d81e362fad8978c4c8c8
     
+    
+      https://github.com/dotnet/dotnet
+      1add0c55b8beeb1b1de4d81e362fad8978c4c8c8
+    
     
       https://github.com/dotnet/dotnet
       1add0c55b8beeb1b1de4d81e362fad8978c4c8c8
diff --git a/eng/Versions.props b/eng/Versions.props
index ca8e8e77b973..a882d60b1295 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -218,6 +218,7 @@
     5.0.0-2.25373.106
     5.0.0-2.25373.106
     5.0.0-2.25373.106
+    5.0.0-2.25373.106
     5.0.0-2.25373.106
     5.0.0-2.25373.106
     5.0.0-2.25373.106
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs
index d5dd7f30c73a..a8bcca667ff9 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs
@@ -86,12 +86,12 @@ private static IEnumerable EscapeArgArrayForCmd(IEnumerable argu
         return escapedArgs;
     }
 
-    public static string EscapeSingleArg(string arg)
+    public static string EscapeSingleArg(string arg, Func? additionalShouldSurroundWithQuotes = null)
     {
         var sb = new StringBuilder();
 
         var length = arg.Length;
-        var needsQuotes = length == 0 || ShouldSurroundWithQuotes(arg);
+        var needsQuotes = length == 0 || ShouldSurroundWithQuotes(arg) || additionalShouldSurroundWithQuotes?.Invoke(arg) == true;
         var isQuoted = needsQuotes || IsSurroundedWithQuotes(arg);
 
         if (needsQuotes) sb.Append("\"");
diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Product.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Product.cs
index 8d61c427aace..60f6aaf151f5 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/Product.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Product.cs
@@ -5,18 +5,32 @@
 
 namespace Microsoft.DotNet.Cli.Utils;
 
-public class Product
+public static class Product
 {
     public static string LongName => LocalizableStrings.DotNetSdkInfo;
-    public static readonly string Version = GetProductVersion();
+    public static readonly string Version;
+    public static readonly string TargetFrameworkVersion;
 
-    private static string GetProductVersion()
+    static Product()
     {
         DotnetVersionFile versionFile = DotnetFiles.VersionFileObject;
-        return versionFile.BuildNumber ??
+        Version = versionFile.BuildNumber ??
                 System.Diagnostics.FileVersionInfo.GetVersionInfo(
                         typeof(Product).GetTypeInfo().Assembly.Location)
                     .ProductVersion ??
                 string.Empty;
+
+        int firstDotIndex = Version.IndexOf('.');
+        if (firstDotIndex >= 0)
+        {
+            int secondDotIndex = Version.IndexOf('.', firstDotIndex + 1);
+            TargetFrameworkVersion = secondDotIndex >= 0
+                ? Version.Substring(0, secondDotIndex)
+                : Version;
+        }
+        else
+        {
+            TargetFrameworkVersion = string.Empty;
+        }
     }
 }
diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx
index 633b991c9644..2a62ba8ec28d 100644
--- a/src/Cli/dotnet/Commands/CliCommandStrings.resx
+++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx
@@ -1611,9 +1611,13 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man
     {0} is an option name like '--source'.
   
   
-    Warning: Binary log option was specified but build will be skipped because output is up to date, specify '--no-cache' to force build.
+    Warning: Binary log option was specified but build will be skipped because output is up to date. Specify '--no-cache' to force build.
     {Locked="--no-cache"}
   
+  
+    Warning: Binary log option was specified but MSBuild will be skipped because running just csc is enough. Specify '--no-cache' to force full build.
+    {Locked="--no-cache"}{Locked="MSBuild"}{Locked="csc"}
+  
   
     Publisher for the .NET Platform
   
diff --git a/src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.Generated.cs b/src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.Generated.cs
new file mode 100644
index 000000000000..51cc8774cceb
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.Generated.cs
@@ -0,0 +1,236 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.DotNet.Cli.Commands.Run;
+
+// Generated by test `RunFileTests.CscArguments`.
+partial class CSharpCompilerCommand
+{
+    private IEnumerable GetCscArguments(
+        string fileNameWithoutExtension,
+        string objDir,
+        string binDir)
+    {
+        return
+        [
+            "/unsafe-",
+            "/checked-",
+            "/nowarn:1701,1702,IL2121,1701,1702",
+            "/fullpaths",
+            "/nostdlib+",
+            "/errorreport:prompt",
+            "/warn:10",
+            "/define:TRACE;DEBUG;NET;NET10_0;NETCOREAPP;NET5_0_OR_GREATER;NET6_0_OR_GREATER;NET7_0_OR_GREATER;NET8_0_OR_GREATER;NET9_0_OR_GREATER;NET10_0_OR_GREATER;NETCOREAPP1_0_OR_GREATER;NETCOREAPP1_1_OR_GREATER;NETCOREAPP2_0_OR_GREATER;NETCOREAPP2_1_OR_GREATER;NETCOREAPP2_2_OR_GREATER;NETCOREAPP3_0_OR_GREATER;NETCOREAPP3_1_OR_GREATER",
+            "/highentropyva+",
+            "/nullable:enable",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/Microsoft.CSharp.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/Microsoft.VisualBasic.Core.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/Microsoft.VisualBasic.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/Microsoft.Win32.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/Microsoft.Win32.Registry.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/mscorlib.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/netstandard.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.AppContext.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Buffers.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Collections.Concurrent.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Collections.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Collections.Immutable.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Collections.NonGeneric.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Collections.Specialized.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ComponentModel.Annotations.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ComponentModel.DataAnnotations.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ComponentModel.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ComponentModel.EventBasedAsync.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ComponentModel.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ComponentModel.TypeConverter.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Configuration.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Console.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Core.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Data.Common.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Data.DataSetExtensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Data.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.Contracts.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.Debug.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.DiagnosticSource.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.FileVersionInfo.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.Process.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.StackTrace.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.TextWriterTraceListener.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.Tools.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.TraceSource.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Diagnostics.Tracing.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Drawing.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Drawing.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Dynamic.Runtime.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Formats.Asn1.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Formats.Tar.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Globalization.Calendars.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Globalization.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Globalization.Extensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Compression.Brotli.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Compression.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Compression.FileSystem.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Compression.ZipFile.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.FileSystem.AccessControl.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.FileSystem.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.FileSystem.DriveInfo.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.FileSystem.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.FileSystem.Watcher.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.IsolatedStorage.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.MemoryMappedFiles.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Pipelines.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Pipes.AccessControl.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.Pipes.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.IO.UnmanagedMemoryStream.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Linq.AsyncEnumerable.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Linq.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Linq.Expressions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Linq.Parallel.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Linq.Queryable.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Memory.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Http.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Http.Json.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.HttpListener.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Mail.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.NameResolution.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.NetworkInformation.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Ping.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Quic.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Requests.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Security.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.ServerSentEvents.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.ServicePoint.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.Sockets.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.WebClient.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.WebHeaderCollection.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.WebProxy.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.WebSockets.Client.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Net.WebSockets.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Numerics.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Numerics.Vectors.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ObjectModel.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.DispatchProxy.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.Emit.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.Emit.ILGeneration.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.Emit.Lightweight.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.Extensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.Metadata.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Reflection.TypeExtensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Resources.Reader.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Resources.ResourceManager.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Resources.Writer.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.CompilerServices.Unsafe.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.CompilerServices.VisualC.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Extensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Handles.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.InteropServices.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.InteropServices.JavaScript.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.InteropServices.RuntimeInformation.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Intrinsics.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Loader.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Numerics.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Serialization.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Serialization.Formatters.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Serialization.Json.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Serialization.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Runtime.Serialization.Xml.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.AccessControl.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Claims.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.Algorithms.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.Cng.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.Csp.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.Encoding.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.OpenSsl.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.Primitives.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Cryptography.X509Certificates.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Principal.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.Principal.Windows.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Security.SecureString.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ServiceModel.Web.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ServiceProcess.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Text.Encoding.CodePages.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Text.Encoding.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Text.Encoding.Extensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Text.Encodings.Web.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Text.Json.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Text.RegularExpressions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.AccessControl.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Channels.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Overlapped.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Tasks.Dataflow.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Tasks.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Tasks.Extensions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Tasks.Parallel.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Thread.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.ThreadPool.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Threading.Timer.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Transactions.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Transactions.Local.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.ValueTuple.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Web.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Web.HttpUtility.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Windows.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.Linq.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.ReaderWriter.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.Serialization.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.XDocument.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.XmlDocument.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.XmlSerializer.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.XPath.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/System.Xml.XPath.XDocument.dll",
+            $"/reference:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/ref/net10.0/WindowsBase.dll",
+            "/debug+",
+            "/debug:portable",
+            "/filealign:512",
+            "/optimize-",
+            $"/out:{binDir}/{fileNameWithoutExtension}.dll",
+            "/target:exe",
+            "/warnaserror-",
+            "/utf8output",
+            "/deterministic+",
+            "/langversion:13.0",
+            "/features:FileBasedProgram",
+            $"/analyzerconfig:{SdkPath}/Sdks/Microsoft.NET.Sdk/codestyle/cs/build/config/analysislevelstyle_default.globalconfig",
+            $"/analyzerconfig:{objDir}/{fileNameWithoutExtension}.GeneratedMSBuildEditorConfig.editorconfig",
+            $"/analyzerconfig:{SdkPath}/Sdks/Microsoft.NET.Sdk/analyzers/build/config/analysislevel_10_default.globalconfig",
+            $"/analyzer:{SdkPath}/Sdks/Microsoft.NET.Sdk/targets/../analyzers/Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll",
+            $"/analyzer:{SdkPath}/Sdks/Microsoft.NET.Sdk/targets/../analyzers/Microsoft.CodeAnalysis.NetAnalyzers.dll",
+            $"/analyzer:{NuGetCachePath}/microsoft.net.illink.tasks/{RuntimeVersion}/analyzers/dotnet/cs/ILLink.CodeFixProvider.dll",
+            $"/analyzer:{NuGetCachePath}/microsoft.net.illink.tasks/{RuntimeVersion}/analyzers/dotnet/cs/ILLink.RoslynAnalyzer.dll",
+            $"/analyzer:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/analyzers/dotnet/cs/Microsoft.Interop.ComInterfaceGenerator.dll",
+            $"/analyzer:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/analyzers/dotnet/cs/Microsoft.Interop.JavaScript.JSImportGenerator.dll",
+            $"/analyzer:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/analyzers/dotnet/cs/Microsoft.Interop.LibraryImportGenerator.dll",
+            $"/analyzer:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/analyzers/dotnet/cs/Microsoft.Interop.SourceGeneration.dll",
+            $"/analyzer:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/analyzers/dotnet/cs/System.Text.Json.SourceGeneration.dll",
+            $"/analyzer:{DotNetRootPath}/packs/Microsoft.NETCore.App.Ref/{RuntimeVersion}/analyzers/dotnet/cs/System.Text.RegularExpressions.Generator.dll",
+            $"{EntryPointFileFullPath}",
+            $"{objDir}/{fileNameWithoutExtension}.GlobalUsings.g.cs",
+            $"{objDir}/.NETCoreApp,Version=v10.0.AssemblyAttributes.cs",
+            $"{objDir}/{fileNameWithoutExtension}.AssemblyInfo.cs",
+            "/warnaserror+:NU1605,SYSLIB0011",
+        ];
+    }
+
+    /// 
+    /// Files that come from referenced NuGet packages (e.g., analyzers for NativeAOT) need to be checked specially (if they don't exist, MSBuild needs to run).
+    /// 
+    public static IEnumerable GetPathsOfCscInputsFromNuGetCache()
+    {
+        return
+        [
+            $"{NuGetCachePath}/microsoft.net.illink.tasks/{RuntimeVersion}/analyzers/dotnet/cs/ILLink.CodeFixProvider.dll",
+            $"{NuGetCachePath}/microsoft.net.illink.tasks/{RuntimeVersion}/analyzers/dotnet/cs/ILLink.RoslynAnalyzer.dll",
+        ];
+    }
+}
diff --git a/src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.cs b/src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.cs
new file mode 100644
index 000000000000..faf6829896d6
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Run/CSharpCompilerCommand.cs
@@ -0,0 +1,357 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Buffers;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Text.Json;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CommandLine;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.DotNet.Cli.Utils.Extensions;
+using Microsoft.NET.HostModel.AppHost;
+using NuGet.Configuration;
+
+namespace Microsoft.DotNet.Cli.Commands.Run;
+
+/// 
+/// Used to invoke C# compiler in some optimized paths of dotnet run file.cs.
+/// 
+internal sealed partial class CSharpCompilerCommand
+{
+    private static readonly SearchValues s_additionalShouldSurroundWithQuotes = SearchValues.Create('=', ',');
+
+    /// 
+    /// Options which denote paths and which might appear in the simple app compilation that we optimize for.
+    /// 
+    private static readonly ImmutableArray s_pathOptions =
+    [
+        "reference:",
+        "analyzer:",
+        "additionalfile:",
+        "analyzerconfig:",
+        "embed:",
+        "resource:",
+        "linkresource:",
+        "ruleset:",
+        "keyfile:",
+        "link:",
+    ];
+
+    private static string SdkPath => field ??= PathUtility.EnsureNoTrailingDirectorySeparator(AppContext.BaseDirectory);
+    private static string DotNetRootPath => field ??= Path.GetDirectoryName(Path.GetDirectoryName(SdkPath)!)!;
+    private static string ClientDirectory => field ??= Path.Combine(SdkPath, "Roslyn", "bincore");
+    private static string NuGetCachePath => field ??= SettingsUtility.GetGlobalPackagesFolder(Settings.LoadDefaultSettings(null));
+    internal static string RuntimeVersion => field ??= RuntimeInformation.FrameworkDescription.Split(' ').Last();
+    private static string TargetFrameworkVersion => Product.TargetFrameworkVersion;
+
+    public required string EntryPointFileFullPath { get; init; }
+    public required string ArtifactsPath { get; init; }
+    public required bool CanReuseAuxiliaryFiles { get; init; }
+
+    /// 
+    /// Whether the returned error code should not cause the build to fail but instead fallback to full MSBuild.
+    /// 
+    public int Execute(out bool fallbackToNormalBuild)
+    {
+        // Write .rsp file and other intermediate build outputs.
+        PrepareAuxiliaryFiles(out string rspPath);
+
+        // Create a request for the compiler server
+        // (this is much faster than starting a csc.dll process, especially on Windows).
+        var buildRequest = BuildServerConnection.CreateBuildRequest(
+            requestId: EntryPointFileFullPath,
+            language: RequestLanguage.CSharpCompile,
+            arguments: ["/noconfig", "/nologo", $"@{EscapeSingleArg(rspPath)}"],
+            workingDirectory: Environment.CurrentDirectory,
+            tempDirectory: Path.GetTempPath(),
+            keepAlive: null,
+            libDirectory: null,
+            compilerHash: GetCompilerCommitHash());
+
+        // Get pipe name.
+        var pipeName = BuildServerConnection.GetPipeName(clientDirectory: ClientDirectory);
+
+        // Create logger.
+        var logger = new CompilerServerLogger(
+            identifier: $"dotnet run file {Environment.ProcessId}",
+            loggingFilePath: null);
+
+        // Send the request.
+        var responseTask = BuildServerConnection.RunServerBuildRequestAsync(
+            buildRequest,
+            pipeName: pipeName,
+            clientDirectory: ClientDirectory,
+            logger,
+            cancellationToken: default);
+
+        // Process the response.
+        return ProcessBuildResponse(responseTask.Result, out fallbackToNormalBuild);
+
+        static string GetCompilerCommitHash()
+        {
+            return typeof(CSharpCompilation).Assembly.GetCustomAttributesData()
+                .FirstOrDefault(attr => attr.AttributeType.FullName == "Microsoft.CodeAnalysis.CommitHashAttribute")?
+                .ConstructorArguments
+                .FirstOrDefault()
+                .Value as string
+                ?? throw new InvalidOperationException("Could not find compiler commit hash in the assembly attributes.");
+        }
+
+        static int ProcessBuildResponse(BuildResponse response, out bool fallbackToNormalBuild)
+        {
+            switch (response)
+            {
+                case CompletedBuildResponse completed:
+                    Reporter.Verbose.WriteLine("Compiler server processed compilation.");
+                    Reporter.Output.Write(completed.Output);
+                    fallbackToNormalBuild = false;
+                    return completed.ReturnCode;
+
+                case IncorrectHashBuildResponse:
+                    Reporter.Error.WriteLine("Error: Compiler server reports a different hash version than the SDK.".Red());
+                    fallbackToNormalBuild = false;
+                    return 1;
+
+                case null:
+                    Reporter.Output.WriteLine("Warning: Could not launch the compiler server.".Yellow());
+                    fallbackToNormalBuild = true;
+                    return 1;
+
+                default:
+                    Reporter.Error.WriteLine($"Warning: Compiler server returned unexpected response: {response.GetType().Name}".Yellow());
+                    fallbackToNormalBuild = true;
+                    return 1;
+            }
+        }
+    }
+
+    private void PrepareAuxiliaryFiles(out string rspPath)
+    {
+        Reporter.Verbose.WriteLine(CanReuseAuxiliaryFiles
+            ? "CSC auxiliary files can be reused."
+            : "CSC auxiliary files can NOT be reused.");
+
+        string fileDirectory = Path.GetDirectoryName(EntryPointFileFullPath) ?? string.Empty;
+        string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(EntryPointFileFullPath);
+
+        // Note that Release builds won't go through this optimized code path because `-c Release` translates to global property `Configuration=Release`
+        // and customizing global properties triggers a full MSBuild run.
+        string objDir = Path.Join(ArtifactsPath, "obj", "debug");
+        Directory.CreateDirectory(objDir);
+        string binDir = Path.Join(ArtifactsPath, "bin", "debug");
+        Directory.CreateDirectory(binDir);
+
+        string assemblyAttributes = Path.Join(objDir, $".NETCoreApp,Version=v{TargetFrameworkVersion}.AssemblyAttributes.cs");
+        if (ShouldEmit(assemblyAttributes))
+        {
+            File.WriteAllText(assemblyAttributes, /* lang=C#-test */ $"""
+                // 
+                using System;
+                using System.Reflection;
+                [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v{TargetFrameworkVersion}", FrameworkDisplayName = ".NET {TargetFrameworkVersion}")]
+
+                """);
+        }
+
+        string globalUsings = Path.Join(objDir, $"{fileNameWithoutExtension}.GlobalUsings.g.cs");
+        if (ShouldEmit(globalUsings))
+        {
+            File.WriteAllText(globalUsings, /* lang=C#-test */ """
+                // 
+                global using System;
+                global using System.Collections.Generic;
+                global using System.IO;
+                global using System.Linq;
+                global using System.Net.Http;
+                global using System.Threading;
+                global using System.Threading.Tasks;
+
+                """);
+        }
+
+        string assemblyInfo = Path.Join(objDir, $"{fileNameWithoutExtension}.AssemblyInfo.cs");
+        if (ShouldEmit(assemblyInfo))
+        {
+            File.WriteAllText(assemblyInfo, /* lang=C#-test */ $"""
+                //------------------------------------------------------------------------------
+                // 
+                //     This code was generated by a tool.
+                //
+                //     Changes to this file may cause incorrect behavior and will be lost if
+                //     the code is regenerated.
+                // 
+                //------------------------------------------------------------------------------
+
+                using System;
+                using System.Reflection;
+
+                [assembly: System.Reflection.AssemblyCompanyAttribute("{fileNameWithoutExtension}")]
+                [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
+                [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
+                [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
+                [assembly: System.Reflection.AssemblyProductAttribute("{fileNameWithoutExtension}")]
+                [assembly: System.Reflection.AssemblyTitleAttribute("{fileNameWithoutExtension}")]
+                [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
+
+                // Generated by the MSBuild WriteCodeFragment class.
+
+
+                """);
+        }
+
+        string editorconfig = Path.Join(objDir, $"{fileNameWithoutExtension}.GeneratedMSBuildEditorConfig.editorconfig");
+        if (ShouldEmit(editorconfig))
+        {
+            File.WriteAllText(editorconfig, $"""
+                is_global = true
+                build_property.EnableAotAnalyzer = true
+                build_property.EnableSingleFileAnalyzer = true
+                build_property.EnableTrimAnalyzer = true
+                build_property.IncludeAllContentForSelfExtract = 
+                build_property.TargetFramework = net{TargetFrameworkVersion}
+                build_property.TargetFrameworkIdentifier = .NETCoreApp
+                build_property.TargetFrameworkVersion = v{TargetFrameworkVersion}
+                build_property.TargetPlatformMinVersion = 
+                build_property.UsingMicrosoftNETSdkWeb = 
+                build_property.ProjectTypeGuids = 
+                build_property.InvariantGlobalization = 
+                build_property.PlatformNeutralAssembly = 
+                build_property.EnforceExtendedAnalyzerRules = 
+                build_property._SupportedPlatformList = Linux,macOS,Windows
+                build_property.RootNamespace = {fileNameWithoutExtension}
+                build_property.ProjectDir = {fileDirectory}{Path.DirectorySeparatorChar}
+                build_property.EnableComHosting = 
+                build_property.EnableGeneratedComInterfaceComImportInterop = false
+                build_property.EffectiveAnalysisLevelStyle = {TargetFrameworkVersion}
+                build_property.EnableCodeStyleSeverity = 
+
+                """);
+        }
+
+        var apphostTarget = Path.Join(binDir, $"{fileNameWithoutExtension}{FileNameSuffixes.CurrentPlatform.Exe}");
+        if (ShouldEmit(apphostTarget))
+        {
+            var rid = RuntimeInformation.RuntimeIdentifier;
+            var apphostSource = Path.Join(SdkPath, "..", "..", "packs", $"Microsoft.NETCore.App.Host.{rid}", RuntimeVersion, "runtimes", rid, "native", $"apphost{FileNameSuffixes.CurrentPlatform.Exe}");
+            HostWriter.CreateAppHost(
+                appHostSourceFilePath: apphostSource,
+                appHostDestinationFilePath: apphostTarget,
+                appBinaryFilePath: $"{fileNameWithoutExtension}.dll",
+                enableMacOSCodeSign: OperatingSystem.IsMacOS());
+        }
+
+        var runtimeConfig = Path.Join(binDir, $"{fileNameWithoutExtension}{FileNameSuffixes.RuntimeConfigJson}");
+        if (ShouldEmit(runtimeConfig))
+        {
+            File.WriteAllText(runtimeConfig, $$"""
+                {
+                  "runtimeOptions": {
+                    "tfm": "net{{TargetFrameworkVersion}}",
+                    "framework": {
+                      "name": "Microsoft.NETCore.App",
+                      "version": {{JsonSerializer.Serialize(RuntimeVersion)}}
+                    },
+                    "configProperties": {
+                      "EntryPointFilePath": {{JsonSerializer.Serialize(EntryPointFileFullPath)}},
+                      "EntryPointFileDirectoryPath": {{JsonSerializer.Serialize(fileDirectory)}},
+                      "Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability": true,
+                      "System.ComponentModel.DefaultValueAttribute.IsSupported": false,
+                      "System.ComponentModel.Design.IDesignerHost.IsSupported": false,
+                      "System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization": false,
+                      "System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported": false,
+                      "System.Data.DataSet.XmlSerializationIsSupported": false,
+                      "System.Diagnostics.Tracing.EventSource.IsSupported": false,
+                      "System.Linq.Enumerable.IsSizeOptimized": true,
+                      "System.Net.SocketsHttpHandler.Http3Support": false,
+                      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+                      "System.Resources.ResourceManager.AllowCustomResourceTypes": false,
+                      "System.Resources.UseSystemResourceKeys": false,
+                      "System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported": false,
+                      "System.Runtime.InteropServices.BuiltInComInterop.IsSupported": false,
+                      "System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting": false,
+                      "System.Runtime.InteropServices.EnableCppCLIHostActivation": false,
+                      "System.Runtime.InteropServices.Marshalling.EnableGeneratedComInterfaceComImportInterop": false,
+                      "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false,
+                      "System.StartupHookProvider.IsSupported": false,
+                      "System.Text.Encoding.EnableUnsafeUTF7Encoding": false,
+                      "System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault": false,
+                      "System.Threading.Thread.EnableAutoreleasePool": false,
+                      "System.Linq.Expressions.CanEmitObjectArrayDelegate": false
+                    }
+                  }
+                }
+                """);
+        }
+
+        rspPath = Path.Join(ArtifactsPath, "csc.rsp");
+        if (ShouldEmit(rspPath))
+        {
+            IEnumerable args = GetCscArguments(
+                fileNameWithoutExtension: fileNameWithoutExtension,
+                objDir: objDir,
+                binDir: binDir);
+
+            File.WriteAllLines(rspPath, args.Select(EscapeSingleArg));
+        }
+
+        bool ShouldEmit(string file)
+        {
+            if (!CanReuseAuxiliaryFiles)
+            {
+                return true;
+            }
+
+            if (!File.Exists(file))
+            {
+                Reporter.Verbose.WriteLine($"Generating CSC auxiliary file because it does not exist: {file}");
+                return true;
+            }
+
+            return false;
+        }
+    }
+
+    private static string EscapeSingleArg(string arg)
+    {
+        if (IsPathOption(arg, out var colonIndex))
+        {
+            return arg[..(colonIndex + 1)] + EscapeCore(arg[(colonIndex + 1)..]);
+        }
+
+        return EscapeCore(arg);
+
+        static string EscapeCore(string arg)
+        {
+            return ArgumentEscaper.EscapeSingleArg(arg, additionalShouldSurroundWithQuotes: static (string arg) =>
+            {
+                return arg.ContainsAny(s_additionalShouldSurroundWithQuotes);
+            });
+        }
+    }
+
+    public static bool IsPathOption(string arg, out int colonIndex)
+    {
+        if (!arg.StartsWith('/'))
+        {
+            colonIndex = -1;
+            return false;
+        }
+
+        var span = arg.AsSpan(start: 1);
+        foreach (var optionName in s_pathOptions)
+        {
+            Debug.Assert(!optionName.StartsWith('/') && optionName.EndsWith(':'));
+
+            if (span.StartsWith(optionName, StringComparison.OrdinalIgnoreCase))
+            {
+                colonIndex = optionName.Length;
+                return true;
+            }
+        }
+
+        colonIndex = -1;
+        return false;
+    }
+}
diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs
index e33180e95cb6..8e2dcb570075 100644
--- a/src/Cli/dotnet/Commands/Run/RunCommand.cs
+++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs
@@ -294,8 +294,8 @@ private void EnsureProjectIsBuilt(out Func?
         if (EntryPointFileFullPath is not null)
         {
             var command = CreateVirtualCommand();
-            projectFactory = command.CreateProjectInstance;
             buildResult = command.Execute();
+            projectFactory = command.LastBuildLevel is BuildLevel.Csc ? null : command.CreateProjectInstance;
         }
         else
         {
@@ -348,6 +348,14 @@ private MSBuildArgs SetupSilentBuildArgs(MSBuildArgs msbuildArgs)
 
     internal ICommand GetTargetCommand(Func? projectFactory)
     {
+        if (projectFactory is null && ProjectFileFullPath is null)
+        {
+            // If we are running a file-based app and projectFactory is null, it means csc was used instead of full msbuild.
+            // So we can skip project evaluation to continue the optimized path.
+            Debug.Assert(EntryPointFileFullPath is not null);
+            return CreateCommandForCscBuiltProgram(EntryPointFileFullPath);
+        }
+
         FacadeLogger? logger = LoggerUtility.DetermineBinlogger([..MSBuildArgs.OtherMSBuildArgs], "dotnet-run");
         var project = EvaluateProject(ProjectFileFullPath, projectFactory, MSBuildArgs, logger);
         ValidatePreconditions(project);
@@ -402,15 +410,41 @@ static ICommand CreateCommandFromRunProperties(ProjectInstance project, RunPrope
             var command = CommandFactoryUsingResolver.Create(commandSpec)
                 .WorkingDirectory(runProperties.RunWorkingDirectory);
 
-            var rootVariableName = EnvironmentVariableNames.TryGetDotNetRootVariableName(
+            SetRootVariableName(
+                command,
                 project.GetPropertyValue("RuntimeIdentifier"),
                 project.GetPropertyValue("DefaultAppHostRuntimeIdentifier"),
                 project.GetPropertyValue("TargetFrameworkVersion"));
 
+            return command;
+        }
+
+        static void SetRootVariableName(ICommand command, string runtimeIdentifier, string defaultAppHostRuntimeIdentifier, string targetFrameworkVersion)
+        {
+            var rootVariableName = EnvironmentVariableNames.TryGetDotNetRootVariableName(
+                runtimeIdentifier,
+                defaultAppHostRuntimeIdentifier,
+                targetFrameworkVersion);
             if (rootVariableName != null && Environment.GetEnvironmentVariable(rootVariableName) == null)
             {
                 command.EnvironmentVariable(rootVariableName, Path.GetDirectoryName(new Muxer().MuxerPath));
             }
+        }
+
+        static ICommand CreateCommandForCscBuiltProgram(string entryPointFileFullPath)
+        {
+            var artifactsPath = VirtualProjectBuildingCommand.GetArtifactsPath(entryPointFileFullPath);
+            var exePath = Path.Join(artifactsPath, "bin", "debug", Path.GetFileNameWithoutExtension(entryPointFileFullPath) + FileNameSuffixes.CurrentPlatform.Exe);
+            var commandSpec = new CommandSpec(path: exePath, args: null);
+            var command = CommandFactoryUsingResolver.Create(commandSpec)
+                .WorkingDirectory(Path.GetDirectoryName(entryPointFileFullPath));
+
+            SetRootVariableName(
+                command,
+                runtimeIdentifier: RuntimeInformation.RuntimeIdentifier,
+                defaultAppHostRuntimeIdentifier: RuntimeInformation.RuntimeIdentifier,
+                targetFrameworkVersion: $"v{VirtualProjectBuildingCommand.TargetFrameworkVersion}");
+
             return command;
         }
 
diff --git a/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs b/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs
index 113337995562..3a5cb4168329 100644
--- a/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs
+++ b/src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs
@@ -1,12 +1,10 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Buffers;
 using System.Collections.Frozen;
 using System.Collections.Immutable;
 using System.Collections.ObjectModel;
 using System.Diagnostics;
-using System.IO;
 using System.Security;
 using System.Text.Json;
 using System.Text.Json.Serialization;
@@ -46,21 +44,28 @@ internal sealed class VirtualProjectBuildingCommand : CommandBase
     /// 
     private const string BuildSuccessCacheFileName = "build-success.cache";
 
-    private static readonly ImmutableArray s_implicitBuildFileNames =
+    /// 
+    /// IsMSBuildFile is  if the presence of the implicit build file (even if there are no s)
+    /// implies that CSC is not enough and MSBuild is needed to build the project, i.e., the file alone can affect MSBuild props or targets.
+    /// 
+    /// 
+    /// For example, the simple programs our CSC optimized path handles do not need NuGet restore, hence we can ignore NuGet config files.
+    /// 
+    private static readonly ImmutableArray<(string Name, bool IsMSBuildFile)> s_implicitBuildFiles =
     [
-        "global.json",
+        ("global.json", false),
 
         // All these casings are recognized on case-sensitive platforms:
         // https://github.com/NuGet/NuGet.Client/blob/ab6b96fd9ba07ed3bf629ee389799ca4fb9a20fb/src/NuGet.Core/NuGet.Configuration/Settings/Settings.cs#L32-L37
-        "nuget.config",
-        "NuGet.config",
-        "NuGet.Config",
-
-        "Directory.Build.props",
-        "Directory.Build.targets",
-        "Directory.Packages.props",
-        "Directory.Build.rsp",
-        "MSBuild.rsp",
+        ("nuget.config", false),
+        ("NuGet.config", false),
+        ("NuGet.Config", false),
+
+        ("Directory.Build.props", true),
+        ("Directory.Build.targets", true),
+        ("Directory.Packages.props", true),
+        ("Directory.Build.rsp", true),
+        ("MSBuild.rsp", true),
     ];
 
     /// 
@@ -69,12 +74,28 @@ internal sealed class VirtualProjectBuildingCommand : CommandBase
     private static readonly FrozenDictionary s_defaultProperties = FrozenDictionary.Create(StringComparer.OrdinalIgnoreCase,
     [
         new("OutputType", "Exe"),
-        new("TargetFramework", "net10.0"),
+        new("TargetFramework", $"net{TargetFrameworkVersion}"),
         new("ImplicitUsings", "enable"),
         new("Nullable", "enable"),
         new("PublishAot", "true"),
     ]);
 
+    /// 
+    /// For purposes of determining whether CSC is enough to build as opposed to full MSBuild,
+    /// we can ignore properties that do not affect the build on their own.
+    /// See also the IsMSBuildFile flag in .
+    /// 
+    /// 
+    /// This is an  rather than  to avoid boxing at the use site.
+    /// 
+    private static readonly IEnumerable s_ignorableProperties =
+    [
+        // This is set by default by `dotnet run`, so it must be ignored otherwise the CSC optimization would not kick in by default.
+        "NuGetInteractive",
+    ];
+
+    public static string TargetFrameworkVersion => Product.TargetFrameworkVersion;
+
     internal static readonly string TargetOverrides = """
           
     
     
+    
     
   
 
diff --git a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs
index edb3e4fe661e..fd980814d9de 100644
--- a/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs
+++ b/test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs
@@ -1174,17 +1174,7 @@ public static void Main()
             var result = runCommand.Execute();
             if (expectedRoot != null)
             {
-                // SDK tests use /tmp for test assets. On macOS, it is a symlink - the app will print the resolved path
-                if (OperatingSystem.IsMacOS())
-                {
-                    string tmpPath = "/tmp/";
-                    DirectoryInfo tmp = new DirectoryInfo(tmpPath[..^1]); // No trailing slash in order to properly check the link target
-                    if (tmp.LinkTarget != null && expectedRoot.StartsWith(tmpPath))
-                    {
-                        expectedRoot = Path.Combine(tmp.ResolveLinkTarget(true).FullName, expectedRoot[tmpPath.Length..]);
-                    }
-                }
-
+                expectedRoot = TestPathUtility.ResolveTempPrefixLink(expectedRoot);
                 result.Should().Pass()
                     .And.HaveStdOutContaining($"Runtime directory: {expectedRoot}");
             }
diff --git a/test/Microsoft.NET.TestFramework/TestAssetsManager.cs b/test/Microsoft.NET.TestFramework/TestAssetsManager.cs
index 097b17c004b7..3f397d133a81 100644
--- a/test/Microsoft.NET.TestFramework/TestAssetsManager.cs
+++ b/test/Microsoft.NET.TestFramework/TestAssetsManager.cs
@@ -144,9 +144,9 @@ private TestAsset CreateTestProjectsInDirectory(
             return testAsset;
         }
 
-        public TestDirectory CreateTestDirectory([CallerMemberName] string? testName = null, string? identifier = null)
+        public TestDirectory CreateTestDirectory([CallerMemberName] string? testName = null, string? identifier = null, string? baseDirectory = null)
         {
-            string dir = GetTestDestinationDirectoryPath(testName, testName, identifier ?? string.Empty);
+            string dir = GetTestDestinationDirectoryPath(testName, testName, identifier ?? string.Empty, baseDirectory: baseDirectory);
             return new TestDirectory(dir, TestContext.Current.SdkVersion);
         }
 
@@ -170,9 +170,10 @@ public static string GetTestDestinationDirectoryPath(
             string? testProjectName,
             string? callingMethodAndFileName,
             string? identifier,
-            bool allowCopyIfPresent = false)
+            bool allowCopyIfPresent = false,
+            string? baseDirectory = null)
         {
-            string? baseDirectory = TestContext.Current.TestExecutionDirectory;
+            baseDirectory ??= TestContext.Current.TestExecutionDirectory;
             var directoryName = new StringBuilder(callingMethodAndFileName).Append(identifier);
 
             if (testProjectName != callingMethodAndFileName)
diff --git a/test/Microsoft.NET.TestFramework/ToolsetInfo.cs b/test/Microsoft.NET.TestFramework/ToolsetInfo.cs
index 51e86418651c..db10ef95ab60 100644
--- a/test/Microsoft.NET.TestFramework/ToolsetInfo.cs
+++ b/test/Microsoft.NET.TestFramework/ToolsetInfo.cs
@@ -69,6 +69,8 @@ public string? MSBuildVersion
 
         public string? SdkResolverPath { get; set; }
 
+        public string? RepoRoot { get; set; }
+
         public ToolsetInfo(string dotNetRoot)
         {
             DotNetRoot = dotNetRoot;
@@ -292,7 +294,10 @@ public static ToolsetInfo Create(string? repoRoot, string? repoArtifactsDir, str
                 throw new FileNotFoundException($"Host '{dotnetHost}' not found. {hostNotFoundReason}");
             }
 
-            var ret = new ToolsetInfo(dotnetRoot);
+            var ret = new ToolsetInfo(dotnetRoot)
+            {
+                RepoRoot = repoRoot,
+            };
 
             if (!string.IsNullOrEmpty(commandLine.FullFrameworkMSBuildPath))
             {
diff --git a/test/Microsoft.NET.TestFramework/Utilities/TestPathUtility.cs b/test/Microsoft.NET.TestFramework/Utilities/TestPathUtility.cs
new file mode 100644
index 000000000000..46971a48fd35
--- /dev/null
+++ b/test/Microsoft.NET.TestFramework/Utilities/TestPathUtility.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.NET.TestFramework.Utilities;
+
+public static class TestPathUtility
+{
+#if NET
+    /// 
+    /// For path like /tmp/something, returns /private/tmp/something on macOS.
+    /// 
+    public static string ResolveTempPrefixLink(string path)
+    {
+        // SDK tests use /tmp for test assets. On macOS, it is a symlink - the app will print the resolved path
+        if (OperatingSystem.IsMacOS())
+        {
+            string tmpPath = "/tmp/";
+            var tmp = new DirectoryInfo(tmpPath[..^1]); // No trailing slash in order to properly check the link target
+            if (tmp.LinkTarget != null && path.StartsWith(tmpPath) && tmp.ResolveLinkTarget(true) is { } linkTarget)
+            {
+                return Path.Combine(linkTarget.FullName, path[tmpPath.Length..]);
+            }
+        }
+
+        return path;
+    }
+#endif
+}
diff --git a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
index dbdb60002d6b..72e6012267bf 100644
--- a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
+++ b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
@@ -3,11 +3,13 @@
 
 using System.Runtime.Versioning;
 using System.Text.Json;
+using Basic.CompilerLog.Util;
 using Microsoft.Build.Framework;
 using Microsoft.Build.Logging.StructuredLogger;
 using Microsoft.CodeAnalysis;
 using Microsoft.DotNet.Cli.Commands;
 using Microsoft.DotNet.Cli.Commands.Run;
+using Microsoft.DotNet.Cli.Utils;
 
 namespace Microsoft.DotNet.Cli.Run.Tests;
 
@@ -74,6 +76,12 @@ public static string GetMessage()
         }
         """;
 
+    /// 
+    /// Used when we need an out-of-tree base test directory to avoid having implicit build files
+    /// like Directory.Build.props in scope and negating the optimizations we want to test.
+    /// 
+    private static string OutOfTreeBaseDirectory => field ??= PrepareOutOfTreeBaseDirectory();
+
     private static bool HasCaseInsensitiveFileSystem
     {
         get
@@ -83,6 +91,25 @@ private static bool HasCaseInsensitiveFileSystem
         }
     }
 
+    /// 
+    private static string PrepareOutOfTreeBaseDirectory()
+    {
+        string outOfTreeBaseDirectory = TestPathUtility.ResolveTempPrefixLink(Path.Join(Path.GetTempPath(), "dotnetSdkTests"));
+        Directory.CreateDirectory(outOfTreeBaseDirectory);
+
+        // Create NuGet.config in our out-of-tree base directory.
+        var sourceNuGetConfig = Path.Join(TestContext.Current.TestExecutionDirectory, "NuGet.config");
+        var targetNuGetConfig = Path.Join(outOfTreeBaseDirectory, "NuGet.config");
+        File.Copy(sourceNuGetConfig, targetNuGetConfig, overwrite: true);
+
+        // Check there are no implicit build files that would prevent testing optimizations.
+        VirtualProjectBuildingCommand.CollectImplicitBuildFiles(new DirectoryInfo(outOfTreeBaseDirectory), [], out var exampleMSBuildFile);
+        exampleMSBuildFile.Should().BeNull(because: "there should not be any implicit build files in the temp directory or its parents " +
+            "so we can test optimizations that would be disabled with implicit build files present");
+
+        return outOfTreeBaseDirectory;
+    }
+
     /// 
     /// dotnet run file.cs succeeds without a project file.
     /// 
@@ -1493,12 +1520,12 @@ public void ArtifactsDirectory_Permissions()
             .Should().Be(actualMode, artifactsDir);
     }
 
-    [Theory]
-    [InlineData("Properties/launchSettings.json")]
-    [InlineData("Program.run.json")]
-    public void LaunchProfile(string relativePath)
+    [Theory, CombinatorialData]
+    public void LaunchProfile(
+        bool cscOnly,
+        [CombinatorialValues("Properties/launchSettings.json", "Program.run.json")] string relativePath)
     {
-        var testInstance = _testAssetsManager.CreateTestDirectory();
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: cscOnly ? OutOfTreeBaseDirectory : null);
         File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program + """
 
             Console.WriteLine($"Message: '{Environment.GetEnvironmentVariable("Message")}'");
@@ -1507,29 +1534,35 @@ public void LaunchProfile(string relativePath)
         Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
         File.WriteAllText(fullPath, s_launchSettings);
 
-        new DotnetCommand(Log, "run", "--no-launch-profile", "Program.cs")
+        var prefix = cscOnly
+            ? CliCommandStrings.NoBinaryLogBecauseRunningJustCsc + Environment.NewLine
+            : string.Empty;
+
+        new DotnetCommand(Log, "run", "-bl", "Program.cs")
             .WithWorkingDirectory(testInstance.Path)
             .Execute()
             .Should().Pass()
-            .And.HaveStdOut("""
+            .And.HaveStdOutContaining(prefix + """
                 Hello from Program
-                Message: ''
+                Message: 'TestProfileMessage1'
                 """);
 
-        new DotnetCommand(Log, "run", "Program.cs")
+        prefix = CliCommandStrings.NoBinaryLogBecauseUpToDate + Environment.NewLine;
+
+        new DotnetCommand(Log, "run", "-bl", "--no-launch-profile", "Program.cs")
             .WithWorkingDirectory(testInstance.Path)
             .Execute()
             .Should().Pass()
-            .And.HaveStdOutContaining("""
+            .And.HaveStdOut(prefix + """
                 Hello from Program
-                Message: 'TestProfileMessage1'
+                Message: ''
                 """);
 
-        new DotnetCommand(Log, "run", "-lp", "TestProfile2", "Program.cs")
+        new DotnetCommand(Log, "run", "-bl", "-lp", "TestProfile2", "Program.cs")
             .WithWorkingDirectory(testInstance.Path)
             .Execute()
             .Should().Pass()
-            .And.HaveStdOutContaining("""
+            .And.HaveStdOutContaining(prefix + """
                 Hello from Program
                 Message: 'TestProfileMessage2'
                 """);
@@ -1837,29 +1870,397 @@ public void ProjectReference_Errors()
                 string.Format(CliStrings.MoreThanOneProjectInDirectory, Path.Join(testInstance.Path, "dir/"))));
     }
 
+    /// 
+    /// Verifies that msbuild-based runs use CSC args equivalent to csc-only runs.
+    /// Can regenerate CSC arguments template in .
+    /// 
+    [Fact]
+    public void CscArguments()
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+        const string programName = "TestProgram";
+        const string fileName = $"{programName}.cs";
+        string entryPointPath = Path.Join(testInstance.Path, fileName);
+        File.WriteAllText(entryPointPath, s_program);
+
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(entryPointPath);
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+        // Build using MSBuild.
+        new DotnetCommand(Log, "run", fileName, "-bl", "--no-cache")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut($"Hello from {programName}");
+
+        // Find the csc args used by the build.
+        var msbuildCall = FindCompilerCall(Path.Join(testInstance.Path, "msbuild.binlog"));
+        var msbuildCallArgs = msbuildCall.GetArguments();
+        var msbuildCallArgsString = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(msbuildCallArgs);
+
+        // Generate argument template code.
+        string sdkPath = NormalizePath(TestContext.Current.ToolsetUnderTest.SdkFolderUnderTest);
+        string dotNetRootPath = NormalizePath(TestContext.Current.ToolsetUnderTest.DotNetRoot);
+        string nuGetCachePath = NormalizePath(TestContext.Current.NuGetCachePath!);
+        string artifactsDirNormalized = NormalizePath(artifactsDir);
+        string objPath = $"{artifactsDirNormalized}/obj/debug";
+        string entryPointPathNormalized = NormalizePath(entryPointPath);
+        var msbuildArgsToVerify = new List();
+        var nuGetPackageFilePaths = new List();
+        var code = new StringBuilder();
+        code.AppendLine($$"""
+            // Licensed to the .NET Foundation under one or more agreements.
+            // The .NET Foundation licenses this file to you under the MIT license.
+
+            namespace Microsoft.DotNet.Cli.Commands.Run;
+
+            // Generated by test `{{nameof(RunFileTests)}}.{{nameof(CscArguments)}}`.
+            partial class CSharpCompilerCommand
+            {
+                private IEnumerable GetCscArguments(
+                    string fileNameWithoutExtension,
+                    string objDir,
+                    string binDir)
+                {
+                    return
+                    [
+            """);
+        foreach (var arg in msbuildCallArgs)
+        {
+            // This option needs to be passed on the command line, not in an RSP file.
+            if (arg is "/noconfig")
+            {
+                continue;
+            }
+
+            // We don't need to generate a ref assembly.
+            if (arg.StartsWith("/refout:", StringComparison.Ordinal))
+            {
+                continue;
+            }
+
+            // There should be no source link arguments.
+            if (arg.StartsWith("/sourcelink:", StringComparison.Ordinal))
+            {
+                Assert.Fail($"Unexpected source link argument: {arg}");
+            }
+
+            // PreferredUILang is normally not set by default but can be in builds, so ignore it.
+            if (arg.StartsWith("/preferreduilang:", StringComparison.Ordinal))
+            {
+                continue;
+            }
+
+            bool needsInterpolation = false;
+            bool fromNuGetPackage = false;
+
+            // Normalize slashes in paths.
+            string rewritten = NormalizePathArg(arg);
+
+            // Remove quotes.
+            rewritten = RemoveQuotes(rewritten);
+
+            string msbuildArgToVerify = rewritten;
+
+            // Use variable SDK path.
+            if (rewritten.Contains(sdkPath, StringComparison.OrdinalIgnoreCase))
+            {
+                rewritten = rewritten.Replace(sdkPath, "{SdkPath}", StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+            }
+
+            // Use variable .NET root path.
+            if (rewritten.Contains(dotNetRootPath, StringComparison.OrdinalIgnoreCase))
+            {
+                rewritten = rewritten.Replace(dotNetRootPath, "{DotNetRootPath}", StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+            }
+
+            // Use variable NuGet cache path.
+            if (rewritten.Contains(nuGetCachePath, StringComparison.OrdinalIgnoreCase))
+            {
+                rewritten = rewritten.Replace(nuGetCachePath, "{NuGetCachePath}", StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+                fromNuGetPackage = true;
+            }
+
+            // Use variable intermediate dir path.
+            if (rewritten.Contains(objPath, StringComparison.OrdinalIgnoreCase))
+            {
+                // We want to emit the resulting DLL directly into the bin folder.
+                bool isOut = arg.StartsWith("/out", StringComparison.Ordinal);
+                string replacement = isOut ? "{binDir}" : "{objDir}";
+
+                if (isOut)
+                {
+                    msbuildArgToVerify = msbuildArgToVerify.Replace("/obj/", "/bin/", StringComparison.OrdinalIgnoreCase);
+                }
+
+                rewritten = rewritten.Replace(objPath, replacement, StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+            }
+
+            // Use variable file name.
+            if (rewritten.Contains(entryPointPathNormalized, StringComparison.OrdinalIgnoreCase))
+            {
+                rewritten = rewritten.Replace(entryPointPathNormalized, "{" + nameof(CSharpCompilerCommand.EntryPointFileFullPath) + "}", StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+            }
+
+            // Use variable program name.
+            if (rewritten.Contains(programName, StringComparison.OrdinalIgnoreCase))
+            {
+                rewritten = rewritten.Replace(programName, "{fileNameWithoutExtension}", StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+            }
+
+            // Use variable runtime version.
+            if (rewritten.Contains(CSharpCompilerCommand.RuntimeVersion, StringComparison.OrdinalIgnoreCase))
+            {
+                rewritten = rewritten.Replace(CSharpCompilerCommand.RuntimeVersion, "{" + nameof(CSharpCompilerCommand.RuntimeVersion) + "}", StringComparison.OrdinalIgnoreCase);
+                needsInterpolation = true;
+            }
+
+            // Ignore `/analyzerconfig` which is not variable (so it comes from the machine or sdk repo).
+            if (!needsInterpolation && arg.StartsWith("/analyzerconfig", StringComparison.Ordinal))
+            {
+                continue;
+            }
+
+            string prefix = needsInterpolation ? "$" : string.Empty;
+
+            code.AppendLine($"""
+                            {prefix}"{rewritten}",
+                """);
+
+            msbuildArgsToVerify.Add(msbuildArgToVerify);
+
+            if (fromNuGetPackage)
+            {
+                nuGetPackageFilePaths.Add(CSharpCompilerCommand.IsPathOption(rewritten, out int colonIndex)
+                    ? rewritten.Substring(colonIndex + 1)
+                    : rewritten);
+            }
+        }
+        code.AppendLine("""
+                    ];
+                }
+
+                /// 
+                /// Files that come from referenced NuGet packages (e.g., analyzers for NativeAOT) need to be checked specially (if they don't exist, MSBuild needs to run).
+                /// 
+                public static IEnumerable GetPathsOfCscInputsFromNuGetCache()
+                {
+                    return
+                    [
+            """);
+        foreach (var nuGetPackageFilePath in nuGetPackageFilePaths)
+        {
+            code.AppendLine($"""
+                            $"{nuGetPackageFilePath}",
+                """);
+        }
+        code.AppendLine("""
+                    ];
+                }
+            }
+            """);
+
+        // Save the code.
+        var codeFolder = new DirectoryInfo(Path.Join(
+            TestContext.Current.ToolsetUnderTest.RepoRoot,
+            "src", "Cli", "dotnet", "Commands", "Run"));
+        var nonGeneratedFile = codeFolder.File("CSharpCompilerCommand.cs");
+        if (!nonGeneratedFile.Exists)
+        {
+            Log.WriteLine($"Skipping code generation because file does not exist: {nonGeneratedFile.FullName}");
+        }
+        else
+        {
+            var codeFilePath = codeFolder.File("CSharpCompilerCommand.Generated.cs");
+            var existingText = codeFilePath.Exists ? File.ReadAllText(codeFilePath.FullName) : string.Empty;
+            var newText = code.ToString();
+            if (existingText != newText)
+            {
+                Log.WriteLine($"{codeFilePath.FullName} needs to be updated:");
+                Log.WriteLine(newText);
+                if (Environment.GetEnvironmentVariable("CI") == "true")
+                {
+                    throw new InvalidOperationException($"Not updating file in CI: {codeFilePath.FullName}");
+                }
+                else
+                {
+                    File.WriteAllText(codeFilePath.FullName, newText);
+                    throw new InvalidOperationException($"File outdated, commit the changes: {codeFilePath.FullName}");
+                }
+            }
+        }
+
+        // Build using CSC.
+        Directory.Delete(artifactsDir, recursive: true);
+        new DotnetCommand(Log, "run", fileName, "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut($"""
+                {CliCommandStrings.NoBinaryLogBecauseRunningJustCsc}
+                Hello from {programName}
+                """);
+
+        // Read args from csc.rsp file.
+        var rspFilePath = Path.Join(artifactsDir, "csc.rsp");
+        var cscOnlyCallArgs = File.ReadAllLines(rspFilePath);
+        var cscOnlyCallArgsString = string.Join(' ', cscOnlyCallArgs);
+
+        // Check that csc args between MSBuild run and CSC-only run are equivalent.
+        var normalizedCscOnlyArgs = cscOnlyCallArgs
+            .Select(static a => NormalizePathArg(RemoveQuotes(a)));
+        Log.WriteLine("CSC-only args:");
+        Log.WriteLine(string.Join(Environment.NewLine, normalizedCscOnlyArgs));
+        Log.WriteLine("MSBuild args:");
+        Log.WriteLine(string.Join(Environment.NewLine, msbuildArgsToVerify));
+        normalizedCscOnlyArgs.Should().Equal(msbuildArgsToVerify,
+            "the generated file might be outdated, run this test locally to regenerate it");
+
+        static CompilerCall FindCompilerCall(string binaryLogPath)
+        {
+            using var reader = BinaryLogReader.Create(binaryLogPath);
+            return reader.ReadAllCompilerCalls().Should().ContainSingle().Subject;
+        }
+
+        static string NormalizePathArg(string arg)
+        {
+            return CSharpCompilerCommand.IsPathOption(arg, out int colonIndex)
+                ? string.Concat(arg.AsSpan(0, colonIndex + 1), NormalizePath(arg.Substring(colonIndex + 1)))
+                : NormalizePath(arg);
+        }
+
+        static string NormalizePath(string path)
+        {
+            return PathUtility.GetPathWithForwardSlashes(TestPathUtility.ResolveTempPrefixLink(path));
+        }
+
+        static string RemoveQuotes(string arg)
+        {
+            return arg.Replace("\"", string.Empty);
+        }
+    }
+
+    /// 
+    /// Verifies that csc-only runs emit auxiliary files equivalent to msbuild-based runs.
+    /// 
+    [Theory]
+    [InlineData("Program.cs")]
+    [InlineData("test.cs")]
+    [InlineData("noext")]
+    public void CscVsMSBuild(string fileName)
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+        string entryPointPath = Path.Join(testInstance.Path, fileName);
+        File.WriteAllText(entryPointPath, $"""
+            #!/test
+            {s_program}
+            """);
+
+        string programName = Path.GetFileNameWithoutExtension(fileName);
+
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(entryPointPath);
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+        var artifactsBackupDir = Path.ChangeExtension(artifactsDir, ".bak");
+        if (Directory.Exists(artifactsBackupDir)) Directory.Delete(artifactsBackupDir, recursive: true);
+
+        // Build using CSC.
+        new DotnetCommand(Log, "run", fileName, "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut($"""
+                {CliCommandStrings.NoBinaryLogBecauseRunningJustCsc}
+                Hello from {programName}
+                """);
+
+        // Backup the artifacts directory.
+        Directory.Move(artifactsDir, artifactsBackupDir);
+
+        // Build using MSBuild.
+        new DotnetCommand(Log, "run", fileName, "-bl", "--no-cache")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut($"Hello from {programName}");
+
+        // Check that files generated by MSBuild and CSC-only runs are equivalent.
+        var cscOnlyFiles = Directory.EnumerateFiles(artifactsBackupDir, "*", SearchOption.AllDirectories)
+            .Where(f =>
+                Path.GetDirectoryName(f) != artifactsBackupDir && // exclude top-level marker files
+                Path.GetFileName(f) != programName && // binary on unix
+                Path.GetExtension(f) is not (".dll" or ".exe" or ".pdb")); // other binaries
+        bool hasErrors = false;
+        foreach (var cscOnlyFile in cscOnlyFiles)
+        {
+            var relativePath = Path.GetRelativePath(relativeTo: artifactsBackupDir, path: cscOnlyFile);
+            var msbuildFile = Path.Join(artifactsDir, relativePath);
+
+            if (!File.Exists(msbuildFile))
+            {
+                throw new InvalidOperationException($"File exists in CSC-only run but not in MSBuild run: {cscOnlyFile}");
+            }
+
+            var cscOnlyFileText = File.ReadAllText(cscOnlyFile);
+            var msbuildFileText = File.ReadAllText(msbuildFile);
+            if (cscOnlyFileText.ReplaceLineEndings() != msbuildFileText.ReplaceLineEndings())
+            {
+                Log.WriteLine($"File differs between MSBuild and CSC-only runs: {cscOnlyFile}");
+                const int limit = 3_000;
+                if (cscOnlyFileText.Length < limit && msbuildFileText.Length < limit)
+                {
+                    Log.WriteLine("MSBuild file content:");
+                    Log.WriteLine(msbuildFileText);
+                    Log.WriteLine("CSC-only file content:");
+                    Log.WriteLine(cscOnlyFileText);
+                }
+                else
+                {
+                    Log.WriteLine($"MSBuild file size: {msbuildFileText.Length} chars");
+                    Log.WriteLine($"CSC-only file size: {cscOnlyFileText.Length} chars");
+                }
+                hasErrors = true;
+            }
+        }
+        hasErrors.Should().BeFalse("some file contents do not match, see the test output for details");
+    }
+
     [Fact]
     public void UpToDate()
     {
-        var testInstance = _testAssetsManager.CreateTestDirectory();
-        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program);
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            Console.WriteLine("Hello v1");
+            """);
+
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(Path.Join(testInstance.Path, "Program.cs"));
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
 
-        Build(expectedUpToDate: false);
+        Build(testInstance, BuildLevel.Csc, expectedOutput: "Hello v1");
 
-        Build(expectedUpToDate: true);
+        Build(testInstance, BuildLevel.None, expectedOutput: "Hello v1");
 
-        Build(expectedUpToDate: true);
+        Build(testInstance, BuildLevel.None, expectedOutput: "Hello v1");
 
         // Change the source file (a rebuild is necessary).
-        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program + " ");
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program);
 
-        Build(expectedUpToDate: false);
+        Build(testInstance, BuildLevel.Csc);
 
-        Build(expectedUpToDate: true);
+        Build(testInstance, BuildLevel.None);
 
         // Change an unrelated source file (no rebuild necessary).
         File.WriteAllText(Path.Join(testInstance.Path, "Program2.cs"), "test");
 
-        Build(expectedUpToDate: true);
+        Build(testInstance, BuildLevel.None);
 
         // Add an implicit build file (a rebuild is necessary).
         string buildPropsFile = Path.Join(testInstance.Path, "Directory.Build.props");
@@ -1871,12 +2272,12 @@ public void UpToDate()
             
             """);
 
-        Build(expectedUpToDate: false, expectedOutput: """
+        Build(testInstance, BuildLevel.All, expectedOutput: """
             Hello from Program
             Custom define
             """);
 
-        Build(expectedUpToDate: true, expectedOutput: """
+        Build(testInstance, BuildLevel.None, expectedOutput: """
             Hello from Program
             Custom define
             """);
@@ -1893,7 +2294,7 @@ Custom define
             
             """);
 
-        Build(expectedUpToDate: false);
+        Build(testInstance, BuildLevel.All);
 
         // Change the imported build file (this is not recognized).
         File.WriteAllText(importedFile, """
@@ -1904,43 +2305,43 @@ Custom define
             
             """);
 
-        Build(expectedUpToDate: true);
+        Build(testInstance, BuildLevel.None);
 
         // Force rebuild.
-        Build(expectedUpToDate: false, args: ["--no-cache"], expectedOutput: """
+        Build(testInstance, BuildLevel.All, args: ["--no-cache"], expectedOutput: """
             Hello from Program
             Custom define
             """);
 
         // Remove an implicit build file (a rebuild is necessary).
         File.Delete(buildPropsFile);
-        Build(expectedUpToDate: false);
+        Build(testInstance, BuildLevel.Csc);
 
         // Force rebuild.
-        Build(expectedUpToDate: false, args: ["--no-cache"]);
+        Build(testInstance, BuildLevel.All, args: ["--no-cache"]);
 
-        Build(expectedUpToDate: true);
+        Build(testInstance, BuildLevel.None);
 
         // Pass argument (no rebuild necessary).
-        Build(expectedUpToDate: true, args: ["--", "test-arg"], expectedOutput: """
+        Build(testInstance, BuildLevel.None, args: ["--", "test-arg"], expectedOutput: """
             echo args:test-arg
             Hello from Program
             """);
 
         // Change config (a rebuild is necessary).
-        Build(expectedUpToDate: false, args: ["-c", "Release"], expectedOutput: """
+        Build(testInstance, BuildLevel.All, args: ["-c", "Release"], expectedOutput: """
             Hello from Program
             Release config
             """);
 
         // Keep changed config (no rebuild necessary).
-        Build(expectedUpToDate: true, args: ["-c", "Release"], expectedOutput: """
+        Build(testInstance, BuildLevel.None, args: ["-c", "Release"], expectedOutput: """
             Hello from Program
             Release config
             """);
 
         // Change config back (a rebuild is necessary).
-        Build(expectedUpToDate: false);
+        Build(testInstance, BuildLevel.Csc);
 
         // Build with a failure.
         new DotnetCommand(Log, ["run", "Program.cs", "-p:LangVersion=Invalid"])
@@ -1950,34 +2351,41 @@ Release config
             .And.HaveStdOutContaining("error CS1617"); // Invalid option 'Invalid' for /langversion.
 
         // A rebuild is necessary since the last build failed.
-        Build(expectedUpToDate: false);
+        Build(testInstance, BuildLevel.Csc);
+    }
 
-        void Build(bool expectedUpToDate, ReadOnlySpan args = default, string expectedOutput = "Hello from Program")
+    private void Build(TestDirectory testInstance, BuildLevel level, ReadOnlySpan args = default, string expectedOutput = "Hello from Program")
+    {
+        string prefix = level switch
         {
-            new DotnetCommand(Log, ["run", "Program.cs", "-bl", .. args])
-                .WithWorkingDirectory(testInstance.Path)
-                .Execute()
-                .Should().Pass()
-                .And.HaveStdOut(expectedUpToDate
-                    ? $"""
-                        {CliCommandStrings.NoBinaryLogBecauseUpToDate}
-                        {expectedOutput}
-                        """
-                    : expectedOutput);
-
-            var binlogs = new DirectoryInfo(testInstance.Path)
-                .EnumerateFiles("*.binlog", SearchOption.TopDirectoryOnly);
-
-            binlogs.Select(f => f.Name)
-                .Should().BeEquivalentTo(
-                    expectedUpToDate
-                        ? ["msbuild-dotnet-run.binlog"]
-                        : ["msbuild.binlog", "msbuild-dotnet-run.binlog"]);
-
-            foreach (var binlog in binlogs)
-            {
-                binlog.Delete();
-            }
+            BuildLevel.None => CliCommandStrings.NoBinaryLogBecauseUpToDate + Environment.NewLine,
+            BuildLevel.Csc => CliCommandStrings.NoBinaryLogBecauseRunningJustCsc + Environment.NewLine,
+            BuildLevel.All => string.Empty,
+            _ => throw new ArgumentOutOfRangeException(paramName: nameof(level)),
+        };
+
+        new DotnetCommand(Log, ["run", "Program.cs", "-bl", .. args])
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut(prefix + expectedOutput);
+
+        var binlogs = new DirectoryInfo(testInstance.Path)
+            .EnumerateFiles("*.binlog", SearchOption.TopDirectoryOnly);
+
+        binlogs.Select(f => f.Name)
+            .Should().BeEquivalentTo(
+                level switch
+                {
+                    BuildLevel.Csc => [],
+                    BuildLevel.None => ["msbuild-dotnet-run.binlog"],
+                    BuildLevel.All => ["msbuild.binlog", "msbuild-dotnet-run.binlog"],
+                    _ => throw new ArgumentOutOfRangeException(paramName: nameof(level), message: level.ToString()),
+                });
+
+        foreach (var binlog in binlogs)
+        {
+            binlog.Delete();
         }
     }
 
@@ -1994,6 +2402,210 @@ public void UpToDate_InvalidOptions()
             .And.HaveStdErrContaining(string.Format(CliCommandStrings.CannotCombineOptions, RunCommandParser.NoCacheOption.Name, RunCommandParser.NoBuildOption.Name));
     }
 
+    [Fact]
+    public void CscOnly()
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            Console.WriteLine("v1");
+            """);
+
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(Path.Join(testInstance.Path, "Program.cs"));
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+        Build(testInstance, BuildLevel.Csc, expectedOutput: "v1");
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            Console.WriteLine("v2");
+            #if !DEBUG
+            Console.WriteLine("Release config");
+            #endif
+            """);
+
+        Build(testInstance, BuildLevel.Csc, expectedOutput: "v2");
+
+        // Customizing a property forces MSBuild to be used.
+        Build(testInstance, BuildLevel.All, args: ["-c", "Release"], expectedOutput: """
+            v2
+            Release config
+            """);
+    }
+
+    [Fact]
+    public void CscOnly_CompilationDiagnostics()
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            string x = null;
+            Console.WriteLine("ran" + x);
+            """);
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOutContaining(CliCommandStrings.NoBinaryLogBecauseRunningJustCsc)
+            // warning CS8600: Converting null literal or possible null value to non-nullable type.
+            .And.HaveStdOutContaining("warning CS8600")
+            .And.HaveStdOutContaining("ran");
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            Console.Write
+            """);
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Fail()
+            .And.HaveStdOutContaining(CliCommandStrings.NoBinaryLogBecauseRunningJustCsc)
+            // error CS1002: ; expected
+            .And.HaveStdOutContaining("error CS1002")
+            .And.HaveStdErrContaining(CliCommandStrings.RunCommandException);
+    }
+
+    /// 
+    /// Checks that the DOTNET_ROOT env var is set the same in csc mode as in msbuild mode.
+    /// 
+    [Fact]
+    public void CscOnly_DotNetRoot()
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            foreach (var entry in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process)
+                .Cast()
+                .Where(e => ((string)e.Key).StartsWith("DOTNET_ROOT")))
+            {
+                Console.WriteLine($"{entry.Key}={entry.Value}");
+            }
+            """);
+
+        var expectedDotNetRoot = TestContext.Current.ToolsetUnderTest.DotNetRoot;
+
+        var cscResult = new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute();
+
+        cscResult.Should().Pass()
+            .And.HaveStdOutContaining(CliCommandStrings.NoBinaryLogBecauseRunningJustCsc)
+            .And.HaveStdOutContaining("DOTNET_ROOT")
+            .And.HaveStdOutContaining($"={expectedDotNetRoot}");
+
+        // Add an implicit build file to force use of msbuild instead of csc.
+        File.WriteAllText(Path.Join(testInstance.Path, "Directory.Build.props"), "");
+
+        var msbuildResult = new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute();
+
+        msbuildResult.Should().Pass()
+            .And.NotHaveStdOutContaining(CliCommandStrings.NoBinaryLogBecauseRunningJustCsc)
+            .And.HaveStdOutContaining("DOTNET_ROOT")
+            .And.HaveStdOutContaining($"={expectedDotNetRoot}");
+
+        // The set of DOTNET_ROOT env vars should be the same in both cases.
+        var cscVars = cscResult.StdOut!
+            .Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)
+            .Where(line => line.StartsWith("DOTNET_ROOT"));
+        var msbuildVars = msbuildResult.StdOut!
+            .Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)
+            .Where(line => line.StartsWith("DOTNET_ROOT"));
+        cscVars.Should().BeEquivalentTo(msbuildVars);
+    }
+
+    /// 
+    /// In CSC-only mode, the SDK needs to manually create intermediate files
+    /// like GlobalUsings.g.cs which are normally generated by MSBuild targets.
+    /// This tests the SDK recreates the files when they are outdated.
+    /// 
+    [Fact]
+    public void CscOnly_IntermediateFiles()
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            Expression> e = () => 1 + 1;
+            Console.WriteLine(e);
+            """);
+
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(Path.Join(testInstance.Path, "Program.cs"));
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Directory.Build.props"), "");
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Fail()
+            // error CS0246: The type or namespace name 'Expression<>' could not be found
+            .And.HaveStdOutContaining("error CS0246");
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Directory.Build.props"), """
+            
+                
+                    
+                
+            
+            """);
+
+        Build(testInstance, BuildLevel.All, expectedOutput: "() => 2");
+
+        File.Delete(Path.Join(testInstance.Path, "Directory.Build.props"));
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Fail()
+            .And.HaveStdOutContaining(CliCommandStrings.NoBinaryLogBecauseRunningJustCsc)
+            // error CS0246: The type or namespace name 'Expression<>' could not be found
+            .And.HaveStdOutContaining("error CS0246");
+    }
+
+    /// 
+    /// If a file from a NuGet package (which would be used by CSC-only build) does not exist, full MSBuild should be used instead.
+    /// 
+    [Fact]
+    public void CscOnly_NotRestored()
+    {
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: OutOfTreeBaseDirectory);
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), s_program);
+
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(Path.Join(testInstance.Path, "Program.cs"));
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl", "--no-restore")
+            .WithEnvironmentVariable("NUGET_PACKAGES", Path.Join(testInstance.Path, "packages"))
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Fail()
+            // error NETSDK1004: Assets file '...\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
+            .And.HaveStdOutContaining("NETSDK1004");
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithEnvironmentVariable("NUGET_PACKAGES", Path.Join(testInstance.Path, "packages"))
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut("Hello from Program");
+
+        File.WriteAllText(Path.Join(testInstance.Path, "Program.cs"), """
+            Console.WriteLine("v2");
+            """);
+
+        new DotnetCommand(Log, "run", "Program.cs", "-bl")
+            .WithEnvironmentVariable("NUGET_PACKAGES", Path.Join(testInstance.Path, "packages"))
+            .WithWorkingDirectory(testInstance.Path)
+            .Execute()
+            .Should().Pass()
+            .And.HaveStdOut($"""
+                {CliCommandStrings.NoBinaryLogBecauseRunningJustCsc}
+                v2
+                """);
+    }
+
     private static string ToJson(string s) => JsonSerializer.Serialize(s);
 
     /// 
@@ -2251,21 +2863,29 @@ public void Api_RunCommand()
                 """);
     }
 
-    [Fact]
-    public void EntryPointFilePath()
+    [Theory, CombinatorialData]
+    public void EntryPointFilePath(bool cscOnly)
     {
-        var testInstance = _testAssetsManager.CreateTestDirectory();
+        var testInstance = _testAssetsManager.CreateTestDirectory(baseDirectory: cscOnly ? OutOfTreeBaseDirectory : null);
         var filePath = Path.Join(testInstance.Path, "Program.cs");
         File.WriteAllText(filePath, """"
             var entryPointFilePath = AppContext.GetData("EntryPointFilePath") as string;
             Console.WriteLine($"""EntryPointFilePath: {entryPointFilePath}""");
             """");
 
-        new DotnetCommand(Log, "run", "Program.cs")
+        // Remove artifacts from possible previous runs of this test.
+        var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(filePath);
+        if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+        var prefix = cscOnly
+            ? CliCommandStrings.NoBinaryLogBecauseRunningJustCsc + Environment.NewLine
+            : string.Empty;
+
+        new DotnetCommand(Log, "run", "-bl", "Program.cs")
             .WithWorkingDirectory(testInstance.Path)
             .Execute()
             .Should().Pass()
-            .And.HaveStdOut($"EntryPointFilePath: {filePath}");
+            .And.HaveStdOut(prefix + $"EntryPointFilePath: {filePath}");
     }
 
     [Fact]