2009-12-29 120 views

回答

2

你爲什麼不使用Process.Start Method以下過載?

+0

它沒有爲我工作。我碰到一個「應用程序未能正確初始化」看到相關的問題:http://stackoverflow.com/questions/1972649/help-with-using-createprocesswithlogonw-in-c/1972860#1972860 – 2009-12-29 17:43:40

2

主叫CreateProcessWithLogonW與重定向STD輸入\輸出\錯誤線程是相同於執行以下,使用的System.Diagnostics.Process類具有指定的用戶\域\密碼字段和重定向設置*字段代碼爲真。其實通過觀察StartWithCreateProcess使用反射過程類的私有方法,你會發現,NativeMethods.CreateProcessWithLogonW程序被執行,如果有應用上述條件。

Process process1 = new Process(); 
process1.StartInfo.FileName = @"c:\windows\system32\ping.exe"; 
process1.StartInfo.Arguments = "127.0.0.1"; 
// all 3 redirect* fields have to be set 
process1.StartInfo.RedirectStandardOutput = true; 
process1.StartInfo.RedirectStandardInput = true; 
process1.StartInfo.RedirectStandardError = true; 
process1.StartInfo.UseShellExecute = false; 
process1.StartInfo.UserName = "admin"; 
process1.StartInfo.Domain = System.Environment.MachineName; 
SecureString password = new SecureString(); 
foreach (char a in "password".ToCharArray()) 
    password.AppendChar(a); 
process1.StartInfo.Password = password; 
process1.Start(); 
string output = process1.StandardOutput.ReadToEnd(); 
Console.WriteLine(output); 
process1.WaitForExit(); 

爲原題:

你需要設置管控點的STARTUPINFO的stdOutput,stdError,stdInput領域。水木清華這樣的:

StartupInfo startupInfo = new StartupInfo(); 
startupInfo.reserved = null; 
startupInfo.flags = STARTF_USESTDHANDLES; 
startupInfo.showWindow = SW_SHOW; 
... 
SafeFileHandle inputHandle = null; 
SafeFileHandle outputHandle = null; 
SafeFileHandle errorHandle = null; 

CreatePipe(out inputHandle, out startupInfo.stdInput, true); 
CreatePipe(out outputHandle, out startupInfo.stdOutput, false); 
CreatePipe(out errorHandle, out startupInfo.stdError, false); 
下面

是CreatePipe實現:

public static void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) 
{ 
    SECURITY_ATTRIBUTES lpPipeAttributes = new SECURITY_ATTRIBUTES(); 
    lpPipeAttributes.bInheritHandle = true; 
    SafeFileHandle hWritePipe = null; 
    try 
    { 
     if (parentInputs) 
      CreatePipeWithSecurityAttributes(out childHandle, out hWritePipe, lpPipeAttributes, 0); 
     else 
      CreatePipeWithSecurityAttributes(out hWritePipe, out childHandle, lpPipeAttributes, 0); 
     if (!DuplicateHandle(GetCurrentProcess(), hWritePipe, GetCurrentProcess(), out parentHandle, 0, false, 2)) 
      throw new Exception(); 
    } 
    finally 
    { 
     if ((hWritePipe != null) && !hWritePipe.IsInvalid) 
     { 
      hWritePipe.Close(); 
     } 
    } 
} 

[StructLayout(LayoutKind.Sequential)] 
public class SECURITY_ATTRIBUTES 
{ 
    public int nLength; 
    public IntPtr lpSecurityDescriptor; 
    public bool bInheritHandle; 
    public SECURITY_ATTRIBUTES() 
    { 
     nLength = 12; 
     lpSecurityDescriptor = IntPtr.Zero; 
    } 
} 

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, 
    SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); 
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, SafeHandle hSourceHandle, 
    IntPtr hTargetProcess, out SafeFileHandle targetHandle, int dwDesiredAccess, 
    bool bInheritHandle, int dwOptions); 
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] 
public static extern IntPtr GetCurrentProcess(); 

public static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, 
    SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) 
{ 
    hReadPipe = null; 
    if ((!CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize) || hReadPipe.IsInvalid) || hWritePipe.IsInvalid) 
     throw new Exception(); 
} 

你與創建管道完成,CreateProcessWithLogonW執行可以從管道中讀取STD輸出後:

StreamWriter standardInput = new StreamWriter(new FileStream(inputHandle, FileAccess.Write, 0x1000, false), Console.InputEncoding, 0x1000); 
standardInput.AutoFlush = true; 
StreamReader reader = new StreamReader(new FileStream(outputHandle, FileAccess.Read, 0x1000, false), Console.OutputEncoding, true, 0x1000); 
StreamReader error = new StreamReader(new FileStream(errorHandle, FileAccess.Read, 0x1000, false), Console.OutputEncoding, true, 0x1000); 

while (!reader.EndOfStream) 
{ 
    string line = reader.ReadLine(); 
    if (line.Length>0) Console.WriteLine(line); 
} 
上述

代碼基本上是什麼在Process類的StartWithCreateProcess方法完成

希望這會有所幫助,至於