MSBuild exec任务没有阻塞

Rob*_*Rob 15 msbuild

有人会碰巧知道一个会阻止这个MSBuild任务阻止的技巧吗?我真的只是想要打开资源管理器和构建脚本继续前进.目前,它会阻止Exec任务,直到资源管理器窗口关闭.

<Target Name="OpenExplorer">
    <Exec Command='explorer.exe "$(DestinationDir)"' IgnoreExitCode="true" />
</Target>
Run Code Online (Sandbox Code Playgroud)

谢谢!

编辑:我希望避免为此创建自定义任务.也许某些命令行魔法存在,可以内联为Command

Luk*_*ski 12

这是一种通过仅使用msbuild和内联任务异步执行进程的简单方法.这仅适用于MSBuild V4.0及更高版本(上帝保佑MSBuild人员添加此功能!).您不需要任何外部扩展包.

实际上,我们正在采用上面建议的代码并将其放入内联任务中.随意摆弄代码以满足您的需求.

此解决方案的重点在于,它可以让您实现结果,而无需为自定义任务创建单独的dll.扩展包中的实现肯定更加可靠,但这可以作为解决此问题的快速方法.您还可以准确地自定义运行方式.

  <!--Launch a Process in Parallel-->
  <UsingTask TaskName="ExecAsync" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <!--The file path is the full path to the executable file to run-->
      <FilePath ParameterType="System.String" Required="true" />
      <!--The arguments should contain all the command line arguments that need to be sent to the application-->
      <Arguments ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs">
        <![CDATA[
  string name = System.IO.Path.GetFileNameWithoutExtension(FilePath);
  Log.LogMessage("Starting {0}...", name);        
  System.Diagnostics.ProcessStartInfo processStartInfo = new System.Diagnostics.ProcessStartInfo(FilePath, Arguments);
  processStartInfo.UseShellExecute = true;
  System.Diagnostics.Process.Start(processStartInfo);
  Log.LogMessage("Finished running process {0}.", name);
  ]]>
      </Code>
    </Task>
  </UsingTask>
Run Code Online (Sandbox Code Playgroud)

然后,您可以按照以下方式从普通脚本中调用ExecAsync任务.注意:下面的我的脚本用于收集应用程序的代码覆盖率.

<!--Start listening for coverage data:-->
<Message Text="Starting to listen for coverage..."/>
<ExecAsync FilePath='$(VSPerfCmdExePath)' Arguments='/start:coverage /output:"$(CoverageFilePath)"' ContinueOnError='true'/>
<Message Text="Listening for coverage..."/>

<!--Start App with Coverage:-->
<Message Text="Starting App..."/>
<Exec Command='"$(AppCoverageLatestExePath)"' ContinueOnError='true' WorkingDirectory='$(AppCoverageLatestFolder)'/>
<Message Text="App shut down."/>

<!--Stop gathering coverage results:-->
<Message Text="Stopping listening for coverage..."/>
<Exec Command='"$(VSPerfCmdExePath)" /shutdown'/>
<Message Text="Coverage shut down."/>
Run Code Online (Sandbox Code Playgroud)

这是对那里发生的事情的描述:

  1. 首先,我关闭性能工具,以便它监听覆盖范围.我使用AsyncExec任务执行此操作,因为通常在MSBuild中运行时工具会阻塞(请参阅此处).
  2. 接下来,我们开始我们想要收集报道的程序.
  3. 然后,一旦完成,我们就会关闭覆盖工具.

  • 请注意,对于 .NET Core 项目,您需要调整任务工厂和程序集文件,如下所示:`&lt;UsingTask TaskName="ExecAsync" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core。 dll"&gt;` (4认同)

Joh*_*lla 8

你不能用本地人做Exec.但是您可以编写自己的异步触发器,如下例所示:

  public class AsyncExec : Exec {
    protected override int ExecuteTool(string pathToTool,
                                       string responseFileCommands,
                                       string commandLineCommands) {
      Process process = new Process();
      process.StartInfo = GetProcessStartInfo(pathToTool, commandLineCommands);
      process.Start();
      return 0;
    }

    protected virtual ProcessStartInfo GetProcessStartInfo(string executable,
                                                           string arguments) {
      if (arguments.Length > 0x7d00) {
        this.Log.LogWarningWithCodeFromResources("ToolTask.CommandTooLong", new object[] { base.GetType().Name });
      }
      ProcessStartInfo startInfo = new ProcessStartInfo(executable, arguments);
      startInfo.WindowStyle = ProcessWindowStyle.Hidden;
      startInfo.CreateNoWindow = true;
      startInfo.UseShellExecute = true;
      string workingDirectory = this.GetWorkingDirectory();
      if (workingDirectory != null) {
        startInfo.WorkingDirectory = workingDirectory;
      }
      StringDictionary environmentOverride = this.EnvironmentOverride;
      if (environmentOverride != null) {
        foreach (DictionaryEntry entry in environmentOverride) {
          startInfo.EnvironmentVariables.Remove(entry.Key.ToString());
          startInfo.EnvironmentVariables.Add(entry.Key.ToString(), entry.Value.ToString());
        }
      }
      return startInfo;
    }
  }
Run Code Online (Sandbox Code Playgroud)

然后你可以运行:

<AsyncExec Command="..." />
Run Code Online (Sandbox Code Playgroud)


MiF*_*vil 5

使用MSBuild/Web部署项目启动程序时回答,而不是等待它

<Exec Command="..." Timeout="2000"></Exec>
Run Code Online (Sandbox Code Playgroud)

  • 发生超时时,看起来该进程被终止.这可能不是你想要的. (3认同)
  • 如果您不希望任务在超时时发出错误信号,则还应设置ContinueOnError ="true". (2认同)

小智 5

MSBuild Extension Pack中尝试AsyncExec 。