如何使 MSBuild MakeDir 任务在 Azure Pipeline YAML 模板中工作?

Posted

技术标签:

【中文标题】如何使 MSBuild MakeDir 任务在 Azure Pipeline YAML 模板中工作?【英文标题】:How to make MSBuild MakeDir task work in Azure Pipeline YAML template? 【发布时间】:2021-12-18 08:56:07 【问题描述】:

带有构建后事件的csproj文件:

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command="dotnet tool restore" />
        <MakeDir Directories=".../../artifacts/swagger/v1" Condition="!Exists('../../artifacts/swagger/v1')" />
        <Exec Command="dotnet swagger tofile --output ../../artifacts/swagger/v1/swagger.json &quot;$(TargetPath)&quot; v1" />
</Target>

这些步骤在本地和 Windows 和 Linux 主机上的 Azure DevOps 中运行了一段时间。但现在,我正在尝试更改我的 azure-pipeline.yml 以使用自定义 YAML 模板。 YAML 模板中的 dotnet 构建步骤相当简单:

- task: DotNetCoreCLI@2
      displayName: Build
      inputs:
        command: build
        projects: $ parameters.projectsToBuild 
        arguments: --no-restore --configuration $ parameters.configuration  /p:Version=$(GitVersion.FullSemVer) /p:ContinuousIntegrationBuild=true

但是,由于某种原因,现在我在模板中有此步骤,MakeDir MSBuild 任务似乎已停止工作,因为生成 swagger.json 文件的以下步骤失败并出现以下错误

  Unhandled exception. System.IO.DirectoryNotFoundException: Could not find a part of the path '/home/vsts/work/1/s/artifacts/swagger/v1/swagger.json'.
     at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter)
     at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String path, OpenFlags flags, Int32 mode)
     at System.IO.FileStream.OpenHandle(FileMode mode, FileShare share, FileOptions options)
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
     at System.IO.StreamWriter.ValidateArgsAndOpenPath(String path, Boolean append, Encoding encoding, Int32 bufferSize)
     at System.IO.StreamWriter..ctor(String path, Boolean append)
     at System.IO.File.CreateText(String path)
     at Swashbuckle.AspNetCore.Cli.Program.<>c.<Main>b__0_3(IDictionary`2 namedArgs) in C:\projects\ahoy\src\Swashbuckle.AspNetCore.Cli\Program.cs:line 90
     at Swashbuckle.AspNetCore.Cli.CommandRunner.Run(IEnumerable`1 args) in C:\projects\ahoy\src\Swashbuckle.AspNetCore.Cli\CommandRunner.cs:line 68
     at Swashbuckle.AspNetCore.Cli.CommandRunner.Run(IEnumerable`1 args) in C:\projects\ahoy\src\Swashbuckle.AspNetCore.Cli\CommandRunner.cs:line 59
     at Swashbuckle.AspNetCore.Cli.Program.Main(String[] args) in C:\projects\ahoy\src\Swashbuckle.AspNetCore.Cli\Program.cs:line 111

如何让这个任务在 YAML 模板中工作?或者有没有这样简单和多平台的解决方法?

【问题讨论】:

【参考方案1】:

*经过更多研究,我尝试了:

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="dotnet tool restore" />
    <Exec Command="mkdir ..\..\artifacts\swagger\v1" Condition="!Exists('..\..\artifacts\swagger\v1') AND '$(OS)' == 'Windows_NT'" />
    <Exec Command="mkdir -p ../../artifacts/swagger/v1" Condition="!Exists('../../artifacts/swagger/v1') AND '$(OS)' != 'Windows_NT'" />
    <Exec Command="dotnet swagger tofile --output ../../artifacts/swagger/v1/swagger.json &quot;$(TargetPath)&quot; v1" />
</Target>

这可行,但我想使用更简单的 MakeDir 任务。

然后我添加了一个 任务并打开了诊断详细度,并注意到 Message 任务和 MakeDir 任务都在 Exec 任务之后被调用。所以,任务成功了,但没有按正确的顺序运行。

我不知道为什么将 dotnet build 任务放在 YAML 模板中会始终导致 Exec MSBuild 任务在其他 MSBuild 任务之前运行,但是当 dotnet build 任务直接在我的 azure-pipelines.yml 文件中时,MSBuild任务始终以正确的顺序运行。

所以,就目前而言,我所做的是将 MakeDir 任务移动到 csproj 中的 Pre-Build 事件。这始终有效。

但如果有人能澄清问题并知道如何让它按预期工作,我会接受你的回答而不是我的回答。

【讨论】:

以上是关于如何使 MSBuild MakeDir 任务在 Azure Pipeline YAML 模板中工作?的主要内容,如果未能解决你的问题,请参考以下文章

仅当文件数大于零时,如何在 MSBuild 中运行任务?

MSBuild 任务,如何删除嵌套目录?

如何使 MSBuild 自动将所有间接引用复制到输出(bin)文件夹

MSBuild:描述要调用的构造函数

给定相对路径时,如何让 MSBUILD 评估和打印完整路径?

CruiseControl.Net 在使用 msbuild 任务的项目后重新启动