PSDataKit.psm1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# Implement your module commands in this script. # Export only the functions using PowerShell standard verb-noun naming. # Be sure to list each exported functions in the FunctionsToExport field of the module manifest file. # This improves performance of command discovery in PowerShell. function Merge-Hashtables { [cmdletbinding()] Param ( [hashtable] # First hashtable to merge, this will have priority $primary, [hashtable] # second hashtable to merge $secondary ) # If in debug mode, show the function currently in #Write-Log -IfDebug -Message $("***** {0} *****" -f $MyInvocation.MyCommand) # Craete an array of types that can be merged. # Hashtables and Dictionaries can be merged $types = @( "Hashtable" "Dictionary``2" ) #check for any duplicate keys $duplicates = $primary.keys | where {$secondary.ContainsKey($_)} if ($duplicates) { foreach ($key in $duplicates) { # if the item is a hashtable then call this function again if ($types -contains $primary.$key.gettype().name -and $types -contains $secondary.$key.gettype().name) { # set the argument hashtable $splat = @{ primary = $primary.$key secondary = $secondary.$key } $Primary.$key = Merge-Hashtables @splat } # if the key is an array merge the two items if ($primary.$key.GetType().Name -eq "Object[]" -and $secondary.$key.GetType().name -eq "Object[]") { $result = @() # Because an array can contain many different types, need to be careful how this information is merged # This means that the normal additional functions and the Unique parameter of Select will not work properly # so iterate around each of the two arrays and add to a result array foreach ($arr in @($primary.$key, $secondary.$key)) { # analyse each item in the arr foreach ($item in $arr) { # Switch on the type of the item to determine how to add the information switch ($item.GetType().Name) { "Object[]" { $result += , $item } # If the type is a string make sure that the array does not already # contain the same string "String" { if ($result -notcontains $item) { $result += $item } } # For everything else add it in default { $result += $item } } } } # Now assign the result back to the primary array $primary.$key = $result } #force primary key, so remove secondary conflict $Secondary.Remove($key) } } #join the two hash tables and return to the calling function $Primary + $Secondary } Export-ModuleMember -Function Merge-Hashtables Function ConvertTo-FlattenObject { # Version 00.02.12, by iRon [CmdletBinding()]Param ( [Parameter(ValueFromPipeLine = $True)][Object[]]$Objects, [String]$Separator = ".", [ValidateSet("", 0, 1)]$Base = 1, [Int]$Depth = 5, [Int]$Uncut = 1, [String[]]$ToString = ([String], [DateTime], [TimeSpan]), [String[]]$Path = @() ) $PipeLine = $Input | ForEach {$_}; If ($PipeLine) {$Objects = $PipeLine} If (@(Get-PSCallStack)[1].Command -eq $MyInvocation.MyCommand.Name -or @(Get-PSCallStack)[1].Command -eq "<position>") { $Object = @($Objects)[0]; $Iterate = New-Object System.Collections.Specialized.OrderedDictionary If ($ToString | Where-Object {$Object -is $_}) {$Object = $Object.ToString()} ElseIf ($Depth) { $Depth-- If ($Object.GetEnumerator.OverloadDefinitions -match "[\W]IDictionaryEnumerator[\W]") { $Iterate = $Object } ElseIf ($Object.GetEnumerator.OverloadDefinitions -match "[\W]IEnumerator[\W]") { $Object.GetEnumerator() | ForEach-Object -Begin {$i = $Base} {$Iterate.($i) = $_; $i += 1} } Else { $Names = If ($Uncut) {$Uncut--} Else {$Object.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames} If (!$Names) {$Names = $Object.PSObject.Properties | Where-Object {$_.IsGettable} | Select-Object -Expand Name} If ($Names) {$Names | ForEach-Object {$Iterate.$_ = $Object.$_}} } } If (@($Iterate.Keys).Count) { $Iterate.Keys | ForEach-Object { ConvertTo-FlattenObject @(, $Iterate.$_) $Separator $Base $Depth $Uncut $ToString ($Path + $_) } } Else {$Property.(($Path | Where-Object {$_}) -Join $Separator) = $Object} } ElseIf ($Objects -ne $Null) { @($Objects) | ForEach-Object -Begin {$Output = @(); $Names = @()} { New-Variable -Force -Option AllScope -Name Property -Value (New-Object System.Collections.Specialized.OrderedDictionary) ConvertTo-FlattenObject @(, $_) $Separator $Base $Depth $Uncut $ToString $Path $Output += New-Object PSObject -Property $Property $Names += $Output[-1].PSObject.Properties | Select -Expand Name } $Output | Select-Object ([String[]]($Names | Select-Object -Unique)) } }; Export-ModuleMember -Function ConvertTo-FlattenObject |