MSBuild执行任务没有阻止

问题描述:

是否有人碰巧知道一个将阻止这个MSBuild任务的技巧?我真的只是想要打开浏览器并且要继续构建脚本。目前它在Exec任务中阻塞,直到资源管理器窗口关闭。MSBuild执行任务没有阻止

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

谢谢!

编辑:我希望避免为此创建自定义任务。也许有些命令行魔术存在,可以放在Command的内联中?

你不能用原生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="..." /> 
+0

很好的答案,如果这最终成为我唯一的选择。希望尽可能避免它。 – Rob 2010-03-05 18:37:11

+0

请注意,您可以包含内联此代码,而无需使用MSBuild 4.0内联任务编译单独的DLL(http://msdn.microsoft.com/zh-cn/library/dd722601.aspx)(编辑:忽略我,我看到卢克在另一个答案中提到了这一点!) – 2014-11-25 11:52:10

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

<Exec Command="..." Timeout="2000"></Exec> 
+2

如果您不希望任务在超时时发出错误信号,您还应该设置ContinueOnError =“true”。 – 2013-05-30 12:59:34

+0

@LewisJubb你能解释一下吗?对我来说,无论如何它只会发出警告,而这似乎没有效果。你使用的是哪个MS版本的版本? – 2014-05-21 21:00:04

+0

当超时发生时,看起来进程被终止。这可能不是你想要的。 – Nikolaj 2017-07-27 11:28:01

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

+2

按照我的经验,这似乎不起作用。我怀疑这个任务是以某种方式阻止它。 – 2013-02-13 18:11:19

尝试在MSBuild Extension Pack中使用AsyncExec。

以下是通过仅使用msbuild和inline任务异步执行进程的简单方法。这只适用于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. 然后,我们完成后关闭覆盖工具。