An In-Depth Review of the Silent Install/Upgrade Process for NetExtender
![Michael_McCool](https://us.v-cdn.net/6031761/uploads/defaultavatar/n29VP08P5C5ND.jpg)
From what I was able to research on the Internet and through various forum posts and Sonicwall KBs, the general consensus is that NetExtender cannot be managed through a RMM (Remote Monitoring & Management), but instead must be manually upgraded or uninstalled, reboot the device, then reinstall with the latest version. After extensive testing, I've determined that this assumption is false. NetExtender can be managed via a RMM and updated silently. It just needs a bit more work.
My testing has shown that there are several issues with the NetExtender installers as currently packaged by Sonicwall, and these issues are what prevents the silent update process from working as expected. I have tickets opened with Sonicwall support and have talked with management about getting these installer issues fixed to make things easier in the future. The main take-a-way is that these issues can be worked around. The update process would be much easier with functional installers, but the workarounds aren't difficult, just annoying.
First, the issues. For the EXE version of NetExtender, NXSetupU, when installing the EXE normally, the installer first performs a silent uninstall of the existing version, then installs the update. When using the silent install switch "/S", the uninstall of the existing version never happens. Instead, the installer goes straight attempting an install over the top of the existing installation. Any files in use are skipped, and you are left with a mismatched version with both old and new files as part of the installation. The version listed in the programs list is updated to the latest version number although it's still technically at the old version. The solution to this is to have the install script silently uninstall the existing version first before performing a silent install of the new.
For the MSI version, it mostly works as is. Simply install the MSI as normal with the silent install switches and everything gets updated at the next reboot. Done. There is however still a small bug in the installer. It is unlikely that you will run into this, but it should be known. The MSI version includes a driver to support pre-logon VPN connections. If you perform an uninstall of the MSI, then install the MSI without performing a reboot in between, the driver installation part will throw an error and pop-up a dialog box despite the MSI being deployed silently. So, if you push this via a RMM that runs the script as system, the install will hang as the pop-up will not be displayed to anyone. Additionally, if you are able to interact with the dialog and click OK at the failure prompt, the MSI then exits and reports as successfully installed (exit code of 0) despite the driver failing to install properly. While this is a rather large failure of the MSI installer process, you are unlikely to encounter it under normal circumstances.
With that out of the way, I'll go through the outline of my update/deployment script with powershell code snippets here and there to assist. I would post the script here, but it is a 600 line script and far too long to post in its entirety.
Step 1 - Determine if the current install is EXE or MSI. I have a function that will build a list of the installed programs by parsing the uninstall registry keys. It's based of the code from a 2017 MCP Magazine post that was tweaked a bit to run better from a RMM. I simply look at the uninstall string for NetExtender and see if it is uninst.exe (EXE) or msiexec.exe (MSI) and go from there.
Step 2 - Get the current version of NetExtender and if an update is required. Currently, there is not a way to scrape the NetExtender download page to programmatically check for the latest version. The download page is protected by Cloudflare and the download page is not listed in the robots.txt file, so access is denied via powershell. At the moment, the current version need to be set manually. Here is a code snippet that builds the various download URLs based on the current version of the software.
$CurrentVersion="10.2.339" function Get-NetExtenderLinks { param ( [Parameter(Mandatory=$true, Position=0)] [version] $CurrentVersion ) if ($currentVersion){ # build the list of download links based on the latest version number. $DownloadLinks=[System.Collections.ArrayList]@() [void]$DownloadLinks.add("https://software.sonicwall.com/NetExtender/NetExtender-x64-$($currentVersion.Major).$($CurrentVersion.Minor).$($CurrentVersion.Build).msi") [void]$DownloadLinks.add("https://software.sonicwall.com/NetExtender/NetExtender-x86-$($currentVersion.Major).$($CurrentVersion.Minor).$($CurrentVersion.Build).msi") [void]$DownloadLinks.add("https://software.sonicwall.com/NetExtender/NXSetupU-x64-$($currentVersion.Major).$($CurrentVersion.Minor).$($CurrentVersion.Build).exe") [void]$DownloadLinks.add("https://software.sonicwall.com/NetExtender/NXSetupU-x86-$($currentVersion.Major).$($CurrentVersion.Minor).$($CurrentVersion.Build).exe") $DownloadLinks } } $DownloadLinks=Get-NetExtenderLinks $CurrentVersion
Step 3 - If the installed version is older than the current version, download the EXE or MSI that matches the bitness of the system.
Step 4 - Remove the previous version if EXE, then install the latest version silently (EXE or MSI). If no version is installed currently, the script deploys the MSI.
MSI - This sets it to use the pre-logon VPN driver and to install as a machine-wide installer.
msiexec.exe /i NetExtender-x64-10.2.339.msi /quiet /qn /norestart netlogon=true ALLUSERS=2
EXE - Uninstalls the existing version silently, then install the latest version silently. This mimics the process that occurs when executing the installer via the GUI interface.
uninst.exe /S NXSetupU-x64-10.2.339.EXE /S
The device will most likely require a reboot to complete the installation, but that is the extent of it.
Answers
Brilliant investigative work and thorough testing. Have you considered posting the script on GitHub?
Sadly, none of the results of the investigation are surprising. It's likely none of the installer code has been updated since the days of Windows Vista.
I have thought about posting this on GitHub. It will take a bit of work to make this a more generic script as I've written this with our RMM (Datto RMM) in mind. We have deployed the script as it stands now to one of our clients, but not everything worked quite as expected. There were some issues with the upgrade process from 8.x to 10.x of NetExtender.
My scripts nowadays have a lot of environmental testing code in the mix so everything gets evaluated along the way. The above outline is the bare minimum steps to make things work, but the script itself has uninstall and cleanup options in there as well as I actively test for the mismatched versions that occur if you did try and perform a silent install of the EXE and it deployed over the top of the existing install. There are a few scenarios that I still don't have quite right like upgrading a 8.x version to 10.x, so it needs a bit more work before I am ready to release it. All told, it's around 600 lines of code currently, and will likely add a few more lines when I get the 8.x to 10.x upgrade process fleshed out. Once I get that done, I will see about posting it to GitHub and sharing a link here.
"My scripts nowadays have a lot of environmental testing code in the mix so everything gets evaluated along the way."
As is required. Sloppy coding is why issues like this exist in the first place.
If I were to pursue this noble goal I'd skip 8.x versions and focus on 9.x and newer.