Feeding input to an interactive command line appli

2020-02-05 07:07发布

I'd like to feed inputs to a command line interface for Cisco AnyConnect vpncli.exe (v2.3) to automate its (re)connection. It does not take username nor password as command line arguments, but reads those interactively from the user via the command line interface.

Problem is that piping input to vpncli.exe doesn't seem to work for the password. It works for everything except the password. So doing things like this doesn't work:

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

The application just gets stuck at where it asks for the password.


Below is an example of normal (working) execution where the user enters the parameters:

Example vpncli.exe run

Notice how the password characters get transformed to *.


Using tools like AutoIt or AutoHotKey to send the inputs to a command prompt window works, but is clumsy and fragile (does not work if the tool can't get to the command prompt window for some reason).


Is there any way to send inputs to such interactive CLI application using PowerShell?

(Or using any other scripting language or some other means?)

2条回答
叼着烟拽天下
2楼-- · 2020-02-05 07:45

There are at least two ways to read input in a Windows console application.

  • ReadConsole: reads input either from keyboard or redirection (documentation).
  • ReadConsoleInput: reads only raw keystrokes (documentation).

The vpncli.exe application uses ReadConsoleInput in order to read the password, that's way redirecting the password does not work. You can, though, use WriteConsoleInput. I have a small Python script that does exactly that:

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()
查看更多
Rolldiameter
3楼-- · 2020-02-05 07:55

you need to create an usual text file like

connect myvpnhost
myloginname
mypassword

save it as myfile.dat (for example) and then call

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

查看更多
登录 后发表回答