Skip to content

Instantly share code, notes, and snippets.

@adbertram
Last active August 29, 2015 14:16
Show Gist options
  • Save adbertram/5d20635c863fb9b8259e to your computer and use it in GitHub Desktop.
Save adbertram/5d20635c863fb9b8259e to your computer and use it in GitHub Desktop.
function Get-LoggedOnUserSID {
<#
.SYNOPSIS
This function queries the registry to find the SID of the user that's currently logged onto the computer interactively.
#>
[CmdletBinding()]
param ()
process {
try {
New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null
(Get-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' }).PSChildName
} catch {
Write-Log -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -LogLevel '3'
$false
}
}
}
function Import-RegistryFile {
<#
.SYNOPSIS
A function that uses the utility reg.exe to do a bulk import of registry changes.
.DESCRIPTION
This function allows the user to import registry changes in bulk by means of a .reg file. This
.reg file should only contain 1 set of registry keys such as HKLM or HKCU. If the .reg file
contains HKLM, HKCU, HKCR or HKCC key references, the file will be imported directly with no modification. If the
.reg file contains HKCU references, it will be modified to account for the currently logged on interactive
user, copied to a location on the computer and will be imported under each HKCU hive when another user
logs on.
.PARAMETER FilePath
The file path to the .reg file
#>
[CmdletBinding()]
param (
[Parameter()]
[ValidateScript({ Test-Path -Path $_ -PathType 'Leaf' })]
[string]$FilePath
)
begin {
try {
## Detect if this is a registry file for HKCU, HKLM, HKU, HKCR or HKCC keys
$Regex = 'HKEY_CURRENT_USER|HKEY_CLASSES_ROOT|HKEY_LOCAL_MACHINE|HKEY_USERS|HKEY_CURRENT_CONFIG'
$HiveNames = Select-String -Path $FilePath -Pattern $Regex | foreach { $_.Matches.Value }
$RegFileHive = $HiveNames | Select-Object -Unique
if ($RegFileHive -is [array]) {
throw "The registry file at '$FilePath' contains more than one hive reference."
} else {
Write-Log -Message "Detected hive type as $RegFileHive"
}
if ((Get-Architecture) -eq 'x64') {
$RegPath = 'syswow64'
} else {
$RegPath = 'System32'
}
} catch {
Write-Log -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -LogLevel '3'
return $false
}
}
process {
try {
if ($RegFileHive -ne 'HKEY_CURRENT_USER') {
Write-Log -Message "Starting registry import of reg file $FilePath..."
($Result = Start-Process "$($env:Systemdrive)\Windows\$RegPath\reg.exe" -Args "import `"$FilePath`"" -Wait -NoNewWindow -PassThru) | Out-Null
Check-Process -Process $Result
Write-Log -Message 'Registry file import done'
} else {
#########
## Import the registry file for the currently logged on user
#########
$LoggedOnSids = Get-LoggedOnUserSID
if ($LoggedOnSids.Count -gt 0) {
Write-Log -Message "Found $($LoggedOnSids.Count) logged on user SIDs"
foreach ($sid in $LoggedOnSids) {
## Replace all HKEY_CURRENT_USER references to HKCU\%SID% so that it can be applied to HKCU while not
## actually running under that context. Create a new reg file with the replacements in the system's temp folder
$HkcuRegFilePath = "$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)"
Write-Log -Message "Replacing HKEY_CURRENT_USER references with HKEY_USERS\$sid and placing temp file in $HkcuRegFilePath"
Find-InTextFile -FilePath $FilePath -Find $RegFileHive -Replace "HKEY_USERS\$sid" -NewFilePath $HkcuRegFilePath -Force
## Perform a recursive function call to itself to import the newly created reg file
Write-Log -Message "Importing reg file $HkcuRegFilePath"
Import-RegistryFile -FilePath $HkcuRegFilePath
Write-Log -Message "Removing temporary registry file $HkcuRegFilePath"
Remove-Item $HkcuRegFilePath -Force
}
} else {
Write-Log -Message 'No users currently logged on. Skipping current user registry import'
}
########
## Use Active Setup to create a registry value to perform an import of the registry file for each logged on user
########
Write-Log -Message "Copying $FilePath to systemp temp folder for later user"
Copy-Item -Path $FilePath -Destination "$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)"
Write-Log -Message "Setting Everyone full control on temp registry file so all users can import it"
$Params = @{
'Path' = "$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)"
'Identity' = 'Everyone'
'Right' = 'Modify';
'InheritanceFlags' = 'None';
'PropagationFlags' = 'NoPropagateInherit';
'Type' = 'Allow';
}
Set-MyFileSystemAcl @Params
Write-Log -Message "Setting registry file to import for each user"
## This isn't the *best* way to do this because this doesn't prevent a user from clearing out all the temp files
Set-AllUserStartupAction -CommandLine "reg import `"$(Get-SystemTempFilePath)\$($FilePath | Split-Path -Leaf)`""
}
} catch {
Write-Log -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" -LogLevel '3'
$false
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment