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{}
@hubertsvk
Copy link

hi,
i have problem with this script ... i have three profiles and when i can connect to specific profile

PS C:\Users\XXX\Documents> .\Cisco_Anyconnect.ps1 'a.b.com' '' 'a.b'
Process vpnui with id: 18412 was stopped
Process vpncli with id: 7840 was stopped
Trying to terminate remaining vpn connections
Connecting to VPN address 'a.b.com' as user 'a.b'.

and script stopt and then shows me anyconnect dialog with button connect ....

...and the second "problem" is how store username and password in secure way .... i try with this, but without success
$Path = "$home\Desktop\multipass.xml"
[PSCustomObject]@{
User3 = Get-Credential -Message domain\a.b
} | Export-Clixml -Path $Path

$multipass = Import-Clixml -Path $Path

can you help me?

@RamanaReddyV
Copy link

Hi

check the below link may be useful. if any problems while setup please let me know.
https://www.codeproject.com/Tips/1250398/Login-VPN-through-Cisco-AnyConnect-Secure-Mobility

@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