Reputation: 101
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
}
Upvotes: 1
Views: 1845
Reputation: 437090
Leaving the 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 the Select-Object
call that do not at least have one non-$null
property value, using the intrinsic .psobject
property.
More work is needed in order to:
Add a Server
property that reflects the executing machine's host name.
Convert the array-valued DhcpDefaultGateway
property to a string-valued one, by joining potentially multiple addressed with ,
, so that exporting to a CSV works meaningfully (array-valued properties end up as verbatim System.String[]
in a CSV).
Both can be achieved via calculated properties:
$regPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces'
Get-ItemProperty $regPath\* |
Select-Object @{
Name='Server';
Expression = { $env:COMPUTERNAME }
},
DhcpIPAddress, DhcpNameServer, DhcpServer,
@{
Name = 'DhcpDefaultGateway';
Expression = { $_.DhcpDefaultGateway -join ', ' }
} |
Where-Object {
$_.psobject.Properties.Where({ $_.Name -ne 'Server' }).Value -ne $null
}
Note: If you want to collect all information in a single CSV file on the calling computer, across all servers, do something like the following:
Invoke-Command -Servers $Servers { ... } |
Select-Object * -Exclude PS*, RunspaceId |
Export-Csv C:\temp\TCPIP_Interface_Details.csv NoTypeInformation
-Exclude PS*, RunspaceId
excludes the properties that PowerShell remoting automatically adds to all output objects.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 the Select-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.
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 ({ ... }
) to Where-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.
Upvotes: 2
Reputation: 61028
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
Upvotes: 1