2017-06-18 129 views
-1

我使用this answer中的示例代码。有用。Pinvoke CreateProcess从文件输入/输出

但我需要将标准输入/输出重定向到文件。 进程启动信息结构有字段:

public IntPtr hStdInput; 
public IntPtr hStdOutput; 
public IntPtr hStdError; 

我想是这样的:

StartupInfo startupInfo = new StartupInfo(); 
startupInfo.cb = Marshal.SizeOf((object)startupInfo); 
startupInfo.dwFlags = 128; 

FileStream fs = new FileStream(filePath, FileMode.Open); 
startupInfo.hStdInput = fs.Handle; 

而且这是行不通的。

如何将文件作为标准输入/输出传递?

UPD1

我怎么叫CreateProccess:

StartupInfo startupInfo = new StartupInfo(); 
startupInfo.cb = Marshal.SizeOf((object)startupInfo); 
startupInfo.dwFlags = 128; 

FileStream fs = new FileStream(filePath, FileMode.Open); 
startupInfo.hStdInput = fs.Handle; 

Pinvoke.SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX); 
CreationFlags dwCreationFlags = CreationFlags.CREATE_BREAKAWAY_FROM_JOB | CreationFlags.CREATE_SUSPENDED | CreationFlags.CREATE_SEPARATE_WOW_VDM; 
SecurityAttributes securityAttributes = new SecurityAttributes(); 
securityAttributes.bInheritHandle = 1; 
ProcessInformation pi; 

if (!Pinvoke.CreateProcess(null, configuration.RunString, ref securityAttributes, ref securityAttributes, boolInheritHandles: true, dwCreationFlags: dwCreationFlags, lpEnvironment: IntPtr.Zero, lpszCurrentDir: configuration.Directory, startupInfo: ref startupInfo, pi: out pi)) 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 

UPD2。 我加SetHandleInformation通话,但它并不能帮助:根据意见

FileStream fs = new FileStream(@"C:\input.txt", FileMode.Open, FileAccess.Read); 
Pinvoke.SetHandleInformation(fs.Handle, 0x00000001, 0x00000001); 
startupInfo.hStdInput = fs.Handle; 
+0

文件句柄必须是*可继承*和过程必须用* bInheritHandles == true * – RbMm

+0

@RbMm创建感谢您的评论。我在'CreateProcess'调用和'securityAttributes'中添加了true,但它并没有帮助 – Backs

+0

,但是您需要在创建/打开文件句柄中使用securityAttributes - 而不是进程 – RbMm

回答

0

  1. 设置startupInfo.dwFlags0x00000100
  2. 添加新的功能CreateFile

    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern IntPtr CreateFile(string lpFileName, DesiredAccess dwDesiredAccess, uint dwShareMode, ref SecurityAttributes lpSecurityAttributes, CreationDisposition dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); 
    
  3. 创建输入/输出处理:

    var input = Pinvoke.CreateFile(inputFile, DesiredAccess.GENERIC_READ, 0, ref securityAttributes, 
          CreationDisposition.OPEN_EXISTING, 0, IntPtr.Zero); 
    
    var output = Pinvoke.CreateFile(outputFile, DesiredAccess.GENERIC_WRITE, 0, ref securityAttributes, 
          CreationDisposition.CREATE_NEW, 0, IntPtr.Zero); 
    
    startupInfo.hStdInput = input; 
    startupInfo.hStdOutput = output; 
    
    ... 
    
    public enum DesiredAccess : uint 
    { 
        GENERIC_WRITE = 30, 
        GENERIC_READ = 31 
    } 
    
    public enum CreationDisposition : uint 
    { 
        CREATE_NEW = 1, 
        CREATE_ALWAYS = 2, 
        OPEN_EXISTING = 3, 
        OPEN_ALWAYS = 4, 
        TRUNCATE_EXISTING = 5 
    }