Classes.psm1
using namespace System.Collections using namespace System.Collections.Generic using namespace System.Management.Automation using namespace System.Management.Automation.Language # CIMRegistryKey is extended in the Types.ps1xml class CIMRegistryObject { # [string]$Path [string]$PSComputerName = 'localhost' [ValidateSet('Dcom','Wsman','Default')] [string]$Protocol = 'Default' [string]$CimSessionId # System.Guid } class CIMRegistryKey:CIMRegistryObject { [string]$Path [string]$ParentKey [string]$Key $DefaultValue $SubKeyCount $ValueCount CIMRegistryKey () {} CIMRegistryKey ([string]$Path, [string]$PSComputerName, [string]$Protocol, [string]$CimSessionId) { $this.Path = $Path $this.PSComputerName = $PSComputerName $this.Protocol = $Protocol $this.CimSessionId = $CimSessionId } CIMRegistryKey ([string]$Path, $DefaultValue, $SubKeyCount, $ValueCount, [string]$PSComputerName, [string]$Protocol, [string]$CimSessionId) { $this.Path = $Path $this.DefaultValue = $DefaultValue $this.SubKeyCount = $SubKeyCount $this.ValueCount = $ValueCount $this.PSComputerName = $PSComputerName $this.Protocol = $Protocol $this.CimSessionId = $CimSessionId } } class CIMRegistryValue:CIMRegistryObject { [string]$Path [string]$ValueName [RegistryDataType]$ValueType [object]$Data [bool]$InvalidData CIMRegistryValue () {} CIMRegistryValue ([string]$Path) { $this.Path = $Path } CIMRegistryValue ([string]$Path,[string]$ValueName,[RegistryDataType]$ValueType, [object]$Data, [string]$PSComputerName) { $this.Path = $Path $this.ValueName = $ValueName $this.Type = $ValueType $this.Data = $Data $this.PSComputerName = $PSComputerName } CIMRegistryValue ([string]$Path,[string]$ValueName,[RegistryDataType]$ValueType, [object]$Data, [string]$PSComputerName, [string]$Protocol, [string]$CimSessionId) { $this.Path = $Path $this.ValueName = $ValueName $this.Type = $ValueType $this.Data = $Data $this.PSComputerName = $PSComputerName $this.Protocol = $Protocol $this.CimSessionId = $CimSessionId } } class CIMRegPathCompleter : IArgumentCompleter { [IEnumerable[CompletionResult]] CompleteArgument( [string] $Command, [string] $Parameter, [string] $WordToComplete, [CommandAst] $Ast, [IDictionary] $FakeBoundParameter ) { $Result = [List[CompletionResult]]::new(10) $RegPath = ($wordToComplete.Trim(' ',"'",'"') -replace '/','\') if (-not $RegPath) {$RegPath = '\'} $Parent = [io.path]::GetDirectoryName($RegPath) $Leaf = [io.path]::GetFileName($RegPath) $NameList = (Get-ChildItem -Path ("Registry::"+ $Parent)).PSChildName foreach ($Name in $NameList) { if ($Name.StartsWith($Leaf, [System.StringComparison]::OrdinalIgnoreCase)) { $CompletionPath = if ($Parent) {"$Parent\$Name"} else {$Name} [CIMRegPathCompleter]::AddCompletionValue($Result,$CompletionPath, $Name, $Name) } } return $Result } static [void] AddCompletionValue([List[CompletionResult]] $Result, [string] $path, [string] $ListItem, [string] $ToolTip) { $CompletionText = If ($Path.Contains(' ')) { "'$Path'" } else { $Path } $result.Add([CompletionResult]::new($CompletionText, $ListItem, [CompletionResultType]::ParameterValue, $ToolTip)) } } Class CimError { # https://stackoverflow.com/questions/49204918/difference-between-throw-and-pscmdlet-throwterminatingerror # [ErrorRecord], ErrorId: https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.errorcategory?view=pscore-6.2.0 # Exception .NET: https://docs.microsoft.com/en-us/dotnet/api/system?view=netframework-4.8 static [ErrorRecord] UnsupportedCimSessionValue ($ComputerName) { $Exception = [System.ArgumentException]::new("CimSession parameter value is not valid. '$ComputerName' is not a string or CimSession object.'") return [ErrorRecord]::new($Exception, "InvalidComputerName", [ErrorCategory]::InvalidArgument, $ComputerName) } static [ErrorRecord] EmptyCIMOutput ($ComputerName,$ProviderName) { $Exception = [System.InvalidOperationException]::new("$ProviderName method of StdRegProv WMI provider returned no data.") If (-not $ComputerName) {$ComputerName = '.'} return [ErrorRecord]::new($Exception, "InvalidOutputData", [ErrorCategory]::InvalidResult, "\\$ComputerName\ROOT\DEFAULT:StdRegProv") } static [ErrorRecord] SubkeysExist ($SubKeyCount, $targetObject) { $Exception = [System.InvalidOperationException]::new("Registry key cannot be deleted because it has $SubKeyCount subkey(s).") return [ErrorRecord]::new($Exception, "InvalidOutputData", [ErrorCategory]::NotEnabled, $targetObject) } static [ErrorRecord] GetWin32ErrorDescription ($Win32Error, $targetObject) { $ErrorMessage = If ($Win32Error -eq 1) { "Registry value does not exist." } ElseIf ($Win32Error -eq 2) { "Registry key does not exist." } ElseIf ($Win32Error -eq 2147749893) { "Type mismatch occurred." } Else { ([System.ComponentModel.Win32Exception]::new([int32]$Win32Error)).Message } $Exception = [System.ArgumentException]::new($ErrorMessage) return [ErrorRecord]::new($Exception, "StdRegProvError", [ErrorCategory]::OperationStopped, $targetObject) } static [ErrorRecord] AccessDeniedVerbose ($AccessPermission, $targetObject) { $ErrorMessage = "Access is denied. You have no '$([RegistryAccess]$AccessPermission)' permission." $Exception = [System.ArgumentException]::new($ErrorMessage) return [ErrorRecord]::new($Exception, "StdRegProvError", [ErrorCategory]::OperationStopped, $targetObject) } } Enum RegistryDataType { REG_SZ = 1 REG_EXPAND_SZ = 2 REG_BINARY = 3 REG_DWORD = 4 REG_MULTI_SZ = 7 REG_QWORD = 11 } [Flags()] enum RegistryAccess { KEY_QUERY_VALUE = 1 KEY_SET_VALUE = 2 KEY_CREATE_SUB_KEY = 4 KEY_ENUMERATE_SUB_KEYS = 8 KEY_NOTIFY = 16 KEY_CREATE = 32 DELETE = 65536 READ_CONTROL = 131072 WRITE_DAC = 262144 WRITE_OWNER = 524288 } ### Drafts <# Class HexToDec { [System.UInt32]$Decimal HexToDec ([string]$Hex) { $this.Decimal = [System.Convert]::ToUInt32($Hex,16) } } Enum CIMRootKey { HKEY_CLASSES_ROOT = '80000000' HKEY_CURRENT_USER = '80000001' HKEY_LOCAL_MACHINE = '80000002' HKEY_USERS = '80000003' HKEY_PERFORMANCE_DATA = '80000004' HKEY_CURRENT_CONFIG = '80000005' HKEY_DYN_DATA = '80000006' } #> |