Always On VPN User tunnel in Add Remove Programs with PowerShell in Windows 11

I have been struggling with deploying Always On VPN to Windows 11. But there is some bugs in the implementation of CSP VPNv2 on Windows 11. Microsoft has released some fixes, but there are still problems. I decided to T-shoot and see if I could get my script to work even on Windows 11. And it seems like I succeeded. I have now also updated the User tunnel script.

I discovered that the enumeration of vpn connections when using CSP over WMI failed on windows 11. It returned general error.

$deleteInstances = $session.EnumerateInstances($namespaceName, $className)}
      	foreach ($deleteInstance in $deleteInstances){
      	$InstanceId = $deleteInstance.InstanceID}

To solve this I added powershell command remove-vpnconnection in case of an error during enumeration:

try {$deleteInstances = $session.EnumerateInstances($namespaceName, $className)}
catch [Exception] {write-host "No existing VPN Tunnel was found."}
if (-not (test-path variable:deleteinstances)){
    Foreach ($deleteInstance in $deleteInstances){
      	$InstanceId = $deleteInstance.InstanceID}
if ($deleteInstance = get-vpnconnection -alluserconnection -name "$profilename" -ErrorAction SilentlyContinue){
   try {$deleteInstance| remove-vpnconnection -force}
   catch [Exception] {write-host "Unable to remove existing VPN Tunnel $($profilename) with powershell: $_"}

Next thing I discovered was that if you have Domain Name Resolution Policy with dnsservers blank, it will result in General Error:


But if you add dnsservers it works just fine:


So now the script also works for creating a user tunnel.

Always On VPN in Add Remove Programs with PowerShell

I have now updated the device tunnel script so that it works with windows 11. You can find it on my Github.


1.0.2202.1 - Initial Version

1.0.2207.1 - Solved a problem with uninstall device tunnel from Add Remove Programs

1.0.2207.2 - Solved Windows 11 problems with CSP over WMI. No blank DNS server list allowed  


The script has three modes: Install, Reinstall and Uninstall. The default is Install, it will install the VPN if missing and update if an old version. If run on a computer with same version it will exit without actions. But what if the VPN has some error and you need to manually update the config. Then it can be reinstalled with the Reinstall switch. And if the VPN connection needs to be removed, just use the uninstall option.

#region ---------------------------------------------------[Script Parameters]-------------------------------------

    [Parameter(HelpMessage = 'Enter Install, ReInstall or UnInstall.')]    
    [validateset("Install", "ReInstall", "UnInstall")][string]$InstallType = "Install"

Modifiable Variables

I have some modifiable variables to customize the deployment and VPN configuration. The VPN connection itself is formed in the default XML way. Had some ideas on using variables, but Always On VPN is often formed in that way, so this is probably the easiest way of customizing. Make sure you go through this part and customize it for your environment.

#region ---------------------------------------------------[Modifiable Parameters and defaults]--------------------
# Customizations
$Company = "Coligo"    #Used in VPN ProfileName and registry keys

#Version info
[version]$ConfigVersion   = "1.0.2202.1" #Increment when changing config, stored in registry to check if new config is needed. syntax: 1.1.YYMM.Version (1.1.2001.1)
$AddRemoveProgramEnabled  = $True        #$true register an App in Add Remove Programs for version and uninstall, $false skip registration in Add Remove Programs
$MinWinBuild              = 17763        #17763 will require Windows 1809 to execute

#Log settings
$Global:GuiLogEnabled   = $False       #$true for test of script in manual execution

Add Remove Programs

As mentioned before the script will also register in Add Remove Programs with it´s name and version. This is quite nice, then it can be inventoried as any other application installed. This info is also used if the script is updated with a new version or if it is running in reinstall mode. The most tricky part with this was the uninstall part. Finally succeeded so it can also be uninstalled from Add Remove Programs.


I have built my own logging function that will write to GUI, Event Viewer or File. Whatever the customer prefer. I use the same function it in many of my scripts and it works really good on all targets so far. The GUI logging is mostly used when testing the script, if disabled it will run silent.

INI file update

The script also searches for the INI file (rasphone.pbk) that the VPN connection created. This INI file can sometimes end up in other location than default. Thereby I use some regkeys to try find the path so I can edit the correct file. I have added the settings that sometimes need optimization for Always On VPN.

The Script

I have published the script on my Github. Feel free to use and I just love feedback

About The Author

Mr T-Bone

Torbjörn Tbone Granheden is a Solution Architect for Modern Workplace at Coligo AB. Most Valuable Professional (MVP) on Enterprise Mobility. Certified in most Microsoft technologies and over 23 years as Microsoft Certified Trainer (MCT)

You may also like...