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$regPathand retrieves their properties.Where-Object{ $_.psobject.Properties.Value -ne $null }filters out any of the custom objects created by theSelect-Objectcall that do not at least have one non-$nullproperty value, using the intrinsic.psobjectproperty.
As for what you tried:
Your
Get-ChildItemcall returned objects of type[Microsoft.Win32.RegistryKey].Passing them to
Get-ItemProperty-Pathstringifies 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-ItemPropertyUse the
.PSPathproperty that PowerShell decorates the objects with:# Note: Parameter -Path implied; for full robustness, use -LiteralPath Get-ItemProperty $interface.PSPathPrepend 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,DhcpDefaultGatewayis an attempt to filter out "empty" objects resulting from theSelect-Objectcall, 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
-Propertyparameter, 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
-Propertyonly supports a single property name (string):Where-Object -Property DhcpIPAddress,DhcpNameServer,DhcpServer,DhcpDefaultGateway -LikeYour logic therefore requires passing a script block (
{ ... }) toWhere-Object's (positionally implied)-FilterScriptparameter, in which the input object as a whole can be referenced as usual, via the automatic$_variable. However, even your-likeoperation wouldn't work as intended; see the command at the top for how to filter out objects with only$nullproperty 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
