【问题标题】:How to get csc.exe path?如何获取 csc.exe 路径?
【发布时间】:2011-10-03 09:10:19
【问题描述】:

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

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

有什么解决办法吗?

【问题讨论】:

  • 你的问题到底是什么?
  • 您知道可以使用CodeDomProvider 从字符串源文件构建吗? (准确的说是CodeDomProvider.CompileAssemblyFromSource)也就是说,当框架已经支持csc.exe时,就不需要单独使用它了。
  • 你有没有检查系统变量下的Path,可能是路径
  • 希望 MS 永远不会重复为我们提供 3.0 和 3.5 的“版本控制”的乐趣,但是当 3.0 安装时,它并没有带来自己的 csc 版本(你必须知道去并找到 2.0.xxxxx 版本)。如果 MS 确实重复这种事情,最新的框架版本可能不会引导您使用最新版本的 csc。
  • 如果您愿意,我可以不接受您的答案,但是,该答案当时解决了我的问题,而当前投票最高的答案对我没有任何价值。

标签: c# .net csc


【解决方案1】:

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 位应用程序所需的所有路径。

【讨论】:

  • 但这基本上就是OP所说的。 :)
  • 是的,也许我只是不理解他的问题。哦,好吧,我试过了。 :)
  • 当 3.0 是框架的最新“版本”时,3.0 文件夹不包含 csc 的副本(现在仍然不包含)
【解决方案2】:

查找 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

问候。

【讨论】:

    【解决方案3】:

    您可以使用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
    

    【讨论】:

      【解决方案4】:

      更新:

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

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

      CSC路径如下:

      C:\Program Files\MSBuild\\Bin

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

      【讨论】:

      • 是的,这就是我使用的。例如,我将 C:\Program Files (x86)\MSBuild\14.0\Bin 添加到我的路径中,以便我可以在终端应用程序中使用 csc。
      【解决方案5】:

      我假设您想使用 csc.exe普通的非开发人员 PC 上编译文件,这就是您询问路径的原因。

      您可以使用以下我创建的小批处理脚本来获取最新的 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 instead of Windows CSC.EXE(如果已安装)。

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

      CompileCS GetDotNetVersion.cs

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

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

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

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

      请注意

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

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

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

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

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

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

      • 我找到了一个很好的描述如何使用response files with CSC.exe。对于更复杂的场景,您将需要MSBUILD Valve 开发者社区的此描述向您展示了如何在不安装 Visual Studio 的情况下获得它。看看吧:-)

      【讨论】:

      • 我认为应该添加 roslyn 编译器路径,比如这个..."%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csc.exe"
      • @beppe9000 - 微软对此不是很清楚。查看this link,这里只提到了csc.exe的可执行文件通常位于Windows目录下的Microsoft.NET\Framework\文件夹中。它的位置可能会根据具体的配置有所不同。特定计算机。如果您的计算机上安装了多个版本的 .NET Framework,您会发现该文件的多个版本。"
      • @Matt 如果您使用该链接推荐的开发人员命令提示符,则路径上的第一个 csc.exe 是例如C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Roslyn\csc.exe
      • @CarlWalsh - 这是正确的。我指的是您经常需要处理的普通的非开发人员 PC。在此类 PC 上,您可以使用我提供的链接编译 + 运行 a little C# program which checks and prints the .NET version 安装。
      【解决方案6】:

      在开发者命令提示符下,运行命令:

      where csc
      

      您将获得csc 的路径,该路径与 Visual Studio 和 net4 一起安装,例如:

      C:\Program Files\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Roslyn\csc.exe
      C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe
      

      【讨论】:

      • 谢谢,这很有用
      【解决方案7】:

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

      csc PathToYourCsSource
      

      【讨论】:

      • 我认为他试图以编程方式进行
      • 如果csc.exe 不在您的$PATH 环境变量中,这将不起作用
      【解决方案8】:

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

      csc.exe 可执行文件通常位于 Windows 目录下的 Microsoft.NET\Framework\ 文件夹。 它的位置可能会有所不同,具体取决于 特定的计算机。如果不止一个版本的 .NET Framework 安装在您的计算机上,您会发现它的多个版本 文件。

      【讨论】:

        【解决方案9】:

        死灵术。
        这就是他们在 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-30
          • 2017-01-09
          相关资源
          最近更新 更多