2009-12-07 30 views
2

我需要自動執行命令行應用程序。它要求用戶輸入密碼。我所有的通過STDIN發送密碼失敗。現在我試圖用一個使用.NET的包裝程序來做到這一點。.NET:將數據注入進程的輸入緩衝區

我開始了應用程序創建一個新的進程,設置StartInfo -Properties,然後啓動過程:

Dim app_path As String 
Dim app_args As String 
Dim myProcess As Process = New Process() 
myProcess.StartInfo.FileName = app_path 
myProcess.StartInfo.Arguments = app_args 
myProcess.StartInfo.UseShellExecute = False 
myProcess.Start() 

我曾嘗試使用StartInfo.RedirectStandardInput物業,但沒有成功。

現在我來到了防空火炮功能WriteConsoleInputkernel32.dll我包括這樣的:

Declare Function WriteConsoleInput Lib "kernel32.dll" Alias "WriteConsoleInputA" (ByVal hConsoleInput As Integer, ByVal lpBuffer As String, ByVal nNumberOfCharsToWrite As Integer, ByRef lpNumberOfCharsWritten As Integer) As Boolean 

我可以通過myProcess.Handle屬性來獲取進程的句柄。但是用這種方式將輸入發送到輸入緩衝區也是不可能的。

我發現了這些問題,但他們並沒有幫助:

  • 我怎樣寫「PAGE DOWN」進入控制檯輸入緩衝區? (1475353)

  • 爪哇 - 傳遞輸入到外部的C/C++應用程序(1421273)

  • 控制一個Windows控制檯應用程序瓦特/標準輸入管(723424)

使用StraceNtX.exe我得到這個輸出應用程序正在等待輸入的時刻:

[T4024] GetConsoleMode(f, 12d35c, 12d3af, 77bff894, ...) = 1 
[T4024] SetConsoleMode(f, 0, 12d3af, 77bff894, ...) = 1 
[T4024] ReadConsoleInputA(f, 12d348, 1, 12d360, ...) = 1 

誰能告訴我,還有什麼嘗試或如何做正確的方式上面? 謝謝!


基於蒂姆·羅賓遜的answere我有了這個代碼了,但它不工作:

myProcess = New Process() 
myProcess.StartInfo.FileName = app_path 
myProcess.StartInfo.Arguments = app_args 
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal 
myProcess.StartInfo.UseShellExecute = False 
myProcess.Start() 
' Wait for process requesting passwort input 
System.Threading.Thread.Sleep(3000) 
Dim len As Integer 
len = 0 
Dim handle As Integer 
handle = GetStdHandle(STD_INPUT_HANDLE) 
WriteConsoleInput(handle, "Test", 4, len) 

我PROGRAMM是一個命令行應用程序,它應該作爲包裝行事。

輸入是發送的,但不是輸入到密碼字段中,而是在密碼字段下面顯示一個新的promt(甚至沒有顯示輸入)。

蒂姆,你能舉個例子嗎?

+1

什麼是需要密碼的應用程序?可能比這更容易。 – 2009-12-07 11:23:27

+1

這是思科證書管理器控制檯應用程序cisco_cert_mgr.exe 但我沒有搜索任何不同的解決方案,但似乎沒有。 – sc911 2009-12-07 13:11:31

回答

2

對不起,我遲到了,一直很忙。

這是一個完整的代碼示例,從我的代碼中剝離下來。我希望我沒有刪除重要的東西。

Private Sub runWaitInput(ByVal exe As String, ByVal parameter As String, ByVal trigger As String, ByVal input As String) 
    ' runs an process, waits for a certain string in stdout and then enters text ' 
    Dim proc As Process 
    Dim stdOut As StreamReader 
    Dim ch As Int32 
    Dim buffer As String = "" 
    Dim InputRecords(0) As KeyEventStruct 

    ' create process ' 
    proc = New Process() 
    proc.StartInfo.FileName = exe 
    proc.StartInfo.Arguments = parameter 
    proc.StartInfo.UseShellExecute = False 
    proc.StartInfo.RedirectStandardOutput = True 
    proc.Start() 

    ' redirect stdOut ' 
    stdOut = proc.StandardOutput 
    While Not proc.HasExited 
     ' read character ' 
     ch = stdOut.Read() 
     Console.Write(Convert.ToChar(ch)) 
     buffer = buffer & Convert.ToChar(ch) 
     ' read output and check for trigger-text ' 
     If buffer.LastIndexOf(trigger) <> -1 Then 
      buffer = "" 
      InputRecords(0) = New KeyEventStruct 
      InputRecords = generateInputRecord(input & Convert.ToChar(13)) 
      WriteConsoleInput(STD_INPUT_HANDLE, InputRecords, InputRecords.Count(), New Integer) 
     End If 
    End While 
    Console.Write(stdOut.ReadToEnd()) 
End Sub 

Function generateInputRecord(ByVal str As String) As KeyEventStruct() 
    Dim ret(str.Count() - 1) As KeyEventStruct 
    For i = 0 To str.Count - 1 Step 1 
     With ret(i) 
      .EventType = 1 
      .bKeyDown = True 
      .uChar.AsciiChar = Convert.ToInt32(str(i)) 
      .dwControlKeyState = 0 
      .wRepeatCount = 1 
      .wVirtualKeyCode = 0 
      .wVirtualScanCode = 0 
     End With 
    Next 
    Return ret 
End Function 

它使用以下模塊:

Imports System.Runtime.InteropServices 

Module ConsoleUtils 

    <Flags()> Public Enum ControlKeyState As Integer 
     RightAltPressed = &H1 
     LeftAltPressed = &H2 
     RightCtrlPressed = &H4 
     LeftCtrlPressed = &H8 
     ShiftPressed = &H10 
     NumLockOn = &H20 
     ScrollLockOn = &H40 
     CapsLockOn = &H80 
     EnhancedKey = &H100 
    End Enum 

    <StructLayout(LayoutKind.Explicit)> Public Structure CHAR_UNION 
     <FieldOffset(0)> Public UnicodeChar As Short 
     <FieldOffset(0)> Public AsciiChar As Byte 
    End Structure 

    <DllImport("kernel32", EntryPoint:="WriteConsoleInputA", CharSet:=CharSet.Auto, SetLastError:=True, ThrowOnUnmappablechar:=True)> _ 
     Public Function WriteConsoleInput(_ 
      ByVal hConsoleInput As IntPtr, _ 
      ByVal lpBuffer() As KeyEventStruct, _ 
      ByVal nLength As Integer, _ 
      ByRef lpNumberOfEventsWritten As Integer _ 
     ) As Boolean 
    End Function 

    <DllImport("KERNEL32.DLL", EntryPoint:="GetStdHandle", SetLastError:=False, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _ 
     Public Function GetStdHandle(_ 
      ByVal nStdHandle As Integer _ 
     ) As Integer 
    End Function 

    <StructLayout(LayoutKind.Sequential)> Public Structure KeyEventStruct 
     Public EventType As Short 
     <MarshalAs(UnmanagedType.Bool)> Public bKeyDown As Boolean 
     Public wRepeatCount As Short 
     Public wVirtualKeyCode As Short 
     Public wVirtualScanCode As Short 
     Public uChar As CHAR_UNION 
     Public dwControlKeyState As ControlKeyState 
    End Structure 

    Public ReadOnly STD_OUTPUT_HANDLE As IntPtr = New IntPtr(GetStdHandle(-11)) 
    Public ReadOnly STD_INPUT_HANDLE As IntPtr = New IntPtr(GetStdHandle(-10)) 
    Public ReadOnly STD_ERROR_HANDLE As IntPtr = New IntPtr(GetStdHandle(-12)) 

End Module 

有了這個功能,你可以啓動進程並等待行輸出的(即「密碼:」)。然後該函數將輸入提供的文本,然後返回。

我希望這有助於!

關注 sc911

0

WriteConsoleInput需要一個控制檯句柄,而不是一個進程句柄。你的問題是如何掌握這個控制檯句柄。

如果您的進程是一個控制檯應用程序,並且您在啓動子進程時未重定向任何內容,那麼該子進程將連接到您自己的進程的控制檯。在這種情況下,你可以到:

  1. 開始重定向子進程關閉
  2. 呼叫GetStdHandle(STD_INPUT_HANDLE)讓自己的控制檯手柄
  3. 通行證持有該控制檯手柄WriteConsoleInput

如果你有一個GUI應用程序,你可以使用AllocConsole爲自己指定一個控制檯。

編輯:我一開始沒有注意到,但這不是WriteConsoleInput的正確定義。它需要一個INPUT_RECORD的數組,而不是一個字符串。一旦我複製了the function prototype from pinvoke.net,我自己的runas.exe實驗就可以正常工作。

+0

我做了一個測試(見上面的變化),但它不起作用。你可以給我一個例子嗎? – sc911 2009-12-07 13:24:31

+0

聽起來它的行爲與runas.exe類似;我會一起使用它進行測試。 – 2009-12-07 13:41:07

+0

@ sc911,看我編輯的答案 - 你的WriteConsoleInput聲明是錯的 – 2009-12-07 14:33:50