需要运行.exe文件7秒,然后在文本文件中执行输入和输出时终止exe

时间:2015-06-05 14:22:04

标签: windows batch-file cmd

我想创建一个运行程序7秒的批处理文件,而不管其他程序的执行是否完成。我还希望程序应该输入并将输出保存在外部文件中。这就是我试过的:

start program.exe
ping 1.1.1.1 -n 1 -w 7000 > nul
taskkill /im program.exe /f
rem continue here

以上工作正常,但当我用以下代码替换第1行时

start program.exe < in.txt > out.txt

然后从文件输入和文件中的输出都不起作用。

1 个答案:

答案 0 :(得分:3)

cmd未设置STARTF_USESTDHANDLES CreateProcess结构的STARTUPINFO标记。相反,它暂时重定向自己的标准句柄并依赖继承。即使cmd必须调用ShellExecuteEx,这种方法仍然有效,因为它缺少明确设置标准句柄的方法。

但是,在进程创建标志中设置CREATE_NEW_CONSOLE时,重定向自己的标准句柄不起作用,这是start命令的默认值。要避免此问题,请使用/b选项阻止创建新控制台。

您可能还想将stderr重定向到stdout或文件。这可以防止将错误写入控制台。例如:

  • start /b program.exe <in.txt >out.txt 2>&1
  • start /b program.exe <in.txt >out.txt 2>err.txt
  • start /b program.exe <in.txt >out.txt 2>nul

使用Debugging Tools for Windows

的示例
(test) C:\>cdb -Goxi ld cmd

Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: cmd
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(ed0.1770): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`77848700 cc              int     3
0:000> .reload /f
Reloading current modules
.....
0:000> bp CreateProcessW
0:000> g

在新控制台中运行where.exe。

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

(test) C:\>start /w where.exe <nul >nul
Breakpoint 0 hit
kernel32!CreateProcessW:
00000000`775a0660 4883ec68        sub     rsp,68h

请注意,cmd.exe会在调用StandardOutput之前重定向其CreateProcess

0:000> ?? ((ntdll!_PEB *)@$peb)->ProcessParameters->StandardOutput
void * 0x00000000`00000060

0:000> !handle 60 3
Handle 60
  Type          File
  Attributes    0
  GrantedAccess 0x120196:
         ReadControl,Synch
         Write/Add,Append/SubDir/CreatePipe,WriteEA,ReadAttr,WriteAttr
  HandleCount   2
  PointerCount  3

进程创建标志,即dwCreationFlags,第6个参数:

0:000> dd (@rsp + 6*8) l1
00000000`00182c58  00080410

传递为0x80410,它是以下标志的按位OR:

  • EXTENDED_STARTUPINFO_PRESENT
  • CREATE_UNICODE_ENVIRONMENT
  • CREATE_NEW_CONSOLE

因为创建了一个新的控制台,where.exe不会继承cmd的标准句柄:

0:000> g
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(1550.1a80): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`77848700 cc              int     3

1:001> ?? ((ntdll!_PEB *)@$peb)->ProcessParameters->StandardOutput
void * 0x00000000`00000007

注意:在Windows 8+中,控制台句柄只是一个常规文件句柄,所以你必须要更深入。

我在这个例子中使用的是Windows 7,因此控制台句柄是通过设置低2位标记的伪句柄(例如3,7,11 =&gt; 0b0011,0b0111,0b1011)。 '假'我的意思是它们不在用于内核对象句柄的进程句柄表中。因此,例如,您无法使用调试器!handle命令来检查句柄7:

1:001> !handle 7 f
Could not duplicate handle 7, error 87

在Windows 7中,控制台句柄由控制台主机进程conhost.exe分配和管理。它们被标记,因此Windows基本功能可以通过NtRequestWaitReplyPort对conhost.exe进行必要的LPC调用。

上面的示例演示了如何创建新控制台来覆盖继承cmd的重定向标准句柄。现在让我们添加/b选项以防止创建新控制台。

1:001> g

(test) C:\>start /b /w where.exe <nul >nul
Breakpoint 0 hit
kernel32!CreateProcessW:
00000000`775a0660 4883ec68        sub     rsp,68h

dwCreationFlags是0x80600:

0:000> dd (@rsp + 6*8) l1
00000000`00182c58  00080600

是以下创建标志的按位OR:

  • EXTENDED_STARTUPINFO_PRESENT
  • CREATE_UNICODE_ENVIRONMENT
  • CREATE_NEW_PROCESS_GROUP

(指定/b的副作用是将进程创建为新进程组的领导者。如果是控制台进程,则允许生成以组为目标的Ctrl + Break事件。)

在这种情况下,where.exe会从cmd.exe继承重定向的标准句柄:

0:000> g
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(1508.1534): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`77848700 cc              int     3

1:001> ?? ((ntdll!_PEB *)@$peb)->ProcessParameters->StandardOutput
void * 0x00000000`00000064
1:001> !handle 64 3
Handle 64
  Type          File
  Attributes    0
  GrantedAccess 0x120196:
         ReadControl,Synch
         Write/Add,Append/SubDir/CreatePipe,WriteEA,ReadAttr,WriteAttr
  HandleCount   3
  PointerCount  4

同样,在Windows 7中,很容易发现控制台伪句柄,因为它通过设置句柄值的低2位来标记。对于Windows 8+,快速检查是查看文件被授予访问权限的低半字节(4位),读取数据访问权限为1,写入数据访问权限为2,附加数据访问权限为4。控制台缓冲区具有读写访问权限,而cmd的重定向使用read(<)或write(>),但不能同时使用。以上是重定向输出,您可以看到文件是通过写入和追加访问(2 + 4)打开的,但不是读取访问权限。这是一个快速检查,但如果你想确定你可以使用内核调试器,如kd.exe,或Sysinternals Process Explorer或handle.exe等工具。这些可以显示NT内核对象路径,例如Windows {8}控制台输入句柄的\Device\ConDrv\Input