msbuild失败并返回1,当我将stdout和stderr分配给os.devnull时,其他情况返回0

1 投票
1 回答
580 浏览
提问于 2025-04-17 08:15

我正在尝试写一个Python脚本,这个脚本的功能是从一个Mercurial代码库中检出一个版本,适用于Visual Studio 2010的C++项目,然后构建这个项目,最后在不同的场景下运行程序。接着,我会比较不同构建的结果等等。所以我现在只是开始做一个原型,我已经有了一些代码:

from subprocess import call
import os
import tempfile
import sys


def main():

    temp_repo_name = 'temprepo'
    d = tempfile.mkdtemp()
    os.chdir(os.path.normpath(d))

    command1 = ['hg', 'clone', r'C:\temp\1\jxg_hcr', temp_repo_name]

    devnull = open(os.devnull,'w')

    rc1 = call(command1,stdout=devnull, stderr=devnull)

    if rc1 != 0:
        print('could not clone repo into temporary directory.  Terminating Program')
        sys.exit(1)

    devnull.close()

    devnull = open(os.devnull,'w')

    os.chdir(temp_repo_name)

    command2 = [r'msbuild', r'hcr_dll.sln', r'/t:Rebuild',r'/p:Configuration=Release']
    rc2 = call(command2,stdout=devnull, stderr=devnull)

    print rc2
    if rc2 != 0:
        print('could not build repo.  Terminating Program')
        sys.exit(1)

    devnull.close()

if __name__ == '__main__':
    main()

当我运行这个代码时,控制台上会输出以下内容:

C:\programming\eclipse_workspace\hcr_cli_build>python hcr_cli_build.py
0
1
could not build repo.  Terminating Program

但是当我把command2那一行改成

rc2 = call(command2)

时,我得到的结果是

0
<bunch of build output>
0

而且构建成功了。我不知道为什么在重定向的时候会失败。

有没有什么想法?也许是我看不出来的简单错误?

注意:我觉得其实每次都关闭再重新打开devnull并不是必要的,但这是我在尝试解决问题时做的一个实验。即使我一直保持它打开,最后再关闭,结果也是一样的。

编辑1:根据David Hess的建议,我在命令行中尝试时也失败了。

编辑2:我还确认了,当我创建一个空的C#控制台应用程序并使用默认的Main函数时,也会出现同样的问题。当msbuild没有重定向到NUL时,它可以通过图形界面和命令行构建,但一旦重定向,就会返回1并且不构建。

悬赏编辑:我最想知道的是为什么会发生这种情况。显然,我也希望能够安静地成功构建,并在返回代码为0时输出一条消息说“构建成功”,所以如果没有人能告诉我为什么会这样,悬赏将给出最佳解决方案。

我还在mintty.exe上尝试了一个bash脚本:

#!/bin/bash
for i in 1 2 3 4
 do
  echo "doing $i"
  msbuild.exe /c/temp/$i/jxg_hcr/hcr_dll.sln //t:Rebuild //p:Configuration=Release
  echo $?
 done

这个可以正常工作(它会打印所有输出,成功构建,然后在控制台上打印0),但是

#!/bin/bash
for i in 1 2 3 4
 do
  echo "doing $i"
  msbuild.exe /c/temp/$i/jxg_hcr/hcr_dll.sln //t:Rebuild //p:Configuration=Release > /dev/null
  echo $?
 done

这个则没有执行构建,只返回1到控制台。

1 个回答

撰写回答