简体   繁体   中英

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
}

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM