2017-06-18 52 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 
    }