Подача ввода в приложение интерактивной командной строки

Я хотел бы подавать входные данные в интерфейс командной строки для Cisco AnyConnect vpncli.exe (v2.3) для автоматизации его (повторного) соединения. Он не принимает имя пользователя и пароль как аргументы командной строки, но читает их в интерактивном режиме от пользователя через интерфейс командной строки.

Проблема заключается в том, что вход для подключения к vpncli.exe не работает для пароля. Он работает для всего, кроме пароля. Так что делать такие вещи не получается:

vpncli.exe < input.txt
type input.txt | vpncli.exe

Приложение просто застревает там, где оно запрашивает пароль.


Ниже приведен пример нормального (рабочего) выполнения, когда пользователь вводит параметры:

Example vpncli.exe run

Обратите внимание, как символы пароля преобразуются в *.


Использование таких инструментов, как AutoIt или AutoHotKey для отправки входов в окно командной строки, работает, но неудобно и хрупко (не работает, если инструмент по какой-то причине не может попасть в окно командной строки).


Есть ли способ отправить данные для такого интерактивного приложения CLI с помощью PowerShell?

(Или используя любой другой язык сценариев или какие-то другие средства?)

Ответы

Ответ 1

Существует как минимум два способа чтения ввода в консольном приложении Windows.

  • ReadConsole: считывает ввод с клавиатуры или перенаправления (документация).
  • ReadConsoleInput: читаются только сырые нажатия клавиш (документация).

Приложение vpncli.exe использует ReadConsoleInput, чтобы прочитать пароль, поэтому перенаправление пароля не работает. Вы можете использовать WriteConsoleInput. У меня есть небольшой Python script, который делает именно это:

import subprocess
import win32console

ANYCONNECT_BIN = 'c:\\Program Files\\Cisco\\Cisco AnyConnect Secure Mobility Client\\vpncli.exe'

def write_console_input(text):
  stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)
  ir = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
  ir.KeyDown = True
  for ch in text:
    ir.Char = unicode(ch)
    stdin.WriteConsoleInput([ir])

def main():
  proc = subprocess.Popen([ANYCONNECT_BIN,'connect','VPN'],stdin=subprocess.PIPE)
  proc.stdin.write('%s\n%s\n' % ('GROUP', 'USERNAME'))
  write_console_input('%s\n' % 'PASSWORD')
  ret = proc.wait()
  print ret

if __name__ == '__main__':
  main()

Ответ 2

вам нужно создать обычный текстовый файл, например

connect myvpnhost
myloginname
мойпароль

сохраните его как myfile.dat(например), а затем вызовите

"% ProgramFiles%\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe" -s < myfile.dat