请问有没有什么技巧可以让这个MSBuild任务不阻塞?我只想打开资源管理器并让构建脚本继续执行。当前它会在Exec任务处阻塞,直到资源管理器窗口关闭。
<Target Name="OpenExplorer">
<Exec Command='explorer.exe "$(DestinationDir)"' IgnoreExitCode="true" />
</Target>
谢谢!
编辑: 我本来希望避免创建自定义任务。也许有一些命令行技巧可以内联放置到Command
里面?
请问有没有什么技巧可以让这个MSBuild任务不阻塞?我只想打开资源管理器并让构建脚本继续执行。当前它会在Exec任务处阻塞,直到资源管理器窗口关闭。
<Target Name="OpenExplorer">
<Exec Command='explorer.exe "$(DestinationDir)"' IgnoreExitCode="true" />
</Target>
谢谢!
编辑: 我本来希望避免创建自定义任务。也许有一些命令行技巧可以内联放置到Command
里面?
以下是一种仅使用 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."/>
以下是那里正在发生的事情的描述:
使用原生的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;
}
}
然后您可以使用以下命令运行:
<AsyncExec Command="..." />
在使用MSBuild/Web部署项目启动程序而不等待其完成时作出回答。
<Exec Command="..." Timeout="2000"></Exec>
在MSBuild扩展包中尝试使用AsyncExec。
在Exec中的命令被放置在批处理文件中并执行。因此,您可以像在控制台窗口中一样在命令中使用"start"关键字。这将解决问题。
GetFileNameWithoutExtension()
函数时遇到了问题,所以我删除了日志记录行,然后它就完美地工作了。甚至在<ExecAsync Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' "
下也能正常工作。谢谢! - CAD bloke<UsingTask TaskName="ExecAsync" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
。 - 0xced