Using Powershell to verify registry entries remotely

2.3k views Asked by At

I'm trying to write a script that checks which print server users on our network are connecting to. To do that, I'm attempting to check the registry values listed under Printer\Connections. On my local machine the following two methods both work:

1)

Get-ChildItem HKCU:\Printers\Connections

Output:

Hive: HKEY_CURRENT_USER\Printers\Connections

Name                              Property
-----                             --------
,,printServer,printerName         GuidPrinter        : {guid}
                                  Server             : \\printserver.domain
                                  Provider           : win32spl.dll
                                  LocalConnection    : 1

2)

>> Get-ChildItem HKCU:\Printers\Connections | ForEach-Object {Get-ItemProperty $_.pspath}

And the output of that command is:

GuidPrinter     : {guid}
Server          : \\printServer.domain
Provider        : win32spl.dll
LocalConnection : 1
PSPath          : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Printers\Connections\,,printServerName,printerName
PSParentPath    : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Printers\Connections
PSChildName     : ,,printServerName, printerName
PSProvider      : Microsoft.PowerShell.Core\Registry    

By themselves, neither of these implementations are easily applied to remote machines. My most recent attempt to get the same information shown above off of a remote machine is:

$machine = 'computerName';
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('CurrentUser',$machine);
$regKey = $reg.OpenSubKey("Printers\Connections");
$regKey.GetValueName()

# I also tried the following which I didn't think
# would work, but I was grasping at straws:
# Get-ChildItem $regKey;

The above code returns nothing. It doesn't throw an error but regKey returns an empty string.

Does anyone know of an alternative solution to getting the information I'm looking for or see something wrong in the implementation above?

Thanks.

2

There are 2 answers

1
Matt On

By no means perfect but I came up with this. In examining its parts there are couple of different ways to get the same thing but this was the first approach where I was able to get tangible results. The function capabilities are lacking but I wanted to showcase the results more than the means.

Function Get-NetworkPrinters($computer){
    # This was the only consistent way I could get the "users" to show up. win32_computersystem has a username but its null for me (UAC maybe?)
    $remoteUsers = Get-WmiObject win32_process -ComputerName $computer -Filter 'Name = "explorer.exe"' -ErrorAction SilentlyContinue | ForEach-Object{
        $_.GetOwner().User
    }

    # Get the users sids from active directory. We need these to check the user hives.
    $users = $remoteUsers | Get-ADUser | Select-Object samaccountname,name,sid

    $users | ForEach-Object{
        # Keep the user for use in another pipe
        $user = $_

        # Key that contains the mappings
        $keyPath = "$($user.Sid)\Printers\Connections"

        # Open the remote registry keys
        $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::Users, $computer)

        # Get the key names of connections which "match" printer mappings
        $reg.OpenSubKey($keyPath).GetSubKeyNames() | ForEach-Object{
            $props = @{
                Printer = $_.Replace(",","\")
                Computer = $computer
                UserName = $user.samaccountname
            }

            New-Object -TypeName PSCustomObject -Property $props
        }
    }
}

You can pass individual computer names to the function and it will find the logged in users. They way it figures out who is logged in is based one users with an associated explorer.exe process. For each of those usernames check again active directory to get their SID (Get-AdUser might not be the best way but it is a simple one). Then we use that information to open the remote registry and get the network printer configuration.

Some sample output:

UserName Printer                        Computer
-------- -------                        --------
matt     \\printserver\kanexecutive01       mypc   
matt     \\printserver\kanlabel02           mypc   
matt     \\printserver\kanpublications01    mypc   
matt     \\printserver\kanpublications02    mypc   
matt     \\printserver\kantechrecords01     mypc   
matt     \\printserver\yowengineering02     mypc   
matt     \\printserver\ywglabel01           mypc   
matt     \\printserver\YEGlabelmtce01       mypc 

There are several potential errors that are not accounted for. So this is definitely subject to improvement over time.

You can also consider other remote registry options that are covered in this question and possibly adapt them to the logic here if what I have does not help you.

3
Luke On

It is because the key you are looking for is HKEY Current user, which although is correct changes with each user depending on who is logged in, so when you run it remotely is loading your hive not the users. you would have to get the user to run it, and one of the easiest ways would be to through it into the startup folder of the machine and it will run and report back to you without them knowing.