MSBuild exec任务没有阻塞

时间:2010-03-05 14:37:56

标签: msbuild

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

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

谢谢!

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

5 个答案:

答案 0 :(得分:10)

这是一种仅使用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>

然后,您可以按照以下方式从普通脚本中调用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."/>

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

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

答案 1 :(得分:8)

您无法使用原生Exec进行此操作。但是您可以编写自己的异步触发,如 this example

  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;
    }
  }

然后您可以运行:

<AsyncExec Command="..." />

答案 2 :(得分:5)

Starting a program with MSBuild/Web Deployment Project and not waiting for it

回答
<Exec Command="..." Timeout="2000"></Exec>

答案 3 :(得分:4)

MSBuild Extension Pack中尝试AsyncExec。

答案 4 :(得分:3)

Exec中的Command放在批处理文件中并执行。因此,您可以在命令中使用“start”关键字,就像在控制台窗口中一样。这样就可以了。