I have written a script to export specific registry keys and the sub keys inside it, but unfortunately my script get the keys, but not able to filter out the subkeys inside the item.
Please help me to get the subkeys for each object and export that data to CSV format.
$Servers = $env:COMPUTERNAME #Get-Content -Path
Foreach ($vm in $Servers) {
$TCPIP_Interface = Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
foreach ($interface in $TCPIP_Interface){
Get-ItemProperty -Path $interface| Where-Object -Like DhcpIPAddress,DhcpNameServer,DhcpServer,DhcpDefaultGateway
}
#| Select-Object -Property DhcpIPAddress,DhcpNameServer,DhcpServer,DhcpDefaultGateway #| Export-Csv -Path "C:\temp\TCPIP_Interface_Details.csv" -NoTypeInformation
}
CodePudding user response:
Leaving the incidental aspect of targeting multiple remote computers aside (for which you'd need Invoke-Command
-ComputerName $Servers { ... }
), you can simplify your code as follows (I'm also omitting the Export-Csv
call):
$regPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces'
Get-ItemProperty $regPath\* |
Select-Object DhcpIPAddress,DhcpNameServer,DhcpServer,DhcpDefaultGateway |
Where-Object { $_.psobject.Properties.Value -ne $null }
Using wildcard path
$regPath\*
implicitly loops over all the child keys in$regPath
and retrieves their properties.Where-Object
{ $_.psobject.Properties.Value -ne $null }
filters out any of the custom objects created by theSelect-Object
call that do not at least have one non-$null
property value, using the intrinsic.psobject
property.
As for what you tried:
Your
Get-ChildItem
call returned objects of type[Microsoft.Win32.RegistryKey]
.Passing them to
Get-ItemProperty
-Path
stringifies them, resulting in a registry-native path to be reported; e.g.:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{223a2c0a-88d9-11e6-b808-806e6f6e6963}
PowerShell doesn't directly recognize such paths and assumes that they are (relative) file-system paths. To force their interpretation as a registry path, you have tree options:
Preferably, use the pipeline to supply the input path:
# Note: This binds the .PSPath property value to the -LiteralPath parameter. $interface | Get-ItemProperty
Use the
.PSPath
property that PowerShell decorates the objects with:# Note: Parameter -Path implied; for full robustness, use -LiteralPath Get-ItemProperty $interface.PSPath
Prepend the
registry::
provider prefix to the registry-native path resulting from the stringification:Get-ItemProperty registry::$interface
I presume that
Where-Object -Like DhcpIPAddress,DhcpNameServer,DhcpServer,DhcpDefaultGateway
is an attempt to filter out "empty" objects resulting from theSelect-Object
call, so that only objects that have actual values for the selected properties are returned and exported to CSV.However, even syntactically this approach cannot work, because as of PowerShell 7.2.x you cannot implicitly apply an operation to each input object as a whole using simplified syntax; instead, you must specify a property to operate on, via the
-Property
parameter, to which the first positional argument implicitly binds.- That said, it would be convenient to be able to operate implicitly on each input object as a whole, and GitHub issue #8357 proposes adding support for it.
Thus, your command is equivalent to the following, which fails, because
-Property
only supports a single property name (string):Where-Object -Property DhcpIPAddress,DhcpNameServer,DhcpServer,DhcpDefaultGateway -Like
Your logic therefore requires passing a script block (
{ ... }
) toWhere-Object
's (positionally implied)-FilterScript
parameter, in which the input object as a whole can be referenced as usual, via the automatic$_
variable. However, even your-like
operation wouldn't work as intended; see the command at the top for how to filter out objects with only$null
property values.
CodePudding user response:
Each $interface
is an object with properties of which .Path
is the interesting one.
Try:
$Servers = $env:COMPUTERNAME # Get-Content -Path
$result = foreach ($vm in $Servers) {
Invoke-Command -ComputerName $vm -ScriptBlock {
Get-ChildItem -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces' | ForEach-Object {
Get-ItemProperty -Path $_.PSPath | Where-Object { $_.PsObject.Properties.Name -like 'Dhcp*' }
}
} | Select-Object -Property @{Name = 'ComputerName'; Expression = {$_.PSComputerName}},
DhcpIPAddress,
@{Name = 'DhcpNameServer'; Expression = {$_.DhcpNameServer -split ' ' -join '; '}},
DhcpServer,
@{Name = 'DhcpDefaultGateway'; Expression = {$_.DhcpDefaultGateway -join '; '}}
}
$result | Export-Csv -Path "C:\temp\TCPIP_Interface_Details.csv" -NoTypeInformation
Of course, you may need to add parameter -Credential
to the Invoke-Command
cmdlet and supply a valid administrator credential