Export and Import from HKLM and HKCU

Hi everybody,

I am using PSADT for about half a year now and almost every day, I get more excited about it. Packaging and software deploying is nothing new to me, before we started with intune, I managed about 500 clients with Matrix42/Empirum for about 5 years.

Now, I have a challenge, I have to update the “Forti-Client” (vpn-software / we use the free version) installed on about 600 clients and most of the users don’t know their vpn-password. Unfortunately, the update process of Forti-Client deletes all user settings and credentials, so I have to export the config (including username and password) before the installation and import it again afterwards. I know, in which 2 registry keys the information is stored, the problem is, one is in HKCU and one in HKLM. As we deploy our software via Intune, PSADT-installation runs under the System-account.

I am able to export the reg-keys with “Get-RegistryKey” as this function supports the “-SID” option
$LoggedOnuser = Get-LoggedOnUser

  • If ($LoggedOnuser.IsConsoleSession){*
  •    if (Test-Path -Path 'HKLM:\SOFTWARE\Fortinet\FortiClient\Sslvpn\Tunnels\VPN') {*
  •            Get-RegistryKey -Key 'HKCU\Software\Fortinet\FortiClient\Sslvpn\Tunnels\VPN' -SID $LoggedOnuser.SID -ContinueOnError $true >C:\temp\FC_HKCU.txt*
  •   		Get-RegistryKey -Key 'HKLM:\SOFTWARE\Fortinet\FortiClient\Sslvpn\Tunnels\VPN' -ContinueOnError $true >C:\temp\FC_HKLM.txt*

The exported files don’t have the syntax of regulary exported *.reg files.

Does anybody know, how to import these files again. I think “Set-RegistryKey” doesn’t do the trick (correct me when I am wrong!). I can’t use normal windows tools here as I need the “-SID” option to import it again under HKCU.

Maybe there is a different way to export and import registry keys from/in HKLM and HKCU…

Thanks in advance


why you use a text file to export/backup?
Just backup the Registry into the Registry.
Get-RegistryKey and Set-RegistryKey

Example for each USER HKCU set regsitry.

 [scriptblock]$HKCURegistrySettings = {
            Set-RegistryKey -Key "HKCU\Software\XXXXX" -Name "XXXXX" -Value "XXXX" -Type String -SID $UserProfile.SID -ContinueOnError $false
		    Set-RegistryKey -Key "HKCU\Software\XXXXX" -Name "XXXXX" -Value "X" -Type DWord -SID $UserProfile.SID -ContinueOnError $false
	    Invoke-HKCURegistrySettingsForAllUsers -RegistrySettings $HKCURegistrySettings

Happy XMas

1 Like

Hi Mirko,

first of all, happy new year to all who read this! :wink:

Thank you for your answer. I am not sure if I understand you right. My problem is, that I have to export the HKCU keys (including the 2 with username and password!) , install the software and the write the keys again back into HKCU.
In your example, always the same keys are set for all users. Unfortunately, this doesn’t work in my case, I have to write the exported values (including individual username and password) back into the HKCU hive.

Do you know how to do this?

Thank you and best regards

It seems you want to massage the HKCU of EACH user on the same computer.

The best way is to use ActiveSetup.
Create an exe or a PS script that runs without PSADT that does want you need on the current user.
Then use Set-ActiveSetup to make it run at login time for each user.

Hi annoying guy (nice name, by the way) :wink:

No, I’m not trying to distribute the HKCU registry keys to all users. The situation is: Every user has its own laptop with only his/her user profile on it (when a laptop goes to another user, we wipe it completely via MS Intune). When I update Forti-Client, the registry keys under HKCU are deleted (strange, no explanation why) and so, the user credentials are not saved anymore. This is the reason why I try to export the keys, update Forti-Client and restore them again.
On the other hand, it would not matter if the credentials are restored to the all users profile as we freshly install any laptop before it goes to another user

Usually, the update starts when the user is logged in, so I can use “Set-RegistryKey” mit the “_SID”-option in PSADT. The export into a file runs great, but is there a way to import that file again…?

Thanks and best regards

I think I understand your issue.

You have figured out how to backup the vpn-password for the current user.
But when an update occurs, the HKCU keys holding the vpn-password get wiped.
This looks like a bug in the Forti-Client update or a “Security Feature”.

I would not use PSADT to import 2 registry values. It’s overkill.

Why not use PSADT to create a Reg file that the user can import when needed?

This is exactly my problem…and I think Fortigate implemented this “feature” to push their customers to the payed version of Forti-Client. But I am not willing to pay for this as I don’t have that much benefit…

You don’t know our users…! :rofl: :rofl: :rofl: A reg-file that they can import by themselves…I see a lot of new support tickes coming up…!

I don’t use PSADK not only to set 2 reg-keys, I do the whole update with it. In fact, I package every(!) software, that is deployed via Intune with PSADK. As I said in the first post, I am not new to packaging and software deployment and PSADK is a really, really great and powerful tool…and I like it very much…!

I thought the update was installed by a Forti-Client process not PSADT.
So I now assume you do something like this in PSADT:

  • if exist, backup the vpn-password for the current user
  • if not already installed, Install Forti-Client
  • if not already installed, Install Forti-Client Update
  • if NOT exist AND was backed-up, restore the vpn-password for the current user

Did you end up using Mito’s “backup to the HKCU” idea?

Yes, I try to do it more less the way you described. I figured out, that exactly 3 regkeys are neccessary to backup and restore user credentials. My last test was successful. I will now repeat the test with my laptop and after that with 3 or 5 prodution laptops.

I didn’t try Mito’s idea…

Unfortunately my tests were only successful when I start <Deploy-Application.ps1> “manually” on the client. I tried an admin user or ans normal user starting with “.\PsExec64.exe -i -s powershell.exe” (to run it in system context). In these cases, everything works fine.
But as soon as I make an intunewin-package out of it, the registry keys from HKCU were somehow not found and the text file, where I write the content into, stays empty.

Here ist my code (I write everything to text files, just to for testing):
echo $LoggedOnuser.IsConsoleSession >C:_INSTALLS\LoggedOnUser-ConsoleSession.txt
echo $LoggedOnuser.SID >C:_INSTALLS\LoggedOnUser-SID.txt
Get-RegistryKey -Key ‘HKCU:Software\Fortinet\FortiClient\Sslvpn\Tunnels\RZIMV_VPN’ -SID $LoggedOnuser.SID -ContinueOnError $true >C:_INSTALLS\FC_HKCU_RZIMV-VPN.reg
Get-RegistryKey -Key ‘HKCU:Software\Fortinet\FortiClient\Sslvpn\Tunnels\RZIMV_SSL’ -SID $LoggedOnuser.SID -ContinueOnError $true >C:_INSTALLS\FC_HKCU_RZIMV-SSL.reg
Get-RegistryKey -Key ‘HKLM:Software\Fortinet\FortiClient\Sslvpn\Tunnels\RZIMV_VPN’ -SID $LoggedOnuser.SID -ContinueOnError $true >C:_INSTALLS\FC_HKLM_RZIMV-VPN.reg
Get-RegistryKey -Key ‘HKLM:Software\Fortinet\FortiClient\Sslvpn\Tunnels\RZIMV_SSL’ -SID $LoggedOnuser.SID -ContinueOnError $true >C:_INSTALLS\FC_HKLM_RZIMV-SSL.reg

The first 2 lines are red correctly, the results of line 3 and 4 (HKCU) are empty and line 5 and 6 (HKLM) are written correctly again.

As I said before, this ONLY happens when the software ist deployed via intunewin-package…starting deploy-application.ps1 manually works correct…!

Any ideas what goes wrong here…?

Thanks in advance

in this case, HKCU: is the user hive of what ever Intune is running as.
Not a logged-in user.
Also, what if there is no logged-in user when PSADT runs?

PSADT has a Invoke-HKCURegistrySettingsForAllUsers function that will run code on all user hives, one at a time. MiTo mentioned it above.

I have massaged his code to try to give you an idea of what to do.
Please Note that I have not tested this code. I expect it to fail on users that have nothing to backup.

CAVEAT: Since you have not given us a REG file, I’m assuming RZIMV_VPN and RZIMV_SSL are value names and are of type String in the registry

#Backup the user's stuff to his own HKCU in HKCU\Software\Fortinet\FortiClient\Sslvpn\BKTunnels
[scriptblock]$HKCURegistrySettings = {
	#CAVEAT: for Get-RegistryKey, -Value is the value's name
    $UserVPN = Get-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\Tunnels" -Value "RZIMV_VPN" -SID $UserProfile.SID -ContinueOnError $false
    $UserSSL = Get-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\Tunnels" -Value "RZIMV_SSL" -SID $UserProfile.SID -ContinueOnError $false

	#CAVEAT: for Set-RegistryKey, -Name is the value's name
    Set-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\BKTunnels" -Name "RZIMV_VPN" -Value $UserVPN -Type String -SID $UserProfile.SID -ContinueOnError $false
    Set-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\BKTunnels" -Name "RZIMV_VPN" -Value $UserVPN -Type String -SID $UserProfile.SID -ContinueOnError $false
#Use this function to loop through ALL user hives (aka All HKCU hive on the computer)
Invoke-HKCURegistrySettingsForAllUsers -RegistrySettings $HKCURegistrySettings

#Here you do you install/ upgrade of Forti-Client as you already have

#Restore the user's stuff from his own HKCU in HKCU\Software\Fortinet\FortiClient\Sslvpn\BKTunnels
[scriptblock]$HKCURegistrySettings = {
	#CAVEAT: for Get-RegistryKey, -Value is the value's name
    $UserVPN = Get-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\BKTunnels" -Value "RZIMV_VPN" -SID $UserProfile.SID -ContinueOnError $false
    $UserSSL = Get-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\BKTunnels" -Value "RZIMV_SSL" -SID $UserProfile.SID -ContinueOnError $false

	#CAVEAT: for Set-RegistryKey, -Name is the value's name
    Set-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\Tunnels\RZIMV_VPN" -Name "RZIMV_VPN" -Value $UserVPN -Type String -SID $UserProfile.SID -ContinueOnError $false
    Set-RegistryKey -Key "HKCU\Software\Fortinet\FortiClient\Sslvpn\Tunnels\RZIMV_SSL" -Name "RZIMV_VPN" -Value $UserVPN -Type String -SID $UserProfile.SID -ContinueOnError $false
#Use this function to loop through ALL user hives (aka All HKCU hive on the computer)
Invoke-HKCURegistrySettingsForAllUsers -RegistrySettings $HKCURegistrySettings```

First of all, thank you for your patience and your code…! :wink:

At the moment, I don’t consider the case when no user is logged in.

I started to try Mitos code, but then I noticed, that the values from HKCU are not read (as I described in my last post). Oddly enough, when I write the values from
$LoggedOnuser = Get-LoggedOnUser
$LoggedOnuserSID = $LoggedOnuser.SID
to text-files on the local hard disk, the content is correct.

I tried your code, but it also failed when reading the values from HKCU (Line 4 of your code, starting with "$UserVPN = Get-RegistryKey -Key “HKCU\Software…”

I know that Intune executes a 32-bit Powershell (also on a 64-bit OS), could that be the reason…?



In Deploy-Application.ps1 use extra code to relaunch as 64bit but the 32bit window needs to stick around until the 64bit child is done.

Finally, I managed it to get the script running. The problem was the 32/64 bit mode. I found some code that starts the script itself in 64 bit Powershell (just put it to the beginning of the script). I will use this “function” for all future PSADT-scripts.

I had some trouble reading the registry values from HKCU, so I read them from HCU (no problem as we always have only 1 user profile per laptop). The rest runs like Mirko and That-Annoying-Guy suggested.

If it is desired, I can post the whole “Deploy-Application.ps1” here…

Thank you for your help…!

I have a ReSpawn-Deploy-Application.ps1-in-64bit block of code added to my Deploy-Application.ps1 for years now. It think it should be boiler-plate stuff. Especially with Intune being only 32-bit :crazy_face: