来自文件

时间:2017-06-18 14:39:25

标签: c# .net winapi pinvoke

我使用this answer中的示例代码。它有效。

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

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;

1 个答案:

答案 0 :(得分:0)

基于评论。

  1. startupInfo.dwFlags设为0x00000100
  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
    }