Get default printer remotely

28,327

Solution 1

You can use wmi32_printer to get the default. Here is the code:

$AllPrinters = gwmi win32_printer -computername c78572
$DefaultPrinter = $AllPrinters | where {$_.Default -eq $true}

This will return all locally attached printers. If you want to get a list of network attached printers (as Aaron commented below), you run into a little bit of an issue. The above script doesn't work because WMI operates on the local machine, and not on the user level. After much research, one way of getting this information is to have a log on script that runs, because there is essentially no other way of remotely using WMI to get the logged in user's information.

How to really do it if we can't use WMI? Use the back door. All the pertinent information is stored in the registry. The output may not be pretty, but it will give you all the information that we need. We are only concerned about 3 key locations:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers

This contains all Locally Installed printers. Forget about it, use the gwmi win32_printer command to get this list.

HKEY_CURRENT_USER\Printers\Settings

This contains all the Currently logged in User Installed printers. It does not have the default printer information.

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device

This is where to get the Currently logged in User Installed Default printer. i.e. This is what Aaron is specifically looking for.

So, we can use PowerShell to connect to the remote registry, and read the currently logged in user's default printer with the following script:

$Computer = "c78572"
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('currentuser', $Computer)
$RegKey= $Reg.OpenSubKey('Software\Microsoft\Windows NT\CurrentVersion\Windows')
$DefaultPrinter = $RegKey.GetValue("Device")
$DefaultPrinter | ConvertFrom-Csv -Header Name, Provider, Order| Select Name

----EDIT - to get a list of all printers----

To list all printers on the remote computer:

$Computer = "c78572"

#Get Local Printers:
$Printers = @(Get-WmiObject win32_printer -computername $Computer | Select Name)

#Get List of Network Printers:
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('currentuser', $Computer)
$RegKey= $Reg.OpenSubKey('Printers\Settings')
$Printers += @($RegKey.GetValueNames())

#Output List of Printers
Write-Output $Printers | ft -Property @{Name="Printer Name";Expression={$_.Name}} -AutoSize


#Get Default Printer
$Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('currentuser', $Computer)
$RegKey= $Reg.OpenSubKey('Software\Microsoft\Windows NT\CurrentVersion\Windows')
$DefaultPrinter = $RegKey.GetValue("Device")

#Output the Default Printer
Write-Output $DefaultPrinter | ConvertFrom-Csv -Header Name, Provider, Order| Select Name | ft -Property @{Name="Default Printer Name";Expression={$_.Name}} -AutoSize

Solution 2

This script will return the specified computer's currently-logged-in user's default printer (read from the Registry).

We're trying to clean up some network printer connections, and a script like this that shows the shared printers that a user is connected to is something we really need.

My primary challenge was figuring out a way to get at the "current user" information (as opposed to the "computer" information). The shared printer connections are stored in the user area, so that's where I needed to be.

I pieced together information from several sources to do it this way:

  • Determine the logged-in user (account)
  • Get the SID for that user
  • Use the SID to navigate to the user's HKEY_USERS Registry hive
  • Output the value in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\Device. Before coding I determined that this Registry value is updated immediately upon a default printer change. BONUS: You can also change/set the user's default printer by updating this Registry value.
# ---------------------------------------------------------------------------
#
# This script requires a computer name.  It will return the computer's 
# currently logged-in user's default printer.
#
# ---------------------------------------------------------------------------

# Set the variable below to choose your computer
$Computer = "computer_name"


# get the logged-in user of the specified computer
$user = Get-WmiObject –ComputerName $computer –Class Win32_ComputerSystem | Select-Object UserName

# get that user's AD object
$AdObj = New-Object System.Security.Principal.NTAccount($user.UserName)

# get the SID for the user's AD Object 
$strSID = $AdObj.Translate([System.Security.Principal.SecurityIdentifier])

# get a handle to the "USERS" hive on the computer
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("Users", $Computer)

# get a handle to the current user's USERS Registry key where the default printer value lives
$regKey = $reg.OpenSubKey("$strSID\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows")

# read and show the new value from the Registry for verification
$regValue = $regKey.GetValue("Device")
write-output $regValue
write-output " "
write-output " "
[void](Read-Host 'Press Enter to continue…')
Share:
28,327
Aaron
Author by

Aaron

Updated on April 07, 2020

Comments

  • Aaron
    Aaron about 4 years

    Windows 7:

    cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\prnmngr.vbs -g
    

    Windows XP:

    cscript C:\windows\system32\prnmngr.vbs -g
    

    These will get the default printer of the current system. I was wondering if there is a way to run this on my computer to get the default printer of a remote computer by computer name?

    I tried running:

    psexec \\c78572 -i -d cscript C:\Windows\System32\Printing_Admin_Scripts\en-US\prnmngr.vbs -g
    

    And it appears to run.. but I only see the results in a quick popup cmd line window on the remote computer and not on mine. All I see on my end is:

    cscript started with process ID 568.
    

    In powershell gwmi win32_printer -computername c78572 works.. but I don't know how to sort it to show me the default printer.

    EDIT 12/20/13 I am trying to combine it with a show all printers and the default but I can't get it to work:

    while (1) {
    $tag1 = Read-Host 'Enter tag # or Q to quit'
    if ($tag1 -eq "Q") {
        break;
    }
    
    cls
    
    sc.exe \\$tag1 start RemoteRegistry;
    
    cls
    
    start-sleep -seconds 2
    
    cls
    
    $OSInfo = get-wmiobject -class win32_operatingsystem -computername $tag1;
    $OSInfo | Format-Table -Property @{Name="OS Name";Expression={$_.Caption}},@{Name="System Boot Time";Expression={$_.ConvertToDateTime($_.LastBootUpTime)}} -AutoSize;
    
    
    gwmi win32_printer -computername $tag1 | ft -Property @{Name="Printer Name";Expression={$_.Name}} -AutoSize;
    
    $Computer = $tag1
    $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('currentuser', $Computer)
    $RegKey= $Reg.OpenSubKey('Software\Microsoft\Windows NT\CurrentVersion\Windows')
    $DefaultPrinter = $RegKey.GetValue("Device")
    $DefaultPrinter | ConvertFrom-Csv -Header Name, Provider, Order| Select Name
    
    # Alt method: Get-WmiObject win32_printer -computername c60311
    

    }