68

有没有办法获取最新的 .NET Framework 的 csc.exe 的路径?

该文件通常位于:c:\Windows\Microsoft.NET\Framework\vX.X.XXX 但问题是可以安装多个版本 + 有 32 位和 64 位版本。

有什么解决办法吗?

4

9 回答 9

34

c:\Windows\Microsoft.NET\Framework\vX.X.XXX 应该包含最新的 32 位版本的 csc.exe

c:\Windows\Microsoft.NET\Framework64\vX.X.XXX 应该包含最新的 64 位版本的 csc.exe

无论如何,这就是我的。

顺便说一句:您可以使用程序文件中的 Visual Studio 工具文件夹中的 Visual Studio 命令行来访问这两者。它会自动设置您使用 csc 编译器构建 32 位和 64 位应用程序所需的所有路径。

于 2011-07-12T07:02:53.720 回答
19

查找CSC.exe路径的最佳方法是在 CLI(命令行解释器)中运行该简单行:

dir /s %WINDIR%\CSC.EXE

dir - 显示目录

/s - 包括子文件夹

%WINDIR%\CSC.EXE - 在根文件夹中查找类似“CSC.exe”的短语。

这是我们的结果: 在此处输入图像描述

然后我们可以简单地逐行编译示例代码,例如:

C:\WINDOWS\...\v.4.0.30319\CSC.exe HelloWorld.cs

问候。

于 2016-11-23T18:33:43.197 回答
16

您可以使用System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory().

using System.Runtime.InteropServices;
var frameworkPath = RuntimeEnvironment.GetRuntimeDirectory();
var cscPath = Path.Combine(frameworkPath, "csc.exe");

Console.WriteLine(frameworkPath);  // C:\Windows\Microsoft.NET\Framework\v4.0.30319
Console.WriteLine(cscPath); }      // C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe
于 2014-08-15T14:58:04.323 回答
11

更新:

打开命令提示符或 Powershell 并运行以下命令以列出已安装的不同 .Net Frameworks 版本的编译器的完整路径。

dir %WINDIR%\Microsoft.NET\Framework64\csc.exe /s/b

CSC 路径如下:

C:\Program Files\MSBuild\\Bin

例如:如果您使用的是 Visual Studio 2013,它将是 12.0。

于 2014-11-06T18:42:10.483 回答
7

我假设您想用于在普通的非开发人员 PCcsc.exe上编译文件,这就是您要求路径的原因。

您可以使用以下我创建的小批处理脚本来获取可用的最新 csc.exe的路径,而不是为此查看注册表;路径在脚本的第一部分确定,然后存储在环境变量中dotNet

@echo off
pushd .& setlocal

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\
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

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% -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% -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 
::::

然后它将使用该路径来调用嵌入在 Windows 中的最新可用 C# 编译器。请注意,Visual Studio 使用比 Windows 更新的 C# 编译器,在 Windows 中,您只能使用 C# 版本 5。当您打算使用它编译源代码时,请记住这一点。

我已经更新了代码,以便它能够在安装时使用Roslyn 而不是 Windows CSC.EXE

将其另存为CompileCS.cmd并将其放在与 *.cs 文件相同的路径中。然后你可以简单地编译它如下:

CompileCS GetDotNetVersion.cs

它将编译控制台应用程序 GetDotNetVersion,这是一个确定已安装 .NET 版本的程序,我已在此处发布。

提示:如果要在编译后立即运行 C# 应用程序/run,请使用如下参数(如果需要,可以在 .cs 文件末尾传递命令行参数,它们将传递给编译后的 .exe 文件):

CompileCS /run GetDotNetVersion.cs [arg1] ... [arg7]

该脚本检查 .NET 2.0.x、3.5 和 4.0.30319 的系统目录是否存在 - 在其他文件夹中我从未见过 csc.exe。因为它从最旧版本到最新版本进行检查,所以该变量dotNet包含最新的现有路径。

注意

  • Microsoft 将所有 4.x 版本的 .NET(包括最新版本 4.7.1)存储在文件夹 4.0.30319 中。因此,如果安装了任何版本的 .NET 4.x,您都会在那里找到它。

  • 如果您需要64 位版本而不是 32 位版本,则只需在环境变量中替换Framework为(脚本的第 2 行)。请注意,即使在 64 位 Windows 上,通常也会安装 32 位版本的框架,如果您真的不需要 64 位,它可以在大多数 32 位 PC 上正常工作。但是,如果您愿意,可以添加对路径是否存在的检查并支持 Framework64(就像我为 .NET 版本所做的那样)。Framework64dotNetBase

  • 如前所述,虽然csc.exe它仍然存在,但仅限于C# 版本 5(每次调用 csc.exe 时都会收到此警告)。但是对于许多小用的控制台应用程序来说,C#5 还是可以的。如果您需要更高版本(C#6、...、C#9 或更高版本),那么您将需要 Visual Studio,或者您可以访问Roslyn GitHub 区域以获取 Roslyn 编译器源代码。

  • 如果您要引用外部程序集(*.dll),则需要更新代码中的以下行:set assemblies=-reference:.\PresentationCore.Dll,.\WindowsBase.dll- 只需附加您需要的任何 dll - 列表以逗号分隔。您需要将它们从dotNet路径复制到输出目录(正在创建 *.exe 的位置)。如果不需要任何程序集,只需将其设置为空白(即set assemblies=)。

  • 您可以通过检查是否需要编译来增强脚本(通过比较 *.cs 文件和 *.exe 文件的文件日期/时间并仅在 *.cs 文件比 *.exe 文件新时编译)。此处描述了如何使用批处理来完成。

  • 使用 C# 编译器的另一种方法是在 C# 程序中。Microsoft在这里描述了这种方法。

  • 我找到了一个很好的描述如何将响应文件与 CSC.exe 一起使用。对于更复杂的场景,您将需要MSBUILD这个来自 Valve 开发者社区的描述向您展示了如何在不安装 Visual Studio 的情况下获得它。一探究竟 :-)

于 2017-10-20T16:12:42.323 回答
4

In the Developer command prompt, run the command:

where csc

You get the path to csc which is installed with Visual Studio and net4 like:

C:\Program Files\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csc.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe
于 2020-07-18T14:53:14.813 回答
3

如果您已经安装了 Visual Studio,只需:单击开始,指向所有程序,指向 Microsoft Visual Studio,指向 Visual Studio 工具,然后单击 Visual Studio 命令提示符,您将在命令行框中进行编译,如下所示:

csc PathToYourCsSource
于 2012-04-22T13:05:47.213 回答
2

微软最近已经很好地记录了这一点 - 检查这里

csc.exe 可执行文件通常位于 Windows 目录下的 Microsoft.NET\Framework\ 文件夹中。 它的位置可能会因特定计算机的确切配置而异。如果您的计算机上安装了多个版本的 .NET Framework,您会发现该文件的多个版本。

于 2017-08-03T03:42:56.200 回答
1

死灵术。
这就是他们在 ReportViewer 中的操作方式:

string compilerDirectory = System.IO.Path.Combine(
System.Environment.GetEnvironmentVariable("windir")
, "Microsoft.NET\\Framework" + (System.Environment.Is64BitProcess ? "64" : "")
, System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion());

C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319
"C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\vbc.exe" 
"C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\csc.exe" 

但在 2018 年,你最好使用 roslyn 内置编译器:

这里有一个例子:

         protected override System.CodeDom.Compiler.CompilerResults FromFileBatch(System.CodeDom.Compiler.CompilerParameters options, string[] fileNames)
        {

#if NETSTANDARD2_0
            return NetStandardFromFileBatch(options, fileNames);
#else
            return OldFromFileBatch(options, fileNames);
#endif
        }




#if NETSTANDARD2_0         



        protected System.CodeDom.Compiler.CompilerResults NetStandardFromFileBatch(System.CodeDom.Compiler.CompilerParameters options, string[] fileNames)
        {
            //// C:\Program Files\dotnet\sdk\2.0.0\Roslyn

            //string sysver = System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion();
            //System.Console.WriteLine(sysver);


            //string pf64 = System.Environment.ExpandEnvironmentVariables("%ProgramW6432%");
            //string pf32 = System.Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%");
            //string pf = pf32;

            //if (System.IntPtr.Size * 8 == 64)
            //    pf = pf64;

            //// compilerDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles);
            ////compilerDirectory = System.IO.Path.Combine(compilerDirectory, "dotnet", "sdk", "2.0.0", "Roslyn");
            //compilerDirectory = System.IO.Path.Combine(pf32, "MSBuild", "14.0", "Bin");
            //if (System.IntPtr.Size * 8 == 64)
            //    compilerDirectory = System.IO.Path.Combine(compilerDirectory, "amd64");

            string assemblyName = System.IO.Path.GetFileNameWithoutExtension(options.OutputAssembly);

            Microsoft.CodeAnalysis.SyntaxTree[] syntaxTrees = new Microsoft.CodeAnalysis.SyntaxTree[fileNames.Length];

            for (int i = 0; i < fileNames.Length; ++i)
            {
                string fileContent = System.IO.File.ReadAllText(fileNames[i], System.Text.Encoding.UTF8);

                Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions op = null;

                // ERR_EncodinglessSyntaxTree = 37236 - Encoding must be specified... 
                syntaxTrees[i] = Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree.ParseText(
                    fileContent, op, fileNames[i], System.Text.Encoding.UTF8
                );

            }

            Microsoft.CodeAnalysis.MetadataReference[] references =
                new Microsoft.CodeAnalysis.MetadataReference[options.ReferencedAssemblies.Count];

            for (int i = 0; i < references.Length; ++i)
            {
                references[i] = Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(
                    options.ReferencedAssemblies[i]
                );
            }



            Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions co =
                new Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilationOptions
            (
                Microsoft.CodeAnalysis.OutputKind.DynamicallyLinkedLibrary
            );

            co.WithOptionStrict(Microsoft.CodeAnalysis.VisualBasic.OptionStrict.Off);
            co.WithOptionExplicit(false);
            co.WithOptionInfer(true);

            Microsoft.CodeAnalysis.Compilation compilation = Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation.Create(
                assemblyName,
                syntaxTrees,
                references,
                co
            );


            System.CodeDom.Compiler.CompilerResults compilerResults = new System.CodeDom.Compiler.CompilerResults(options.TempFiles);

            compilerResults.NativeCompilerReturnValue = -1;

            // using (var dllStream = new System.IO.MemoryStream())
            using (System.IO.FileStream dllStream = System.IO.File.Create(options.OutputAssembly))
            {
                using (System.IO.MemoryStream pdbStream = new System.IO.MemoryStream())
                {
                    Microsoft.CodeAnalysis.Emit.EmitResult emitResult = compilation.Emit(dllStream, pdbStream);
                    if (!emitResult.Success)
                    {

                        foreach (Microsoft.CodeAnalysis.Diagnostic diagnostic in emitResult.Diagnostics)
                        {
                            // options.TreatWarningsAsErrors
                            if (diagnostic.IsWarningAsError || diagnostic.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error)
                            {
                                string errorNumber = diagnostic.Id;
                                string errorMessage = diagnostic.GetMessage();

                                string message = $"{errorNumber}: {errorMessage};";
                                string fileName = diagnostic.Location.SourceTree.FilePath;

                                Microsoft.CodeAnalysis.FileLinePositionSpan lineSpan = diagnostic.Location.GetLineSpan();
                                string codeInQuestion = lineSpan.Path;
                                int line = lineSpan.StartLinePosition.Line;
                                int col = lineSpan.StartLinePosition.Character;

                                compilerResults.Errors.Add(
                                    new System.CodeDom.Compiler.CompilerError(fileName, line, col, errorNumber, errorMessage)
                                );
                            } // End if 

                        } // Next diagnostic 

                        // emitResult.Diagnostics
                        // CheckCompilationResult(emitResult);
                    }
                    else
                    {
                        compilerResults.PathToAssembly = options.OutputAssembly;
                        compilerResults.NativeCompilerReturnValue = 0;
                    }
                }
            }

            // compilerResults.CompiledAssembly = System.Reflection.Assembly.Load(array3, null);

            return compilerResults;
        }
#endif
于 2018-09-26T15:37:07.963 回答