newprogrammer
newprogrammer

Reputation: 620

Remote registry key extractor PowerShell script

I am trying to create a PowerShell script that remotely checks each machine on the domain for a registry key entry, then outputs that key value along with the machine name to a .csv file.

So far the script outputs all the machines on the domain to a .csv file but puts its local registry key value not the value of the remote machine.

Any help would be greatly appreciated, here is what I have so far.

Import-Module ActiveDirectory

$SRVS = Get-ADComputer -Filter * -SearchBase 'DC=mydomain,DC=local' |
        select dnshostname

foreach ($SRV in $SRVS) {
    $REG = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $SRV.name)
    $REGKEY = $REG.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\QualityCompat")
    $MELT = $REGKEY.GetValue('cadca5fe-87d3-4b96-b7fb-a231484277cc')
    "$($SRV);$($MELT)" | Out-File C:\Users\user1\Desktop\regkeys.CSV -Append
}

Upvotes: 1

Views: 3584

Answers (3)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200273

The statement

$SRVS = Get-ADComputer ... | select dnshostname

gives you a list of custom objects with only one property: dnshostname. But in your loop you're trying to use a property name, which those custom objects don't have. Hence the statement

[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $SRV.name)

effectively becomes

[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $null)

meaning you're opening the local registry, not the registry on a remote host.

Change $SRV.name to $SRV.dnshostname and the problem will disappear.

Upvotes: 2

postanote
postanote

Reputation: 16096

Any reason you are trying to printout the actual regkey vs just checking for it's existence?

It either exists or it does not. Say using something like...

Clear-Host 
Import-Module ActiveDirectory

$SRVS = (Get-ADComputer -Filter * -SearchBase (Get-ADDomainController).DefaultPartition)
$MeltHive = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\QualityCompat'
$MeltHiveKey = 'cadca5fe-87d3-4b96-b7fb-a231484277cc'

ForEach($Srv in $SRVS)
{
    Invoke-Command -ComputerName $Srv.Name -ScriptBlock {
            If (Get-ItemProperty -Path $Using:MeltHive -Name $MeltHiveKey -ErrorAction SilentlyContinue)
            {"On Host $env:COMPUTERNAME MELT registry information exists"}
            Else {Write-Warning -Message "On host $env:COMPUTERNAME MELT registry information does not exist"}
        }
}



ForEach($Srv in $SRVS)
{
    Invoke-Command -ComputerName $Srv.Name -ScriptBlock {
            If ((Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion) -match 'QualityCompat')
            {"On Host $env:COMPUTERNAME MELT registry information exists"}
            Else {Write-Warning -Message "On host $env:COMPUTERNAME MELT registry information does not exist"}
        }
}


Results of both the above is:

WARNING: On host DC01 MELT registry information does not exist
WARNING: On host EX01 MELT registry information does not exist
WARNING: On host SQL01 MELT registry information does not exist
On Host IIS01 MELT registry information exists

Upvotes: 0

Bacon Bits
Bacon Bits

Reputation: 32170

Once it's been instanced the RegistryKey class does not expose that it's a remote key. That means you have to record the computer name yourself. There's also no standard format for a remote registry value.

If I had a PowerShell v5+, I would use something like this:

Import-Module ActiveDirectory

# No need for the Select-Object here since we're using $SRV.Name later
$SRVS = Get-ADComputer -Filter * -SearchBase 'DC=mydomain,DC=local'

# Create an arraylist to save our records
$Report = New-Object System.Collections.ArrayList

# This try finally is to ensure we can always write out what we've done so far
try {
    foreach ($SRV in $SRVS) {
        # Test if the remote computer is online
        $IsOnline = Test-Connection -ComputerName $SRV.Name -Count 1 -Quiet;
        if ($IsOnline) {
            # If system is Online
            $REG = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $SRV.name)
            $REGKEY = $REG.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\QualityCompat")
            $MELT = $REGKEY.GetValue('cadca5fe-87d3-4b96-b7fb-a231484277cc')

            # Create a PSObject record for convenience
            $Record = [PSCustomObject]@{
                ComputerName = $SRV;
                Key          = $REGKEY.Name;
                Value        = $MELT;
            }
        }
        else {
            # If system is Offline
            # Create a PSObject record for convenience
            $Record = [PSCustomObject]@{
                ComputerName = $SRV;
                Key          = '';
                Value        = '';
            }
        }

        # Add our record to the report
        $Report.Add($Record);
    }
}
finally {
    # Always write out what we have whether or not we hit an error in the middle
    $Report | Export-Csv -Path "C:\Users\user1\Desktop\regkeys.csv" -NoTypeInformation
}

That may work on PowerShell v3+, but I don't have it around anymore to test.

Upvotes: 1

Related Questions