""" cmdfix.py - fix piping problems with cmd.exe $Id: cmdfix.py.txt,v 1.1 2005/02/02 06:32:35 u37519820 Exp $ With Win32 cmd.exe, 'python some.py >t' works but 'some.py >t' doesn't. cmdfix.py gets around this problem by using alternative piping syntax: some.py @input !output #error or some.py @input !#bothoutput Adding .py/.pyc to the environment PATHEXT= changes this to simply: some @input !#bothoutput To install, change the registry entry for Python.File/shell/open/command to: D:\python\python.exe D:\python\cmdfix.py D:\python\python.exe "%1" %* Similar changes are required for Python.CompiledFile (.pyc) as well. If you precompile cmdfix.py you can use cmdfix.pyc in it's place for likely unnoticeable performance improvements. This script is written generically, not assuming the executed process is python, so it would also work for perl or other scripting languages. The !# syntax is also useful for 'normal' commands, because cmd normally won't produce 'interleaved' stdout/stderr. Unfortunately, the .py configuration will preparse the @!# if trying to use cmdfix.py directly. Arguments containing spaces are reassembled appropriately. """ import sys import string import pywintypes import win32api import win32event import win32file import win32process def main(argc, argv): # oops - incorrect usage if not argc: print __doc__ return # input file name tagged with @ iFileName = arg(argv, '@') if iFileName: i = open_read(iFileName); win32api.SetStdHandle(win32api.STD_INPUT_HANDLE, i) # output file name tagged with ! oFileName = arg(argv, '!') if oFileName: both = 0 # '!#' gives mixed standard and error output, # but results can be affected by buffering differences if oFileName[0]=='#': both = 1; oFileName = oFileName[1:] o = open_write(oFileName) win32api.SetStdHandle(win32api.STD_OUTPUT_HANDLE, o) if both: win32api.SetStdHandle(win32api.STD_ERROR_HANDLE, o) # error file name tagged with # eFileName = arg(argv, '#') if eFileName: e = open_write(eFileName); # 00.8.17 oops, type here, had o instead of e win32api.SetStdHandle(win32api.STD_ERROR_HANDLE, e); # put the rest of the command back together, and execute it cmd = join(argv) execute(cmd) # arg - return a tagged argument and delete it from the list def arg(args, tag): i = 0 for a in args: if a[0] == tag: del args[i] return a[1:] i = i + 1 # join the arguments back together, handle arguments with spaces by quoting def join(args): i = 0 for a in args: if string.find(a, ' ') >= 0: args[i] = '"%s"' % a i = i + 1 return string.join(args) # windows open routines def open_read(fileName): return open(fileName, win32file.GENERIC_READ, win32file.OPEN_EXISTING) def open_write(fileName): return open(fileName, win32file.GENERIC_WRITE, win32file.CREATE_ALWAYS) def open(fileName, wAccess, wDisposition): sa = pywintypes.SECURITY_ATTRIBUTES() sa.bInheritHandle = 1; return win32file.CreateFile(fileName, wAccess, 0, sa, wDisposition, 0, 0) # windows execute and wait def execute(command): startupInfo = win32process.STARTUPINFO() pinfo = win32process.CreateProcess(None, command, None , None, 1, 0, None, None, startupInfo) return win32event.WaitForSingleObject(pinfo[0], win32event.INFINITE) # invoke main if appropriate if __name__ == "__main__": main(len(sys.argv)-1, sys.argv[1:])