使用GUI应用程序的启动命令时的批量输出重定向

时间:2009-08-13 14:27:11

标签: python windows batch-file output-redirect

这是情景:

我们有一个Python脚本可以启动Windows批处理文件并将其输出重定向到文件。之后它会读取文件,然后尝试删除它:

os.system(C:\batch.bat >C:\temp.txt 2>&1)
os.remove(C:\temp.txt)

在batch.bat中,我们启动一个这样的Windows GUI程序:

start c:\the_programm.exe

这一切都在批处理中。

现在os.remove()因“权限被拒绝”而失败,因为temp.txt仍然被系统锁定。这似乎是由仍在运行的the_programm.exe引起的(其输出似乎也被重定向到temp.txt)。

任何想法如何启动the_programm.exe而没有在temp.txt仍在运行时锁定? Python部分几乎不可更改,因为这是一个工具(BusyB)。

实际上我不需要the_programm.exe的输出,所以问题的实质是:如何解析the_programm.exe与锁定temp.txt的输出? 或者:如何在不继承批量输出重定向的情况下使用START或其他Windows命令启动程序?

6 个答案:

答案 0 :(得分:2)

这有点hacky,但你可以尝试一下。它使用AT命令在将来运行the_programm.exe最多一分钟(使用%TIME%环境变量和SET算法计算它。)

batch.bat:

@echo off
setlocal
:: store the current time so it does not change while parsing
set t=%time%
:: parse hour, minute, second
set h=%t:~0,2%
set m=%t:~3,2%
set s=%t:~6,2%
:: reduce strings to simple integers
if "%h:~0,1%"==" " set h=%h:~1%
if "%m:~0,1%"=="0" set m=%m:~1%
if "%s:~0,1%"=="0" set s=%s:~1%
:: choose number of seconds in the future; granularity for AT is one
:: minute, plus we need a few extra seconds for this script to run
set x=70
:: calculate hour and minute to run the program
set /a x=s + x
set /a s="x %% 60"
set /a x=m + x / 60
set /a m="x %% 60"
set /a h=h + x / 60
set /a h="h %% 24"
:: schedule the program to run
at %h%:%m% c:\the_programm.exe

您可以查看AT /?SET /?,了解每项内容的作用。由于您评论“不允许任何用户互动”,因此我保留了/interactive AT参数{。}}。

注意事项:

  • 无论控制面板中的区域设置如何,%TIME%似乎总是24小时,但我没有任何证据。
  • 如果系统已下载且batch.bat运行时间超过10秒,则AT命令将安排在1天后运行。您可以使用AT {job} /delete手动恢复,并将x=70增加到更可接受的范围。

遗憾的是,START命令即使在/i被忽略当前环境时,也似乎传递了父cmd.exe进程的打开文件描述符。这些文件描述符似乎被移交给子进程,即使子进程被重定向到NUL,并且即使中间shell进程终止也保持打开状态。如果您有一个批处理文件START另一个批处理文件START另一个批处理文件(等)START是一个GUI Windows应用程序,您可以在Process Explorer中看到这个。一旦中间批处理文件终止,GUI应用程序将拥有文件句柄,即使它(和中间批处理文件)都被重定向到NUL

答案 1 :(得分:0)

我认为Windows不允许您删除打开的文件。听起来你想丢掉程序的输出;将重定向到'nul'而不是做你需要的东西?

答案 2 :(得分:0)

据我所知,这是问题,他想做什么:

  1. 进行 no 更改。
  2. 编写Python代码时假设在此函数返回时不再使用“temp.txt”:

    os.system(C:\ batch.bat> C:\ temp.txt 2>& 1)

  3. 事实并非如此,因为“batch.bat”使用“start”命令生成交互式GUI程序。

  4. 如何更改“batch.bat”文件以包含:

    start c:\the_programm.exe
    pause
    

    这将使“batch.bat”文件保持运行,直到您点击该窗口上的某个键。一旦你按下一个键,“os.system”python命令将返回,然后python将调用“os.remove”。

答案 3 :(得分:0)

您在阅读完文件后是否正在关闭该文件?以下是我的最终作品:

import os

os.system('runbat.bat > runbat.log 2>&1')
f = open('runbat.log')
print f.read()
f.close()
os.remove('runbat.log')

但如果删除f.close()行,则会失败。

答案 4 :(得分:0)

如果您只是立即删除文件,为什么要捕获到文件?

这个怎么样:

os.system(C:\batch.bat >nul 2>&1)
编辑:哎呀,我错过了关于阅读文件的评论,我只注意到了代码。

答案 5 :(得分:0)

最后,我找到了一个合适的解决方案:

我不再使用批处理文件来启动the_programm.exe,而是使用Python脚本:

from subprocess import Popen

     if __name__ == '__main__':
          Popen('C:/the_programm.exe', close_fds=True)

close_fds参数将文件句柄与.exe进程分离!就是这样!