nikon D3400
nikon D3400

Reputation: 101

Export Specific Registry Keys

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

Answers (2)

mklement0
mklement0

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.

      • 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 ({ ... }) 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

Theo
Theo

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

Related Questions