I assume you want to use csc.exe
to compile files on a plain, non-developer PC, that's why you were asking for the path.
Rather than looking into the registry for this purpose you can use the following little batch script I have created to get the path to the latest csc.exe available; the path is determined in the first section of the script and then stored in the environment variable dotNet
:
@echo off
pushd .& setlocal
set dotNetVS=%ProgramFiles(x86)%\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\Roslyn\
set dotNetBase=%SystemRoot%\Microsoft.NET\Framework\
rem get latest .net path containing csc.exe:
set dotNet20=%dotNetBase%v2.0.50727\
set dotNet35=%dotNetBase%v3.5\
set dotNet40=%dotNetBase%v4.0.30319\
if exist %dotNet20%nul set dotNet=%dotNet20%
if exist %dotNet35%nul set dotNet=%dotNet35%
if exist %dotNet40%nul set dotNet=%dotNet40%
set msbuildDir=%ProgramFiles(x86)%\MSBuild\14.0\Bin\
if exist "%dotNetVS%csc.exe" set msbuildDir=%dotNetVS%
set cscExe="%msbuildDir%csc.exe"
if not exist %cscExe% set cscExe="%dotNet%csc.exe"
::echo %cscExe%
set assemblies=
REM reference required assemblies here, copy them to the output directory after the colon (:), separated by comma
REM set assemblies=-reference:.\PresentationCore.Dll,.\WindowsBase.dll
REM If preview does not work, set this to latest:
set langversion=preview
set runArgs=%3 %4 %5 %6 %7 %8 %9
if not "%1"=="/run" (set outPath=%~DP1& set outFileName=%~n1& CALL :Compile) else (set outPath=%~DP2& set outFileName=%~n2& CALL :CompileAndRun)
GOTO :End
:Compile
echo Compiling "%outPath%%outFileName%.cs"
if exist "%outPath%%outFileName%.exe" del /F "%outPath%%outFileName%.exe"
%cscExe% -langversion:%langversion% -optimize+ -lib:"%dotNet%\" %assemblies% /t:exe /out:"%outPath%%outFileName%.exe" %outFileName%.cs
exit /B
:CompileAndRun
echo Compiling "%outPath%%outFileName%.cs"
if exist "%outPath%%outFileName%.exe" del /F "%outPath%%outFileName%.exe"
%cscExe% -langversion:%langversion% -optimize+ -lib:"%dotNet%\" %assemblies% /t:exe /out:"%outPath%%outFileName%.exe" %outFileName%.cs >nul
echo Running "%outPath%%outFileName%.exe"
"%outPath%%outFileName%.exe" %runArgs%
exit /B
:End
::::
It will then use that path to invoke the latest available C# compiler embedded in Windows. Note that Visual Studio is using newer C# compilers than Windows, with Windows you are limited to C# version 5. This is important to keep in mind when you intend to compile source code with it.
I have updated the code so that it is able to use Roslyn instead of Windows CSC.EXE if it is installed.
Save it as CompileCS.cmd
and put it in the same path as your *.cs files. Then you can simply compile it as follows:
CompileCS GetDotNetVersion.cs
Which will compile the console application GetDotNetVersion, a program to determine the installed .NET versions, which I've published here.
Hint: If you want to run the C# application immediately after compilation, use the /run
parameter as follows (you can pass command line arguments at the end of the .cs file if required, they will be passed to the compiled .exe file):
CompileCS /run GetDotNetVersion.cs
[arg1] ... [arg7]
The script checks for existence of the system directories for .NET 2.0.x, 3.5 and 4.0.30319 - in other folders I have never seen csc.exe. Because it does the check from the oldest to the newest version, the variable dotNet
contains the latest existing path.
Note that
Language is set to preview
to allow trying out latest syntax. Change langversion
to latest
if you encounter any issues (applies to Roslyn compiler)
For .NET core projects, you can use the dotnet run
command instead of CSC. It is included in the .NET core SDK.
Microsoft stores all the 4.x versions of .NET - including the latest version 4.7.1 - in the folder 4.0.30319. Because of that, if any version of .NET 4.x is installed, you will find it there.
If you need the 64 bit version rather than the 32 bit version then simply replace Framework
by Framework64
in the environment variable dotNetBase
(2nd line of the script). Note that even on 64 bit Windows there is usually a 32 bit version of the framework installed and if you don't really need to have 64 bit, it will work fine on most PCs with 32 bit. However, you could add a check for existance of the path and favor Framework64 if you prefer that (like I did it for the .NET versions).
As said before, while csc.exe
still exists, it is restricted to C# version 5 (you will get this warning each time you invoke csc.exe). But for many little useful console applications, C#5 is still fine. If you need a higher version (C#6, ..., C#9 or higher), then you'll need either Visual Studio or you can visit the Roslyn GitHub area to get the Roslyn compiler source code.
If you're referencing external assemblies (*.dll's), you will need to update the following line in the code: set assemblies=-reference:.\PresentationCore.Dll,.\WindowsBase.dll
- just append any dll's you need - the list is comma-separated. You need to copy them from the dotNet
path to the output directory (where the *.exe is being created). If no assemblies are needed, just set it blank (i.e. set assemblies=
).
You could enhance the script by checking if compilation is required (by comparing the file date/time of the *.cs file and *.exe file and compile only if the *.cs file is newer than the *.exe file). How that can be done with a batch is described here.
An alternative way to use the C# compiler is from within your C# program. Microsoft describes this approach here.
I found a nice description how to use response files with CSC.exe. And for more complex scenarios you will need MSBUILD This description from the Valve Developer Community shows you how you can get it without installing Visual Studio. Check it out :-)
CodeDomProvider
to build from a string source file? (orCodeDomProvider.CompileAssemblyFromSource
, to be precise) In other words, there is no need to usecsc.exe
as a separate tool when framework already supports it. – DesuetudePath
under system variables, maybe that holds the path – Gelid