MSBuild BuildInParallel,自定义任务生成进程无法运行
我使用 MSBuild 任务的 BuildInParallel 属性来并行运行生成项目。根项目正在构建四个子项目。子项目使用自定义 MSBuild 任务,该任务使用 System.Diagnostics.Process 启动新进程。由于某种原因,当 UseShellExecute 为 false 时,生成的进程无法正常运行。我不知道为什么会这样,也无法弄清楚错误是什么 - 所发生的只是 Process.ExitCode 为 1,无一例外。
这是自定义 MSBuild 任务:
using System;
using Microsoft.Build.Utilities;
using System.Diagnostics;
public class MSBuildProcessTask : Task
{
public string Executable { get; set; }
public string Arguments { get; set; }
public override bool Execute()
{
using (var p = new Process())
{
try
{
p.StartInfo = new ProcessStartInfo(Executable, Arguments)
{
UseShellExecute = false,
//RedirectStandardOutput = true
};
//p.OutputDataReceived += (o, e) =>
//{
// if (e.Data != null)
// {
// Log.LogMessage(MessageImportance.Normal, e.Data);
// }
//};
p.Start();
//p.BeginOutputReadLine();
p.WaitForExit();
}
catch (Exception e)
{
throw; // for setting breakpoint
}
finally
{
if (p.ExitCode != 0)
{
Log.LogError("Error. Exit code: " + p.ExitCode);
}
p.Close();
}
}
return true;
}
}
这是根 MSBuild 项目文件(测试.proj,实际上我只在这里构建两个子项目,但仍然收到错误..):
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="MSBuildProcessTask" AssemblyFile="C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\bin\Debug\MSBuildProcessTask.dll" />
<Target Name="Default">
<ItemGroup>
<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.1.proj" />
<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.2.proj" />
<!--<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.3.proj" />
<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.4.proj" />-->
</ItemGroup>
<MSBuild BuildInParallel="true" Projects="@(ProjectFiles)" />
</Target>
</Project>
这是子项目文件的示例(Test.1.proj):
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="MSBuildProcessTask" AssemblyFile="C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\bin\Debug\MSBuildProcessTask.dll" />
<Target Name="Default">
<Message Text="Hello" />
<MSBuildProcessTask Executable="sqlcmd" Arguments="-S .\SQLEXPRESS -Q "SELECT @@VERSION"" />
</Target>
</Project>
我的命令行是: C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /m /nr:false C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj
和这是一个示例输出:
C:\Users\Tom>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /m /nr:false C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildPr
ocessTask\Test.proj
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.235]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 16/08/2011 22:22:06.
1>Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" on node 1 (default targets).
1>Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (1) is building "C:\Users\Tom\Sandbox\reposito
ry_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.1.proj" (2) on node 1 (default targets).
2>Default:
Hello
1>Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (1) is building "C:\Users\Tom\Sandbox\reposito
ry_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj" (3) on node 2 (default targets).
------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------
Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64)
Mar 29 2009 10:11:52
Copyright (c) 1988-2008 Microsoft Corporation
Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
(1 rows affected)
3>Default:
Hello
2>Done Building Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.1.proj" (default targets).
3>C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj(6,3): error : Error. Exit code: 1
3>Done Building Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj" (default targets).
1>Done Building Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (default targets).
Build succeeded.
"C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (default target) (1) ->
"C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj" (default target) (3) ->
(Default target) ->
C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj(6,3): error : Error. Exit code: 1
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.23
C:\Users\Tom>
正如您所看到的,我们仅从 SQLCMD 命令之一获取输出。
I'm using the BuildInParallel attribute of the MSBuild task to run build projects in parallel. The root project is building four child projects. The child projects are using a custom MSBuild task which starts a new process using System.Diagnostics.Process. For some reason the spawned process fails to run properly when UseShellExecute is false. I've no idea why this is and I can't figure out what the error is - all that happens is the Process.ExitCode is 1, no exception..
Here's the custom MSBuild task:
using System;
using Microsoft.Build.Utilities;
using System.Diagnostics;
public class MSBuildProcessTask : Task
{
public string Executable { get; set; }
public string Arguments { get; set; }
public override bool Execute()
{
using (var p = new Process())
{
try
{
p.StartInfo = new ProcessStartInfo(Executable, Arguments)
{
UseShellExecute = false,
//RedirectStandardOutput = true
};
//p.OutputDataReceived += (o, e) =>
//{
// if (e.Data != null)
// {
// Log.LogMessage(MessageImportance.Normal, e.Data);
// }
//};
p.Start();
//p.BeginOutputReadLine();
p.WaitForExit();
}
catch (Exception e)
{
throw; // for setting breakpoint
}
finally
{
if (p.ExitCode != 0)
{
Log.LogError("Error. Exit code: " + p.ExitCode);
}
p.Close();
}
}
return true;
}
}
And here's the root MSBuild project file (Test.proj, actually I'm only building two child project here but still get the error..):
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="MSBuildProcessTask" AssemblyFile="C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\bin\Debug\MSBuildProcessTask.dll" />
<Target Name="Default">
<ItemGroup>
<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.1.proj" />
<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.2.proj" />
<!--<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.3.proj" />
<ProjectFiles Include="$(MSBuildProjectDirectory)\Test.4.proj" />-->
</ItemGroup>
<MSBuild BuildInParallel="true" Projects="@(ProjectFiles)" />
</Target>
</Project>
And here's an example of the child project files (Test.1.proj):
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="MSBuildProcessTask" AssemblyFile="C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\bin\Debug\MSBuildProcessTask.dll" />
<Target Name="Default">
<Message Text="Hello" />
<MSBuildProcessTask Executable="sqlcmd" Arguments="-S .\SQLEXPRESS -Q "SELECT @@VERSION"" />
</Target>
</Project>
My command line is: C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /m /nr:false C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj
And here's a sample output:
C:\Users\Tom>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /m /nr:false C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildPr
ocessTask\Test.proj
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.235]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 16/08/2011 22:22:06.
1>Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" on node 1 (default targets).
1>Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (1) is building "C:\Users\Tom\Sandbox\reposito
ry_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.1.proj" (2) on node 1 (default targets).
2>Default:
Hello
1>Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (1) is building "C:\Users\Tom\Sandbox\reposito
ry_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj" (3) on node 2 (default targets).
------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------
Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (X64)
Mar 29 2009 10:11:52
Copyright (c) 1988-2008 Microsoft Corporation
Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
(1 rows affected)
3>Default:
Hello
2>Done Building Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.1.proj" (default targets).
3>C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj(6,3): error : Error. Exit code: 1
3>Done Building Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj" (default targets).
1>Done Building Project "C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (default targets).
Build succeeded.
"C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.proj" (default target) (1) ->
"C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj" (default target) (3) ->
(Default target) ->
C:\Users\Tom\Sandbox\repository_trunk\MSBuildProcessTask\MSBuildProcessTask\Test.2.proj(6,3): error : Error. Exit code: 1
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.23
C:\Users\Tom>
As you can see we only get output from one of the SQLCMD commands.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
没有机会说出到底是什么导致了问题,您必须自己调查或至少提供有关错误的更多详细信息。
尝试运行指定诊断详细级别的 MSBuild,它将在运行时转储非常详细的输出:
No chance to say what exactly causes a problem, you have to investigate it yourself or at least provide more details regarding an error.
Try out to run
MSBuild
specifying diagnostic verbosity level, it will dump very detailed output whilst run:您是否尝试为每个目标指定一个唯一的名称(而不是“默认”)?
我认为当您包含一个项目时,msbuild 会将包含的项目的目标扩展到当前项目。当您添加与现有目标同名的另一个目标时,现有目标将被覆盖。
您可以使用 /preprocess 开关查看展开的项目,如此处所述。
Did you try giving each target a unique name (not 'Default')?
I think that when you include a project, msbuild expands the included project's targets into the current project. When you add another target with the same name as an existing one, the existing one is overridden.
You can see what your expanded project looks like using the /preprocess switch as described here.