2009-12-29 43 views
1

我試圖在Windows XP中使用asp.net(C#)中的參數執行控制檯應用程序。我已經嘗試了diagnostics.Process,但我無法讓它工作,所以我切換到CreateProcessWithLogonW。我使用了http://www.pinvoke.net/default.aspx/advapi32.createprocesswithlogonw的代碼示例,但控制檯應用似乎無法運行,並且CreateProcessWithLogonW api調用的返回值爲false。幫助在C#中使用CreateProcessWithLogonW

我的控制檯應用程序的語法是這樣的:「C:\ Program Files文件\商業智能\ mycommand.exe」 ARG1參數3 ARG4如果我在DOS窗口交互運行它它運行正常。

在C#代碼,我之前和節目名稱後加上雙引號。當代碼運行時,我注意到任務管理器進程計數​​沒有增加第二個我運行它告訴我的應用程序沒有運行。 processInfo結構全部爲0。

我的問題: 1-「CreateProcessWithLogonW」調用的兩個'command'參數是否需要雙引號?現在我正在整個命令行中。

2-如何捕獲標準輸出以便知道發生了什麼?

回答

1

從PInvoke的一個例子defenitelly的作品,您就可以使用平水木清華簡單嘗試一下先?我修改了pInvoke中的代碼來執行ping 127.0.0.1,如果它適合你,請參閱下面的內容。回答你的問題:1 - 我想不需要這樣做,但可以雙向工作,2 - 你可以這樣做,但如果應用程序沒有從第一個地方開始,它不會幫助你。

示例代碼:

public const UInt32 Infinite = 0xffffffff; 
public const Int32 Startf_UseStdHandles = 0x00000100; 
public const Int32 StdOutputHandle = -11; 
public const Int32 StdErrorHandle = -12; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public struct StartupInfo 
{ 
    public int cb; 
    public String reserved; 
    public String desktop; 
    public String title; 
    public int x; 
    public int y; 
    public int xSize; 
    public int ySize; 
    public int xCountChars; 
    public int yCountChars; 
    public int fillAttribute; 
    public int flags; 
    public UInt16 showWindow; 
    public UInt16 reserved2; 
    public byte reserved3; 
    public IntPtr stdInput; 
    public IntPtr stdOutput; 
    public IntPtr stdError; 
} 

public struct ProcessInformation 
{ 
    public IntPtr process; 
    public IntPtr thread; 
    public int processId; 
    public int threadId; 
} 


[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
public static extern bool CreateProcessWithLogonW(
    String userName, 
    String domain, 
    String password, 
    UInt32 logonFlags, 
    String applicationName, 
    String commandLine, 
    UInt32 creationFlags, 
    UInt32 environment, 
    String currentDirectory, 
    ref StartupInfo startupInfo, 
    out ProcessInformation processInformation); 

[DllImport("kernel32.dll", SetLastError = true)] 
public static extern bool GetExitCodeProcess(IntPtr process, ref UInt32 exitCode); 

[DllImport("Kernel32.dll", SetLastError = true)] 
public static extern UInt32 WaitForSingleObject(IntPtr handle, UInt32 milliseconds); 

[DllImport("Kernel32.dll", SetLastError = true)] 
public static extern IntPtr GetStdHandle(IntPtr handle); 

[DllImport("Kernel32.dll", SetLastError = true)] 
public static extern bool CloseHandle(IntPtr handle); 


private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    StartupInfo startupInfo = new StartupInfo(); 
    startupInfo.reserved = null; 
    startupInfo.flags &= Startf_UseStdHandles; 
    startupInfo.stdOutput = (IntPtr)StdOutputHandle; 
    startupInfo.stdError = (IntPtr)StdErrorHandle; 

    UInt32 exitCode = 123456; 
    ProcessInformation processInfo = new ProcessInformation(); 

    String command = @"c:\windows\system32\ping.exe 127.0.0.1"; 
    String user = "admin"; 
    String domain = System.Environment.MachineName; 
    String password = "password"; 
    String currentDirectory = System.IO.Directory.GetCurrentDirectory(); 

    try 
    { 
     CreateProcessWithLogonW(
      user, 
      domain, 
      password, 
      (UInt32)1, 
      null, 
      command, 
      (UInt32)0, 
      (UInt32)0, 
      currentDirectory, 
      ref startupInfo, 
      out processInfo); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.ToString()); 
    } 

    Console.WriteLine("Running ..."); 
    WaitForSingleObject(processInfo.process, Infinite); 
    GetExitCodeProcess(processInfo.process, ref exitCode); 

    Console.WriteLine("Exit code: {0}", exitCode); 

    CloseHandle(processInfo.process); 
    CloseHandle(processInfo.thread); 
} 

希望這會有所幫助,至於

+0

當我啓動像notepad.exe之類的代碼時,該代碼起作用。不過,我需要從我的應用程序捕獲輸出。這可以告訴我,如果應用程序的工作,但遇到一個錯誤,甚至沒有找到「文件」是有幫助的,這可以告訴我,我沒有正確構建命令。 – 2009-12-29 07:23:43

+1

爲了重定向標準輸出,您必須設置StartupInfo結構的stdInput,stdOutput,stdError字段。有關如何執行此操作的示例,可以使用反射器檢查System.Diagnostics.Process類的StartWithCreateProcess方法。簡而言之,您需要創建管道(CreatePipe API調用),將管道的句柄分配給StartupInfo的stdInput,stdOutput和stdError字段,然後使用FileStreams將數據從\寫入管道。 – 2009-12-29 17:35:32

0

如果進程不運行在所有的,你應該得到一個例外。你打電話時是否會遇到異常情況,如果有,哪個例外? (請將這個附加信息添加到您的問題)。

如果你沒有得到一個例外,它幾乎可以肯定的是,應用程序正在執行的情況,但事情是做不到這一點app--裏面,它的退出速度不夠快,你沒有看到它執行。要驗證或排除這種可能性,您可以添加一個Thread.Sleep(20000)調用作爲mycommand.exe應用程序的第一行,它應該使應用程序保持20秒左右,以便您可以使用任務管理器找到它並轉移您的調試從調用者應用程序到被調用者應用程序的努力。

回答你的問題#1:是的,你需要引號,因爲你的EXE的路徑中有空格。

回答你的#2:是的,你可以做到這一點,但它可能更好地爲您拆分到一個單獨的SO問題,一旦你已經回答了第一個,更緊迫的問題。

+0

沒有例外。 mycommand.exe是第三方工具,所以我不能添加任何東西。如果應用程序正在執行,任務管理器中的計數器應該至少增加1,然後減少1 ..即使在一秒鐘內。 – 2009-12-29 07:20:27