Files
ADDAP/Functions/Invoke-RegistryHiveAction.ps1
T
freedbygrace 3fcf06990c Initial Upload
2022-12-01 11:40:57 -05:00

355 lines
23 KiB
PowerShell

## Microsoft Function Naming Convention: http://msdn.microsoft.com/en-us/library/ms714428(v=vs.85).aspx
#region Function Invoke-RegistryHiveAction
Function Invoke-RegistryHiveAction
{
<#
.SYNOPSIS
A brief overview of what your function does
.DESCRIPTION
Slightly more detailed description of what your function does
.PARAMETER HivePath
A valid file path to a valid registry hive.
.PARAMETER KeyPath
One or more registry key paths that are relative to the specified registry hive.
.PARAMETER ValueNameExpression
One or more regular expressions that will determine which registry value names will be extracted from the specified registry hive.
.EXAMPLE
Invoke-RegistryHiveAction -HivePath "$($Env:Userprofile)\Downloads\RegistryHives\SOFTWARE" -KeyPath @('Root\Microsoft\Windows NT\CurrentVersion') -ValueNameExpression @('.*') -Verbose
.EXAMPLE
$InvokeRegistryHiveActionParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokeRegistryHiveActionParameters.HivePath = "$($Env:Userprofile)\Downloads\RegistryHives\SOFTWARE"
$InvokeRegistryHiveActionParameters.KeyPath = New-Object -TypeName 'System.Collections.Generic.List[String]'
$InvokeRegistryHiveActionParameters.KeyPath.Add('Root\Microsoft\Windows NT\CurrentVersion')
$InvokeRegistryHiveActionParameters.ValueNameExpression = New-Object -TypeName 'System.Collections.Generic.List[Regex]'
$InvokeRegistryHiveActionParameters.ValueNameExpression.Add('.*')
$InvokeRegistryHiveActionParameters.ContinueOnError = $False
$InvokeRegistryHiveActionParameters.Verbose = $True
$InvokeRegistryHiveActionResult = Invoke-RegistryHiveAction @InvokeRegistryHiveActionParameters
Write-Output -InputObject ($InvokeRegistryHiveActionResult)
.NOTES
Please ensure that the specified registry hive is not in use!
.LINK
https://github.com/EricZimmerman/Registry
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({(Test-Path -Path $_)})]
[System.IO.FileInfo]$HivePath,
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern('^Root\\.+')]
[String[]]$KeyPath,
[Parameter(Mandatory=$False)]
[Regex[]]$ValueNameExpression,
[Parameter(Mandatory=$False)]
[Switch]$ContinueOnError
)
Begin
{
Try
{
$DateTimeLogFormat = 'dddd, MMMM dd, yyyy @ hh:mm:ss.FFF tt' ###Monday, January 01, 2019 @ 10:15:34.000 AM###
[ScriptBlock]$GetCurrentDateTimeLogFormat = {(Get-Date).ToString($DateTimeLogFormat)}
$DateTimeMessageFormat = 'MM/dd/yyyy HH:mm:ss.FFF' ###03/23/2022 11:12:48.347###
[ScriptBlock]$GetCurrentDateTimeMessageFormat = {(Get-Date).ToString($DateTimeMessageFormat)}
$DateFileFormat = 'yyyyMMdd' ###20190403###
[ScriptBlock]$GetCurrentDateFileFormat = {(Get-Date).ToString($DateFileFormat)}
$DateTimeFileFormat = 'yyyyMMdd_HHmmss' ###20190403_115354###
[ScriptBlock]$GetCurrentDateTimeFileFormat = {(Get-Date).ToString($DateTimeFileFormat)}
$TextInfo = (Get-Culture).TextInfo
$LoggingDetails = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$LoggingDetails.Add('LogMessage', $Null)
$LoggingDetails.Add('WarningMessage', $Null)
$LoggingDetails.Add('ErrorMessage', $Null)
$CommonParameterList = New-Object -TypeName 'System.Collections.Generic.List[String]'
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::CommonParameters)
$CommonParameterList.AddRange([System.Management.Automation.PSCmdlet]::OptionalCommonParameters)
[System.IO.DirectoryInfo]$System32Directory = [System.Environment]::SystemDirectory
$RegexOptionList = New-Object -TypeName 'System.Collections.Generic.List[System.Text.RegularExpressions.RegexOptions]'
$RegexOptionList.Add([System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
$ValueNameExpressionList = New-Object -TypeName 'System.Collections.Generic.List[System.Text.RegularExpressions.Regex]'
[ScriptBlock]$ErrorHandlingDefinition = {
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$ErrorMessageList.Add('Message', $_.Exception.Message)
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
$ErrorMessageList.Add('Script', $_.InvocationInfo.ScriptName)
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
{
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
Write-Warning -Message ($LoggingDetails.ErrorMessage)
}
Switch (($ContinueOnError.IsPresent -eq $False) -or ($ContinueOnError -eq $False))
{
{($_ -eq $True)}
{
Throw
}
}
}
#Determine the date and time we executed the function
$FunctionStartTime = (Get-Date)
[String]$FunctionName = $MyInvocation.MyCommand
[System.IO.FileInfo]$InvokingScriptPath = $MyInvocation.PSCommandPath
[System.IO.DirectoryInfo]$InvokingScriptDirectory = $InvokingScriptPath.Directory.FullName
[System.IO.FileInfo]$FunctionPath = "$($InvokingScriptDirectory.FullName)\Functions\$($FunctionName).ps1"
[System.IO.DirectoryInfo]$FunctionDirectory = "$($FunctionPath.Directory.FullName)"
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function `'$($FunctionName)`' is beginning. Please Wait..."
Write-Verbose -Message ($LoggingDetails.LogMessage)
#Define Default Action Preferences
$ErrorActionPreference = 'Stop'
[String[]]$AvailableScriptParameters = (Get-Command -Name ($FunctionName)).Parameters.GetEnumerator() | Where-Object {($_.Value.Name -inotin $CommonParameterList)} | ForEach-Object {"-$($_.Value.Name):$($_.Value.ParameterType.Name)"}
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Available Function Parameter(s) = $($AvailableScriptParameters -Join ', ')"
Write-Verbose -Message ($LoggingDetails.LogMessage)
[String[]]$SuppliedScriptParameters = $PSBoundParameters.GetEnumerator() | ForEach-Object {"-$($_.Key):$($_.Value.GetType().Name)"}
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Supplied Function Parameter(s) = $($SuppliedScriptParameters -Join ', ')"
Write-Verbose -Message ($LoggingDetails.LogMessage)
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($FunctionName) began on $($FunctionStartTime.ToString($DateTimeLogFormat))"
Write-Verbose -Message ($LoggingDetails.LogMessage)
#region Load any required libraries
[System.IO.DirectoryInfo]$LibariesDirectory = "$($FunctionDirectory.FullName)\Libraries"
Switch ([System.IO.Directory]::Exists($LibariesDirectory.FullName))
{
{($_ -eq $True)}
{
$LibraryPatternList = New-Object -TypeName 'System.Collections.Generic.List[String]'
$LibraryPatternList.Add('NFluent.dll')
$LibraryPatternList.Add('NLog.dll')
$LibraryPatternList.Add('Registry.dll')
Switch ($LibraryPatternList.Count -gt 0)
{
{($_ -eq $True)}
{
$LibraryList = Get-ChildItem -Path ($LibariesDirectory.FullName) -Include ($LibraryPatternList.ToArray()) -Recurse -Force | Where-Object {($_ -is [System.IO.FileInfo])}
$LibraryListCount = ($LibraryList | Measure-Object).Count
Switch ($LibraryListCount -gt 0)
{
{($_ -eq $True)}
{
For ($LibraryListIndex = 0; $LibraryListIndex -lt $LibraryListCount; $LibraryListIndex++)
{
$Library = $LibraryList[$LibraryListIndex]
[Byte[]]$LibraryBytes = [System.IO.File]::ReadAllBytes($Library.FullName)
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to load assembly `"$($Library.FullName)`". Please Wait..."
Write-Verbose -Message ($LoggingDetails.LogMessage)
$Null = [System.Reflection.Assembly]::Load($LibraryBytes)
}
}
}
}
}
}
}
#endregion
#Create an object that will contain the functions output.
$OutputObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
#Set default parameter values
Switch ($True)
{
{($Null -ieq $ValueNameExpression) -or ($ValueNameExpression.Count -eq 0)}
{
$ValueNameExpression += '.*'
}
{($Null -ine $ValueNameExpression) -or ($ValueNameExpression.Count -gt 0)}
{
$ValueNameExpression | ForEach-Object {$ValueNameExpressionList.Add((New-Object -TypeName 'System.Text.RegularExpressions.Regex' -ArgumentList @($_, $RegexOptionList)))}
}
}
}
Catch
{
$ErrorHandlingDefinition.Invoke()
}
Finally
{
}
}
Process
{
Try
{
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to load registry hive `"$($HivePath.FullName)`" on demand. Please Wait..."
Write-Verbose -Message ($LoggingDetails.LogMessage)
$RegistryHive = New-Object -TypeName 'Registry.RegistryHiveOnDemand' -ArgumentList ($HivePath.FullName)
ForEach ($Key In $KeyPath)
{
Try
{
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to retrieve the details of registry key path `"$($Key)`". Please Wait..."
Write-Verbose -Message ($LoggingDetails.LogMessage)
$RegistryKeyProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$RegistryKeyProperties.Path = $Key
$RegistryKeyProperties.ValueList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
$RegistryKey = $RegistryHive.GetKey($Key)
ForEach ($Item In $RegistryKey.Values)
{
ForEach ($Expression In $ValueNameExpressionList)
{
$ExpressionEvaluation = $Expression.Match($Item.ValueName)
Switch ($ExpressionEvaluation.Success)
{
{($_ -eq $True)}
{
$ValueProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$ValueProperties.Name = $Item.ValueName
$ValueProperties.Alias = $ValueProperties.Name -ireplace '(\s+)', ''
$ValueProperties.Type = $Item.ValueType
$ValueProperties.Value = $Null
$ValueProperties.ValueAsDecimal = $Null
$ValueProperties.ValueAsHex = $Null
#$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Attempting to retrieve the registry key value of `"$($ValueProperties.Name)`" because the value name matches the regular expression of `"$($Expression.ToString())`". Please Wait..."
#Write-Verbose -Message ($LoggingDetails.LogMessage)
Switch ($Null -ine $Item.ValueData)
{
{($_ -eq $True)}
{
$ValueProperties.Value = $Item.ValueData
Switch ($ValueProperties.Type)
{
{($_ -iin @('RegDword', 'RegQword'))}
{
$ValueProperties.ValueAsDecimal = Try {[System.Convert]::ToString($ValueProperties.Value, 10)} Catch {}
$ValueProperties.ValueAsHex = Try {'0x' + [System.Convert]::ToString($ValueProperties.Value, 16).PadLeft(8, '0').ToUpper()} Catch {}
}
{($_ -iin @('RegBinary'))}
{
#$ValueProperties.ValueAsDecimal = Try {} Catch {}
#$ValueProperties.ValueAsHex = Try {} Catch {}
}
}
}
}
$ValueObject = New-Object -TypeName 'PSObject' -Property ($ValueProperties)
$RegistryKeyProperties.ValueList.Add($ValueObject)
}
}
}
}
$RegistryKeyObject = New-Object -TypeName 'PSObject' -Property ($RegistryKeyProperties)
$OutputObjectList.Add($RegistryKeyObject)
}
Catch
{
$ErrorMessageList = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$ErrorMessageList.Add('Message', $_.Exception.Message)
$ErrorMessageList.Add('Category', $_.Exception.ErrorRecord.FullyQualifiedErrorID)
$ErrorMessageList.Add('LineNumber', $_.InvocationInfo.ScriptLineNumber)
$ErrorMessageList.Add('LinePosition', $_.InvocationInfo.OffsetInLine)
$ErrorMessageList.Add('Code', $_.InvocationInfo.Line.Trim())
ForEach ($ErrorMessage In $ErrorMessageList.GetEnumerator())
{
$LoggingDetails.ErrorMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - ERROR: $($ErrorMessage.Key): $($ErrorMessage.Value)"
Write-Warning -Message ($LoggingDetails.ErrorMessage)
}
}
Finally
{
}
}
}
Catch
{
$ErrorHandlingDefinition.Invoke()
}
Finally
{
}
}
End
{
Try
{
#Determine the date and time the function completed execution
$FunctionEndTime = (Get-Date)
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Execution of $($FunctionName) ended on $($FunctionEndTime.ToString($DateTimeLogFormat))"
Write-Verbose -Message ($LoggingDetails.LogMessage)
#Log the total script execution time
$FunctionExecutionTimespan = New-TimeSpan -Start ($FunctionStartTime) -End ($FunctionEndTime)
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function execution took $($FunctionExecutionTimespan.Hours.ToString()) hour(s), $($FunctionExecutionTimespan.Minutes.ToString()) minute(s), $($FunctionExecutionTimespan.Seconds.ToString()) second(s), and $($FunctionExecutionTimespan.Milliseconds.ToString()) millisecond(s)"
Write-Verbose -Message ($LoggingDetails.LogMessage)
$LoggingDetails.LogMessage = "$($GetCurrentDateTimeMessageFormat.Invoke()) - Function `'$($FunctionName)`' is completed."
Write-Verbose -Message ($LoggingDetails.LogMessage)
}
Catch
{
$ErrorHandlingDefinition.Invoke()
}
Finally
{
#Write the object to the powershell pipeline
$OutputObjectList = $OutputObjectList.ToArray()
Write-Output -InputObject ($OutputObjectList)
}
}
}
#endregion