Visual Studio 如何在 .csproj 文件中未通知时确定输出路径

本文关键字:通知 路径 输出 Studio 文件 csproj Visual | 更新日期: 2023-09-27 18:31:31

我正在尝试从另一个解决方案引用 C# DLL 项目,但构建正在一个非常奇怪的输出文件夹中生成 DLL。

目录内容如下:

c:'a'b'c'src'Solution.sln
c:'a'x'y'z'MyDLL'MyDLL.csproj

MyDLL.csproj没有<输出路径>标记。但是,它确实有一个我不经常看到的标签。

计算的输出路径(如"属性"视图中所示)恰好是:

..'..'..'..'b'c'src-z'MyDLL'objd'i386

这对应于以下路径:

c:'a'b'c'src-z'src'MyDLL'objd'i386

这很奇怪,因为我不知道 src-z 配置中的任何内容。Visual Studio是用连字符计算的路径吗?

我想解决这个问题,可能会更改,但我不想破坏其他解决方案。

计算似乎在构建过程的早期就发生了,因为构建器记录的第一件事是:

1>Project 'MyDLL (x'y'z'MyDLL'MyDLL.csproj)' is not up to date.
  Input file 'x'y'z'MyDLL'MyDLL.csproj' is modified after output
  file 'c:'a'b'c'src-z'src'MyDLL'objd'i386'MyDLL.pdb'.

那么,当找不到项目标记时,Visual Studio 使用什么算法来计算输出路径?

Visual Studio 如何在 .csproj 文件中未通知时确定输出路径

填充

OutputPath 的代码可以在 C:'Program Files (x86)'MSBuild'12.0'Bin'Microsoft.Common.CurrentVersion.targets 中找到(默认情况下;如果 MSBuild 安装目录不同,它可能会更改)。

有一条关于它的评论是:

目录:

指示项目或解决方案的最终输出位置。生成解决方案时,OutDir 可用于在一个位置收集多个项目输出。此外,OutDir 包含在用于解析引用的 AssemblySearchPath 中。

输出路径:

此属性通常在项目文件中指定,用于初始化 OutDir。 OutDir 和 OutputPath 是出于遗留原因而区分的,如果可能的话,应该使用 OutDir。

因此,虽然 OutputPath 通常是被引用的内容,但真正重要的是 OutDir。如果没有设置的平台或配置,则输出路径设置为 bin'Debug'

如果我们查看该文件,我们可以看到设置OutDir的逻辑非常简单。如果未设置OutDir则将其设置为 OutputPath 。如果设置了GenerateProjectSpecificOutputPath,则以项目命名的文件夹附加到路径中需要一些额外的逻辑。

看看Microsoft.CSharp.targetsMicrosoft.CSharp.CurrentVersion.targetsMicrosoft.Common.TargetsMicrosoft.Common.CurrentVersion.targetsOutDirOutputPath似乎都没有设置在其他任何地方。因此,假设一个"开箱即用"的 C# 项目,它基本上等于 OutDirOutputPathbin'Debug

相关的最后一点信息是工作目录。 OutDir可以是相对路径,在这种情况下,它将位于工作目录中的某个位置。

至于BaseIntermediateOutputPath,信息在同一个文件中:

Base中间输出路径:

这是将在其中创建所有特定于配置的中间输出文件夹的顶级文件夹。默认值为 obj''

中间输出路径:

这是完整的中间输出路径,如果未指定,则派生自 BaseIntermediateOutputPath(例如 obj''debug)。如果此属性被重写,则设置 BaseIntermediateOutputPath 不起作用。

查看逻辑,如果未设置,则默认为 obj'(注意,相对路径,以便工作目录再次发挥作用)。

我会说你在某处有一个 OutputPath 声明,但如果不是在导入的目标文件之一的 .csproj 文件中。

我将把我的答案分成几个部分:

  1. <解决方案目录>标记并更改它。
    使用此标签,您可以声明解决方案目录变量$(SolutionDir),但是如果Visual Studio与解决方案实际所在的位置不同,则我认为Visual Studio不会从.csproj文件内部使用它。
    但该标记可能由 MSBuild 生成使用。如果我在.csproj文件中声明它,我无法让Visual Studio使用它。
    Visual Studio 使用加载的解决方案的目录作为变量内容,而不是我的测试中的 .csproj 文件中的任何不同声明。
    话虽如此:更改标签可能会改变 $(SolutionDir) 变量在您使用它的任何地方(如 PreBuild/PostBuild 或输出目录)的使用。无论在哪里使用。但不是在Visual Studio中。
    如果不使用它来更改它,它在Visual Studio版本中不会有太大变化。

  2. 无输出路径标记
    如果 .csproj 文件加载到 Visual Studio 中,我希望这个标签。但是可以在目标文件中声明它,而不是在.csproj文件中声明它。因此,您还必须检查导入的目标文件。
    例如,查看文件Microsoft.CSharp.targets。这是Visual Studio中CS项目的标准导入目标文件。它进行输出路径的计算和声明。
    第二种查看可能性是可以导入的您自己的目标文件(手写 .csproj 文件)。那里也可以进行声明。
    第三种可能性:我认为可以通过MSBuild的命令行参数声明此变量,但不适用于Visual Studio。

  3. Visual Studio 在 .csproj 文件中没有这个标记会工作吗?
    通常不会,但您可以声明覆盖标准 C# 目标文件 (Microsoft.CSharp.targets ) 中的错误并使其生成 - 但随后在此文件中声明。
    如果未声明标准输出目录,则为 ''bin''Debug(用于调试版本),如 Microsoft.CSharp.targets 定义。
    否则,您会收到错误。缺少输出路径声明。

  4. 它是如何计算的查看 .csproj 文件和目标文件(不包括 MSBuild 中的命令行参数),并查看哪些属性组部分有效(检查条件)。例如:

    <属性组条件>

    其中的所有内容对于选定的配置调试和 AnyCPU 都有效。特别是在标准目标文件中,有一些用于输出路径的声明。如果你的信息是正确的,这就是它似乎对你来说不标准的地方:通常,如果没有声明OutputPath,你会在Visual Studio构建中出现错误,因为有一个部分在目标中检查声明并抛出错误(您可以更改此行为 - 请参阅第 3 点)。解释将像任何脚本一样自上而下。

  5. SRC-Z从哪里来?(在Visual Studio中)
    扫描用于"src-z"的所有 .csproj 文件和目标文件以及解决方案文件的硬盘位置,以找出它的来源。

如果你真的在任何地方没有任何 OutputPath 声明,那么我没有解释为什么你的 VS-Build 可以工作。
如果你没有找到src-z,那么你可以在你的.csproj文件上发布更多信息以及你如何使用它(Visual Studio和解决方案)吗?

我发现了这个问题。其中一个参考项目是将定义为$SolutionDir + "-" + $ProjectName,这会产生c:'a'b'c'src-z

至于回答我的问题,我能推断出的最好的是:

  1. 如果有<输出路径>,则使用它。
  2. 否则,输出路径定义为 + + "bin"。
  3. 的默认值是项目目录。
  4. 默认值 <中间输出路径>由生成类型(即调试、发布等)定义。