Home > OS >  Export Specific Registry Keys
Export Specific Registry Keys

Time:03-31

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 the Select-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 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.

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

  • Related