Skip to content
Luca Dell'Oca Principal Cloud Architect @Veeam
Virtual To The Core Virtual To The Core

Virtualization blog, the italian way.

  • Media
  • About me
Virtual To The Core
Virtual To The Core

Virtualization blog, the italian way.

Pass keystrokes to a pfSense virtual machine to install it automatically

Luca Dell'Oca, March 28, 2024March 27, 2024
In my previous post I showed how to install automaticaly a virtual machine with pfSense. The automation I reached was around 90%, as I didn’t know how to automate the installation of the software. Thanks to Michael Zenzmaier who suggested me the Set-VMKeystrokes function created by William Lam I was able to also automate the installation. This solution is also a great example to automate every situation where we need to send keystrokes to a vSphere VM.
The full script is posted below, while I will comment the most relevant parts. I also created a video to show the final result.
In the first section, I import the VMKeystrokes module, and I also load a “Sleep-Progress” function.
Function Sleep-Progress($TotalSeconds) {
    $Counter = 0;
    for ($i = 0; $i -lt $TotalSeconds; $i++) {
        $Progress = [math]::Round(100 - (($TotalSeconds - $Counter) / $TotalSeconds * 100));
        Write-Progress -Activity "Waiting..." -Status "$Progress% Complete:" -SecondsRemaining ($TotalSeconds - $Counter) -PercentComplete $Progress;
        Start-Sleep 1
        $Counter++;
    }    
}

This is very important for the script, as we will never have any feedback or return code from the virtual machine. For this reason, each keystroke has to be properly separated from the previous one, to give the operation to complete. In my script you will see many waiting times, which may seem excessive, but they are needed to avoid having some clicks happening too soon, like for example while the virtual machine at some point is still rebooting. You will need to test the script in your own environment to find out the right timings for your situation.

The rest of the script is a long sequence of commands like this one:

Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

this one for example is a Return, while this one:

Set-VMKeystrokes -VMName $PfSenseVM -SpecialKeyInput "TAB" ;Start-Sleep -Milliseconds $key_wait_time

hits the TAB key, or also this one:

Set-VMKeystrokes -VMName $PfSenseVM -StringInput "vmx3" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

that writes the text “vmx3” in the console and then hit returns. Here is the full video, and below you can copy the script.

# Install or Import needed modules

# Install VMware PowerCLI if you don't have it already
# Install-Module -Name VMware.PowerCLI

Invoke-WebRequest -Uri https://raw.githubusercontent.com/lamw/vmware-scripts/master/powershell/VMKeystrokes.ps1 -OutFile $env:TEMP\VMKeystrokes.ps1
Import-Module $env:TEMP\VMKeystrokes.ps1

Function Sleep-Progress($TotalSeconds) {
    $Counter = 0;
    for ($i = 0; $i -lt $TotalSeconds; $i++) {
        $Progress = [math]::Round(100 - (($TotalSeconds - $Counter) / $TotalSeconds * 100));
        Write-Progress -Activity "Waiting..." -Status "$Progress% Complete:" -SecondsRemaining ($TotalSeconds - $Counter) -PercentComplete $Progress;
        Start-Sleep 1
        $Counter++;
    }    
}
 
#Variables
$vcenter = "vcenter.vsphere.local"
$username = "administrator@vsphere.local"
$password = "VeryComplicatedPassword"
$key_wait_time="1000"
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
Connect-VIServer $vcenter -User $username -Password $password 

$PfSenseVM=Get-VM pfSense

$lan_IP    ="172.27.217.254"
$wan_IP    ="203.0.113.151"
$gtw_IP    ="203.0.113.1"

##Send Commands
Start-Sleep -Seconds 10

#AcceptEulas
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Install
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Auto (ZFS)
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Install
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Stripe
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Use Disk
Set-VMKeystrokes -VMName $PfSenseVM -StringInput " " ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Last Chance!
Set-VMKeystrokes -VMName $PfSenseVM -SpecialKeyInput "TAB" ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#WORKING
Write-Host "Wait for Installation" ;Sleep-Progress 60

#No Change
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Reboot
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Write-Host "Wait for Reboot and startup"
Sleep-Progress 60

##Configure network interfaces
$key_wait_time="2"
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "vmx3" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "vmx1" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "y" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

#Sometimes the configurator gets stuck here for a while, let's wait enough time
Sleep-Progress  240

#Configure LAN Interface
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "2" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "2" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput $lan_IP -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "24" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Sleep-Progress  $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Sleep-Progress  $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Sleep-Progress 10

#Configure WAN Interface
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "2" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "1" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput $wan_IP -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "24" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput $gtw_IP -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "y" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Sleep-Progress  $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "n" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -ReturnCarriage:$true ;Sleep-Progress  $key_wait_time

#Install Sudo
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "8" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "pkg install pfSense-pkg-sudo" -ReturnCarriage:$true ;Start-Sleep 5
Set-VMKeystrokes -VMName $PfSenseVM -StringInput "y" -ReturnCarriage:$true ;Start-Sleep -Milliseconds $key_wait_time

##DONE

 

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to email a link to a friend (Opens in new window) Email
  • Click to share on Tumblr (Opens in new window) Tumblr
  • Click to share on Pinterest (Opens in new window) Pinterest
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to share on WhatsApp (Opens in new window) WhatsApp
  • Click to share on Pocket (Opens in new window) Pocket
Tech automationkeystrokespfsenseVMvsphere

Post navigation

Previous post
Next post

Search

Sponsors

Latest Posts

  • Migrate WSL (Windows Subsystem for Linux) to a new computer
  • Pass keystrokes to a pfSense virtual machine to install it automatically
  • Automatically deploy pfSense with Terraform and Ansible
  • My Automated Lab project: #6 Create a S3 Bucket with Terraform
  • My Automated Lab project: #5 Deploy a Linux vSphere VM with Terraform and custom disks
©2025 Virtual To The Core | WordPress Theme by SuperbThemes
We use cookies to ensure that we give you the best experience on our website, and to collect anonymous data regarding navigations stats using 3rd party plugins; they all adhere to the EU Privacy Laws. If you continue to use this site we will assume that you are ok with it.OkNoPrivacy Policy