1

I am creating a script to insert a registry key PreventInstallationFromMsi in HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\Teams. I am doing this because my environment doesn’t want teams to install on Admin accounts. However, as you can see this is in HKCU, to find the user profile registry patch, it is in NTUSER.DAT registry file. So I want to load the NTUSER.DAT file in profiles with -admin in the profile name. Here is the first script:

#Create Custom HKU Powershell Drive

New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS

# Define the path to the Users directory

$usersPath = "C:\Users"

 

# Initialize an empty list to store admin folders

$AdminFolders = @()

 

# Get all directories in the Users folder

$directories = Get-ChildItem -Path $usersPath -Directory

 

# Iterate through each directory and check if it contains "-admin"

foreach ($dir in $directories) {

    if ($dir.Name -match "-admin") {

        $AdminFolders += $dir.FullName

    }

}

 

# Load the NTUSER.DAT file for each admin folder, edit the registry, and then unload it

foreach ($adminFolder in $AdminFolders) {

    $ntUserPath = Join-Path -Path $adminFolder -ChildPath "NTUSER.DAT"

   

    if (Test-Path -Path $ntUserPath) {

        # Define a temporary registry hive name

        $hiveName = "TempHive"

       

        try {

            # Load the NTUSER.DAT file into the registry

            reg load "HKU\$hiveName" $ntUserPath

 

            # Define the registry path and value to be set

            $regPath = "HKU\$hiveName\Software\Microsoft\Office\Teams"

            $name = "PreventInstallationFromMsi"

            $value = "1"

           

            # Create the registry key if it does not exist

            if (-not (Test-Path -Path $regPath)) {

                New-Item -Path $regPath -Force | Out-Null

            }

           

            # Set the registry value

            Set-ItemProperty -Path $regPath -Name $name -Value $value -PropertyType String

           

            Write-Output "Edited registry for: $adminFolder"

        } catch {

            Write-Output "Failed to edit registry for: $adminFolder"

            Write-Output $_

        } finally {

            # Unload the hive

            reg unload "HKU\$hiveName"

        }

    } else {

        Write-Output "NTUSER.DAT not found in: $adminFolder"

    }

}

I got this output when ran:

Name           Used (GB)     Free (GB) Provider      Root                                               CurrentLocation

----           ---------     --------- --------      ----                                               ---------------

HKU                                    Registry      HKEY_USERS

The operation completed successfully.

Failed to edit registry for: C:\Users\admin0-admin

Set-ItemProperty : A parameter cannot be found that matches parameter name 'PropertyType'.

At line:42 char:71

+ ... roperty -Path $regPath -Name $name -Value $value -PropertyType String

+                                                      ~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Set-ItemProperty], ParameterBindingException

    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.SetItemPropertyCommand


The operation completed successfully.

The operation completed successfully.

Failed to edit registry for: C:\Users\admin1-admin

Set-ItemProperty : A parameter cannot be found that matches parameter name 'PropertyType'.

At line:42 char:71

+ ... roperty -Path $regPath -Name $name -Value $value -PropertyType String

+                                                      ~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Set-ItemProperty], ParameterBindingException

    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.SetItemPropertyCommand


The operation completed successfully.

ERROR: The process cannot access the file because it is being used by another process.

Failed to edit registry for: C:\Users\admin2-admin

Set-ItemProperty : A parameter cannot be found that matches parameter name 'PropertyType'.

At line:42 char:71

+ ... roperty -Path $regPath -Name $name -Value $value -PropertyType String

+                                                      ~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Set-ItemProperty], ParameterBindingException

    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.SetItemPropertyCommand

 

ERROR: The parameter is incorrect.

Although I can find Microsoft kb articles showing that string type should be declared like that, (maybe I read them incorrectly) it isn’t working. So I removed the -PropertyType String from the script and received this output (Italicized output is print from the script which is misleading, the registry was not edited, I verified through regedit.) :

New-PSDrive : A drive with the name 'HKU' already exists.

At line:2 char:1

+ New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ResourceExists: (HKU:String) [New-PSDrive], SessionStateException

    + FullyQualifiedErrorId : DriveAlreadyExists,Microsoft.PowerShell.Commands.NewPSDriveCommand

 

The operation completed successfully.

Set-ItemProperty : The property string PreventInstallationFromMsi=1 does not exist or was not found.

At line:42 char:13

+             Set-ItemProperty -Path $regPath -Name $name -Value $value

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ReadError: (string PreventInstallationFromMsi=1:PSNoteProperty) [Set-ItemProperty], IOEx

   ception

    + FullyQualifiedErrorId : SetPropertyError,Microsoft.PowerShell.Commands.SetItemPropertyCommand

 

*Edited registry for: C:\Users\admin0-admin*

The operation completed successfully.

The operation completed successfully.

Set-ItemProperty : The property string PreventInstallationFromMsi=1 does not exist or was not found.

At line:42 char:13

+             Set-ItemProperty -Path $regPath -Name $name -Value $value

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ReadError: (string PreventInstallationFromMsi=1:PSNoteProperty) [Set-ItemProperty], IOEx

   ception

    + FullyQualifiedErrorId : SetPropertyError,Microsoft.PowerShell.Commands.SetItemPropertyCommand

 

*Edited registry for: C:\Users\admin1-admin*

The operation completed successfully.

ERROR: The process cannot access the file because it is being used by another process.

Set-ItemProperty : The property string PreventInstallationFromMsi=1 does not exist or was not found.

At line:42 char:13

+             Set-ItemProperty -Path $regPath -Name $name -Value $value

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ReadError: (string PreventInstallationFromMsi=1:PSNoteProperty) [Set-ItemProperty], IOEx

   ception

    + FullyQualifiedErrorId : SetPropertyError,Microsoft.PowerShell.Commands.SetItemPropertyCommand

 

*Edited registry for: C:\Users\admin2-admin*

ERROR: The parameter is incorrect.

Edit: I tried implementing New-ItemProperty instead of Set-ItemProperty and got this output. Its strange because I would think the registry provider would support new-item property and I've seen it in the microsoft kb as an example. I'm not sure what I am missing from it. Output:

     Name           Used (GB)     Free (GB) Provider      Root                                               CurrentLocation
----           ---------     --------- --------      ----                                               ---------------
HKU                                    Registry      HKEY_USERS
The operation completed successfully.
New-ItemProperty : Cannot use interface. The IDynamicPropertyCmdletProvider interface is not implemented by this
provider.
At line:42 char:13
+             New-ItemProperty -Path $regPath -Name $name -Value $value ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (:) [New-ItemProperty], PSNotSupportedException
    + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.NewItemPropertyCommand

Edited registry for: C:\Users\admin0-admin
The operation completed successfully.
The operation completed successfully.
New-ItemProperty : Cannot use interface. The IDynamicPropertyCmdletProvider interface is not implemented by this
provider.
At line:42 char:13
+             New-ItemProperty -Path $regPath -Name $name -Value $value ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (:) [New-ItemProperty], PSNotSupportedException
    + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.NewItemPropertyCommand

Edited registry for: C:\Users\admin1-admin
The operation completed successfully.
ERROR: The process cannot access the file because it is being used by another process.
New-ItemProperty : Cannot use interface. The IDynamicPropertyCmdletProvider interface is not implemented by this
provider.
At line:42 char:13
+             New-ItemProperty -Path $regPath -Name $name -Value $value ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (:) [New-ItemProperty], PSNotSupportedException
    + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.NewItemPropertyCommand

Edited registry for: C:\Users\admin2-admin
ERROR: The parameter is incorrect.

Edit 2: Sorry for the long post for the question, and adding on, but I thought this might be useful info for someone else with this issue. I see an answer that I am going to try, hopefully it works with SCCM running the script on the machines. This additional edit to the script works only through PS Session, however it does work. I found the parameters for reg add, after searching more about reg load. Script:

#Create Custom HKU Powershell Drive

New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS

# Define the path to the Users directory

$usersPath = "C:\Users"

 

# Initialize an empty list to store admin folders

$AdminFolders = @()

 

# Get all directories in the Users folder

$directories = Get-ChildItem -Path $usersPath -Directory

 

# Iterate through each directory and check if it contains "-admin"

foreach ($dir in $directories) {

    if ($dir.Name -match "-admin") {

        $AdminFolders += $dir.FullName

    }

}

 

# Load the NTUSER.DAT file for each admin folder, edit the registry, and then unload it

foreach ($adminFolder in $AdminFolders) {

    $ntUserPath = Join-Path -Path $adminFolder -ChildPath "NTUSER.DAT"

   

    if (Test-Path -Path $ntUserPath) {

        # Define a temporary registry hive name

        $hiveName = "TempHive"

       

        try {

            # Load the NTUSER.DAT file into the registry

             # Load the NTUSER.DAT file into the registry

            Write-Output "Loading: $adminFolder"

            reg load "HKU\$hiveName" $ntUserPath

 

            # Define the registry path and value to be set

            $regPath = "HKU\$hiveName\Software\Microsoft\Office\Teams"

            $name = "PreventInstallationFromMsi"

            $value = "1"

           

            # Create the registry key if it does not exist

            if (-not (Test-Path -Path $regPath)) {

              Write-Output "Teams registry path not found, adding path"

                reg add HKU\$hiveName\Software\Microsoft\Office\Teams 

            }

              Write-Output "Adding PreventInstallationfromMsi key for: $adminFolder"

            reg add HKU\$hiveName\Software\Microsoft\Office\Teams /v $name /t REG_SZ /d $value

           

      

           

            Write-Output "Edited registry for: $adminFolder"

        } catch {

            Write-Output "Failed to edit registry for: $adminFolder"

            Write-Output $_

        } finally {

            # Unload the hive

              Write-Output "unloading hive: $adminFolder"

            reg unload "HKU\$hiveName"

        }

    } else {

        Write-Output "NTUSER.DAT not found in: $adminFolder"

    }

}

Remove-PSDrive HKU

 

Output of the script. The error for admin1-admin is my account running the script via PS Session. I have never logged into the machine, but I believe it has something to do with PS Session. Output:

Edited registry for: C:\Users\admin0-admin

unloading hive: C:\Users\admin0-admin

The operation completed successfully.

 

Loading: C:\Users\admin1-Admin

reg : ERROR: The process cannot access the file because it is being used by another process.

At line:31 char:13

+             reg load "HKU\$hiveName" $ntUserPath

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (ERROR: The proc...nother process.:String) [], RemoteException

    + FullyQualifiedErrorId : NativeCommandError

 

Teams registry path not found, adding path

reg : ERROR: The parameter is incorrect.

At line:41 char:17

+                 reg add HKU\$hiveName\Software\Microsoft\Office\Teams

+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (ERROR: The parameter is incorrect.:String) [], RemoteException

    + FullyQualifiedErrorId : NativeCommandError

 

Adding PreventInstallationfromMsi key for: C:\Users\admin1-Admin

reg : ERROR: The parameter is incorrect.

At line:44 char:13

+             reg add HKU\$hiveName\Software\Microsoft\Office\Teams /v  ...

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (ERROR: The parameter is incorrect.:String) [], RemoteException

    + FullyQualifiedErrorId : NativeCommandError

 

Edited registry for: C:\Users\admin1-Admin

unloading hive: C:\Users\admin1-Admin

reg : ERROR: The parameter is incorrect.

At line:55 char:13

+             reg unload "HKU\$hiveName"

+             ~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (ERROR: The parameter is incorrect.:String) [], RemoteException

    + FullyQualifiedErrorId : NativeCommandError
4
  • I don't believe Set-ItemProperty accepts -PropertyType, but New-ItemProperty does. Commented Jul 17, 2024 at 2:17
  • I tried New-ItemProperty, and I got this summarized error: New-ItemProperty : Cannot use interface. The IDynamicPropertyCmdletProvider interface is not implemented by this provider. Commented Jul 17, 2024 at 3:02
  • What happens when you use -force with New-ItemProperty? The docs say "Add the optional Force parameter to display hidden or system items.". The error code doesn't seem to indicate this should be the problem, but I've seen a number of deceptive error codes. Commented Jul 17, 2024 at 9:29
  • Also, you should have reg load "HKU\$hiveName" $ntUserPath, followed by if (-not $LASTEXITCODE) {, followed by try {. You do not want to run reg unload "HKU\$hiveName" if reg load ... fails. Commented Jul 17, 2024 at 12:23

1 Answer 1

0

Use Registry::HKEY_USERS\HiveName to access HKU items

This function takes a file, keypath, name of the registry value, its type, an actual value that will be saved in the registry, and the optional Force switch. Also found a way to generate a 7 letter random temporary hive name in a single line!

function Set-RegDatFile {
   [CmdletBinding()]
   param (
      [Parameter(Mandatory = $true)]
      [string]$File,
      [Parameter(Mandatory = $true)]
      [string]$KeyPath,
      [Parameter(Mandatory = $true)]
      [string]$Name,
      [Parameter(Mandatory = $true)]
      [ValidateSet('Binary', 'DWord', 'ExpandString', 'MultiString', 'QWord', 'String')]
      [string]$PropertyType,
      [Parameter(Mandatory = $true)]
      $Value,
      [switch]$Force
   )
   if (Test-Path -LiteralPath $File) {
      $hiveName = -join ([char[]](65..90) | Get-Random -Count 7)
      $hivePath = "HKU\$hiveName"
      REG.EXE LOAD $hivePath $file
      if (-not $LASTEXITCODE) {
         $fullKeyPath = Join-Path -Path "Registry::HKEY_USERS\$hiveName" -ChildPath $KeyPath
         if (-not (Test-Path -LiteralPath $fullKeyPath)) {
            $null = New-Item $fullKeyPath -Force -ErrorAction SilentlyContinue
         }
         $null = New-ItemProperty -LiteralPath $fullKeyPath -Name $Name -PropertyType $PropertyType -Value $Value -Force:$Force -ErrorAction SilentlyContinue
         REG.EXE UNLOAD $hivePath
         if ($LASTEXITCODE) {
            Write-Error "Error: Unable to unload registry hive: $hivePath"
         }
      }
      else {
         Write-Error "Error: Unable to load regitry file: $File"
      }
   }
   else {
      Write-Error "ERROR: Unable to find file: $File"
   }
}

And this is an example use:

Set-RegDatFile -File "$PSScriptRoot\User2\NTUSER.DAT" -KeyPath 'Software\Microsoft\Office\Teams' -Name 'PreventInstallationFromMsi' -PropertyType 'DWord' -Value 0x1
Sign up to request clarification or add additional context in comments.

2 Comments

I see the example use, but I am not sure where to put it in the script. I've been trying a few different ways and haven't had success. Should I put it after the end bracket for: if (-not (Test-Path -LiteralPath $fullKeyPath)) { $null = New-Item $fullKeyPath -Force -ErrorAction SilentlyContinue }
@Motivator6310, my intent wasn't nearly so much as to make a function that you can use, as it was to give you a working demonstration and proof that Registry::HKEY_USERS\$hiveName works. Take note of where I used this path and where I used $hivePath.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.