Skip to content

Instantly share code, notes, and snippets.

@jhorsman
Created January 6, 2015 10:11
Show Gist options
  • Save jhorsman/88321511ce4f416c0605 to your computer and use it in GitHub Desktop.
Save jhorsman/88321511ce4f416c0605 to your computer and use it in GitHub Desktop.
PowerShell to automate VPN connection with Cisco AnyConnect Secure Mobility Client
# Usage: & '.\Cisco_Anyconnect.ps1' [-Server <server name or ip>] [-Group <group>] [-User <user>] [-Password <password>]
#Source www.cze.cz
#This script is tested with "Cisco AnyConnect Secure Mobility Client version 3.1.00495"
# Usage: & '.\Cisco_Anyconnect.ps1' [-Server <server name or ip>] [-Group <group>] [-User <user>] [-Password <password>]
#Please change following variables
#IP address or host name of cisco vpn, Username, Group and Password as parameters
param (
[string]$Server = $( Read-Host "Input server, please" ),
[string]$Group = $( Read-Host "Input group, please" ),
[string]$User = $( Read-Host "Input username, please" ),
[string]$Password = $( Read-Host -assecurestring "Input password, please" )
)
#Please check if file exists on following paths
[string]$vpncliAbsolutePath = 'C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe'
[string]$vpnuiAbsolutePath = 'C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe'
#****************************************************************************
#**** Please do not modify code below unless you know what you are doing ****
#****************************************************************************
Add-Type -AssemblyName System.Windows.Forms -ErrorAction Stop
#Set foreground window function
#This function is called in VPNConnect
Add-Type @'
using System;
using System.Runtime.InteropServices;
public class Win {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
'@ -ErrorAction Stop
#quickly start VPN
#This function is called later in the code
Function VPNConnect()
{
Start-Process -WindowStyle Minimized -FilePath $vpncliAbsolutePath -ArgumentList "connect $Server"
$counter = 0; $h = 0;
while($counter++ -lt 1000 -and $h -eq 0)
{
sleep -m 10
$h = (Get-Process vpncli).MainWindowHandle
}
#if it takes more than 10 seconds then display message
if($h -eq 0){echo "Could not start VPNUI it takes too long."}
else{[void] [Win]::SetForegroundWindow($h)}
}
#Terminate all vpnui processes.
Get-Process | ForEach-Object {if($_.ProcessName.ToLower() -eq "vpnui")
{$Id = $_.Id; Stop-Process $Id; echo "Process vpnui with id: $Id was stopped"}}
#Terminate all vpncli processes.
Get-Process | ForEach-Object {if($_.ProcessName.ToLower() -eq "vpncli")
{$Id = $_.Id; Stop-Process $Id; echo "Process vpncli with id: $Id was stopped"}}
#Disconnect from VPN
echo "Trying to terminate remaining vpn connections"
Start-Process -WindowStyle Minimized -FilePath $vpncliAbsolutePath -ArgumentList 'disconnect' -wait
#Connect to VPN
echo "Connecting to VPN address '$Server' as user '$User'."
VPNConnect
#Write login and password
[System.Windows.Forms.SendKeys]::SendWait("$Group{Enter}")
[System.Windows.Forms.SendKeys]::SendWait("$User{Enter}")
[System.Windows.Forms.SendKeys]::SendWait("$Password{Enter}")
#Start vpnui
Start-Process -WindowStyle Minimized -FilePath $vpnuiAbsolutePath
#Wait for keydown
#echo "Press any key to continue ..."
#try{$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")}catch{}
@jakawell
Copy link

Love this script. Just sharing something that I did to automate import of a one-time password (a la, Google Authenticator, etc.). First, I installed this great open-source Python TOTP/HOTP CLI: https://github.com/JeNeSuisPasDave/authenticator
Once you setup your OTP account in that, you can get the latest OTP in your Powershell script like this:

$AuthResult = "foo" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

Just update the authenticator password (foo, above) and update the regex to match the number of digits in your OTP (I used a typical 6 digit code above).

@UsamaWaheed
Copy link

$AuthResult = "foo" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

I tried that but I get an error saying, authenticator command is unknown. If I open CLI and type authenticator generate it works perfectly fine.

authenticator : The term 'authenticator' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the 
spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\testuser\Desktop\Mode Selector.ps1:218 char:25
+ $AuthResult = "abcde" | authenticator generate --refresh "once" | Out ...
+                         ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (authenticator:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
 
False

The code that I added is exactly what u did

$AuthResult = "abcde" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

@Shikha1912
Copy link

Is there anyway, if we can hide the command line window rather than minimize?

@dlwiii
Copy link

dlwiii commented Mar 27, 2021

This works great from the command line. But I added this as a windows scheduled task which runs "powershell" and it does not seem to work. Any idea why this would not work as a scheduled task?

@FPl47h
Copy link

FPl47h commented Jul 20, 2021

I had the same problem. I was able to fix it by starting the task as admin.
In the new Jabber version 4.10.01075 I suddenly had problems entering the password. Adjusted line 71 without the wait-operator [System.Windows.Forms.SendKeys] :: Send("$ User {Enter}")

@vensondiana
Copy link

Hi,

This was nice and working. Also, we have a banner to accept on dual authentication. Is there a way on how to auto-accept also the banner?

@uluvdj
Copy link

uluvdj commented Sep 21, 2021

Hi,

This was nice and working. Also, we have a banner to accept on dual authentication. Is there a way on how to auto-accept also the banner?

Hi, You may have figured this out by now but, what i did to get this to work was after the section that sends the keys to application, i added:

Sleep 20
[System.Windows.Forms.SendKeys]::SendWait(‘y~’)

@ommcodes
Copy link

Love this script. Just sharing something that I did to automate import of a one-time password (a la, Google Authenticator, etc.). First, I installed this great open-source Python TOTP/HOTP CLI: https://github.com/JeNeSuisPasDave/authenticator Once you setup your OTP account in that, you can get the latest OTP in your Powershell script like this:

$AuthResult = "foo" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

Just update the authenticator password (foo, above) and update the regex to match the number of digits in your OTP (I used a typical 6 digit code above).

Hi, Did you achieved getting TOPT from Microsoft Authenticator based on the script in the link you provided ?

@mattcargile
Copy link

Ever try to automate a M365 login prompt with MFA? We recently switched to it and I really miss my script. I've considered some robo-hack but haven't gotten to it yet. It would be cool if one could hook in with a powershell module like MSAL.PS.

@brianhauge
Copy link

@mattcargile

Ever try to automate a M365 login prompt with MFA? We recently switched to it and I really miss my script. I've considered some robo-hack but haven't gotten to it yet. It would be cool if one could hook in with a powershell module like MSAL.PS.

I've added and extra parameters to by able to wait for a 2FA. Add the following after inputs of username and password:

if($Sms -eq 'yes') {
		do { 
            sleep -s 2
        } while (
            -not ( $Host.UI.RawUI.KeyAvailable -and ($Host.UI.RawUI.ReadKey("IncludeKeyUp,NoEcho").VirtualKeyCode -eq 13 ) ) 
       )
}

@brianhauge
Copy link

brianhauge commented Oct 3, 2023

I have a problem. After the latest Windows 11 Update, It's not possible to send @ as part of the parameters any longer, when using [System.Windows.Forms.SendKeys]::SendWait. Anyone knows a way around this?

Found out it is because I'm using a danish keyboard. Switching to en-US:

Set-WinUserLanguageList -Force 'en-US'
[System.Windows.Forms.SendKeys]::SendWait("$user{Enter}")
Set-WinUserLanguageList -Force 'da-DK'

@mattcargile
Copy link

Thanks @brianhauge . I might look into that. It still seems like I need AutoIT or AutohotKey to really maximize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment