Manolis
Manolis

Reputation: 167

Printing borderless with PowerShell script

I'm using a modified version of the script I found at https://monadblog.blogspot.com/2006/02/msh-print-image.html. It allows you to print by using PowerShell.

Something that I have been unable to figure out is how to print borderless, I have removed margins and I tried adding a custom paper size or sending a bigger image than the allowed image to the printer but it didn't work. Is there a way to enable the borderless flag?


$imageName = 'C:\image.png'
$printer = "Canon SELPHY CP1500"
$fitImageToPaper = $true

 trap { break; }

 # check out Lee Holmes' blog(http://www.leeholmes.com/blog/HowDoIEasilyLoadAssembliesWhenLoadWithPartialNameHasBeenDeprecated.aspx)
 # on how to avoid using deprecated "LoadWithPartialName" function
 # To load assembly containing System.Drawing.Printing.PrintDocument
 [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

 # Bitmap image to use to print image
 $bitmap = $null

 $doc = new-object System.Drawing.Printing.PrintDocument
 $doc.DefaultPageSettings.Margins.Left = 0
$doc.DefaultPageSettings.Margins.Right = 0
$doc.DefaultPageSettings.Margins.Top = 0
$doc.DefaultPageSettings.Margins.Bottom = 0

 Write-Host $doc.DefaultPageSettings.PaperSize
 # if printer name not given, use default printer
 if ($printer -ne "") {
  $doc.PrinterSettings.PrinterName = $printer
 }
 
 $doc.DocumentName = [System.IO.Path]::GetFileName($imageName)

 $doc.add_BeginPrint({
  Write-Host "==================== $($doc.DocumentName) ===================="
 })
 
 # clean up after printing...
 $doc.add_EndPrint({
  if ($bitmap -ne $null) {
   $bitmap.Dispose()
   $bitmap = $null
  }
  Write-Host "xxxxxxxxxxxxxxxxxxxx $($doc.DocumentName) xxxxxxxxxxxxxxxxxxxx"
 })
 
 # Adjust image size to fit into paper and print image
 $doc.add_PrintPage({
  Write-Host "Printing $imageName..."
 
  $g = $_.Graphics
  $pageBounds = $_.PageBounds
  $img = new-object Drawing.Bitmap($imageName)
  
  $adjustedImageSize = $img.Size
  $ratio = [double] 1;
  
  # Adjust image size to fit on the paper
  if ($fitImageToPaper) {
   $fitWidth = [bool] ($img.Size.Width > $img.Size.Height)
   if (($img.Size.Width -le $_.MarginBounds.Width) -and
    ($img.Size.Height -le $_.MarginBounds.Height)) {
    $adjustedImageSize = new-object System.Drawing.SizeF($img.Size.Width, $img.Size.Height)
   } else {
    if ($fitWidth) {
     $ratio = [double] ($_.MarginBounds.Width / $img.Size.Width);
    } else {
     $ratio = [double] ($_.MarginBounds.Height / $img.Size.Height)
    }
    
    $adjustedImageSize = new-object System.Drawing.SizeF($img.Size.Width, $img.Size.Height)
   }
  }

  # calculate destination and source sizes
  $recDest = new-object Drawing.RectangleF($pageBounds.Location, $adjustedImageSize)
  $recSrc = new-object Drawing.RectangleF(0, 0, $img.Width, $img.Height)
  
  # Print to the paper
  $_.Graphics.DrawImage($img, $recDest, $recSrc, [Drawing.GraphicsUnit]"Pixel")

  $_.HasMorePages = $false; # nothing else to print
 })
 
 $doc.Print()

Thanks!

Upvotes: 0

Views: 331

Answers (1)

kconsiglio
kconsiglio

Reputation: 675

While I can't fully test borderless printing since I don't have a printer to test it with, I was able to test enable duplex printing using the same method.

We can accomplish this using the System.Printing namespace. Specifically, we will use PrintServer, PrintQueue, and UserPrintTicket to edit the PageBorderless property.

We first create a PrintServer object. You can either use LocalPrintServer for locally connected device or you can specify a print server name:

$PrintServer = New-Object System.Printing.LocalPrintServer
#$PrintServer = New-Object System.Printing.PrintServer("\\somePrintserver")

We then create a PrintQueue specifying the PrintServer object, a printer name, and PrintSystemDesiredAccess which specifies access right for printing objects. I set the access to AdministratePrinter.

$desiredAccess = New-Object System.Printing.PrintSystemDesiredAccess
# AdministratePrinter value
$desiredAccess.value__ = 983052
$printerName = "TEST"
# Create PrintQueue object using the PrintServer, printer name, and the desired access as parameters
$PrintQueue = New-Object System.Printing.PrintQueue($PrintServer,$printerName,$desiredAccess)

Once the queue is created we can get the UserPrintTicket, which we will use to modify the PageBorderless property

# get UserPrintTicket from the PrintQueue
$PrintTicket =  $PrintQueue.UserPrintTicket

I did add some checks to make sure that the printer has the capability before changing that setting. Using $PrintQueue.GetPrintCapabilities() we can see the capabilities and verify before changing them. Due to limitation of my printer I was only able to verify this was working for changing the Duplexing property but since it's the same as editing the PageBorderless property I believe it should still work. I left the example for Duplexing in here. You will need to add back in the code to handle actual printing since this just modifies the setting.

$exitOnNotEnabled = $true

Add-Type -AssemblyName System.Printing

# Specify desired access to modify settings
$desiredAccess = New-Object System.Printing.PrintSystemDesiredAccess
# AdministratePrinter value
# https://learn.microsoft.com/en-us/dotnet/api/system.printing.printsystemdesiredaccess?view=windowsdesktop-7.0
$desiredAccess.value__ = 983052

# change to your printer name
$printerName = "TEST"

# Create PrintServer object. Can specify a print server but here I just have printer connected locally. 
$PrintServer = New-Object System.Printing.LocalPrintServer
#$PrintServer = New-Object System.Printing.PrintServer("\\somePrintserver")

# Create PrintQueue object using the PrintServer, printer name, and the desired access as parameters
$PrintQueue = New-Object System.Printing.PrintQueue($PrintServer,$printerName,$desiredAccess)

# get UserPrintTicket from the PrintQueue
$PrintTicket =  $PrintQueue.UserPrintTicket

# get printer capabilities. Going to use to make sure we only change setting that the printer has
$PrintCapabilities = $PrintQueue.GetPrintCapabilities()

# check if the PageBorderlessCapability exists
if ($PrintCapabilities.PageBorderlessCapability -ne $null){
    Write-Output "-------------------------"
    Write-Output "PageBorderless is currently set to $($PrintTicket.PageBorderless)"
    Write-Output "-------------------------"
    # check if the PageBorderlessCapability contains 'Borderless'
    if ($PrintCapabilities.PageBorderlessCapability.Contains("Borderless")){
        Write-Output "Borderless printing capability found"
        Write-Output "Enable Borderless printing"
        # set to borderless printing
        $PrintTicket.PageBorderless = 1
        $PrintQueue.Commit()
        $PrintQueue.Refresh()
        Write-Output "-------------------------"
        Write-Output "PageBorderless is currently set to $($PrintTicket.PageBorderless)"
        Write-Output "-------------------------"
    }
    else{
        Write-Output "Borderless printing capability NOT found"        
    }    
}
else{
    Write-Output "PageBorderlessCapability is null. Printer may not support it."
}
# example for duplexing since I couldn't test borderless printing
# https://learn.microsoft.com/en-us/dotnet/api/system.printing.duplexing?view=windowsdesktop-7.0
if ($PrintCapabilities.DuplexingCapability -ne $null){
    Write-Output "-------------------------"
    Write-Output "Duplex is currently set to $($PrintTicket.Duplexing)"
    Write-Output "-------------------------"
    if ($PrintCapabilities.DuplexingCapability.Contains("TwoSidedLongEdge")){
        Write-Output "Duplexing capability TwoSidedLonEdge found."
        Write-Output "Enabling duplex TwoSidedLonEdge"
        # change duplexing to "TwoSidedLonEdge"
        $PrintTicket.Duplexing = 3
        $PrintQueue.Commit()
        $PrintQueue.Refresh()
        Write-Output "-------------------------"
        Write-Output "Duplex is currently set to $($PrintTicket.Duplexing)"
        Write-Output "-------------------------"
    }
    else{
        Write-Output "Duplexing capability TwoSidedLonEdge NOT found."
    }
}

if (($PrintQueue.UserPrintTicket.PageBorderless -ne 1) -and $exitOnNotEnabled){
    Write-Output "Borderless Printing was not enabled..exiting"
    exit
}

if (($PrintQueue.UserPrintTicket.Duplexing -ne 3) -and $exitOnNotEnabled){
    Write-Output "Duplexing printing TwoSidedLonEdge was not enabled..exiting"
    exit
}

### do stuff you were doing to print ###



### change back setting if you wanted
# something like 
# $PrintTicket.PageBorderless = 0
# $PrintQueue.Commit()

Example Output

PageBorderlessCapability is null. Printer may not support it.
-------------------------
Duplex is currently set to OneSided
-------------------------
Duplexing capability TwoSidedLonEdge found.
Enabling duplex TwoSidedLonEdge
-------------------------
Duplex is currently set to TwoSidedLongEdge
-------------------------
Borderless Printing was not enabled..exiting
Note

Code will exit if the settings for PageBorderless or Duplexing were not able to be change. $exitOnNotEnabled = $true you can change that to $false so that doesn't happen. You could also just remove the duplexing parts since that example doesn't pertain to the setting you actually want to change.

"Classes within the System.Printing namespace are not supported for use within a Windows service or ASP.NET application or service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions"ref

Upvotes: 0

Related Questions