johnstaveley
johnstaveley

Reputation: 1499

Save as PDF using Selenium and Chrome

I am trying to Save as pdf using the print dialog, a web page where I have already logged on using Selenium and Headless Chrome (v81). All the articles state I should be able to print/save the document as pdf using kiosk mode where the print to pdf happens automatically so the preview dialog is surpressed e.g.

I cannot get Chrome to default to saving as a PDF when using Selenium Selenium Chrome save as pdf change download folder

So far I have the following code:

ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("--headless", "--disable-infobars", "--disable-extensions", "--test-type", "--allow-insecure-localhost", "--ignore-certificate-errors", "--ignore-ssl-errors=yes", "--disable-gpu", "--kiosk-printing", "--allow-running-insecure-content"); 
chromeOptions.AcceptInsecureCertificates = acceptInsecureCertificates;
chromeOptions.UnhandledPromptBehavior = UnhandledPromptBehavior.Ignore;
chromeOptions.AddUserProfilePreference("print.always_print_silent", true);
chromeOptions.AddUserProfilePreference("download.default_directory", @"C:\Temp");
chromeOptions.AddUserProfilePreference("savefile.default_directory", @"C:\Temp");
chromeOptions.AddUserProfilePreference("download.prompt_for_download", false);
chromeOptions.AddUserProfilePreference("printing.default_destination_selection_rules", "{\"kind\": \"local\", \"namePattern\": \"Save as PDF\"}");
chromeOptions.AddUserProfilePreference("printing.print_preview_sticky_settings.appState", "{\"recentDestinations\": [{\"id\": \"Save as PDF\", \"origin\": \"local\", \"account\": \"\" }],\"version\":2,\"isGcpPromoDismissed\":false,\"selectedDestinationId\":\"Save as PDF\"}");                    
webDriver = new ChromeDriver(ChromeDriverService.CreateDefaultService(), chromeOptions, TimeSpan.FromMinutes(timeoutMinutes));

Then I print the page using this:

var driver = FeatureContext.Current.GetWebDriver();
driver.ExecuteJavaScript("window.print();");

But I get the print preview dialog, always and my default printer is set and not Save as PDF.

I would use the chrome command line however for the fact I need to be logged on to the site. What is wrong with the code above?

Upvotes: 5

Views: 3560

Answers (1)

Diego Montania
Diego Montania

Reputation: 346

Update 20/05/2022 : With Selenium 4, now is possible "Save to PDF" more easly. With one condition : Your application needs to run in headless mode if not, the Selenium will throw a exception PrintToPDF is only supported in headless mode. But If some reason, you cant run in headless mode, my previous reply still working.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.IO;

private static ChromeOptions _chromeOptions;
private static WebDriver _driver;
private static string fileName = "MyPrint";
private static string printFinalPath = Path.Combine($@"C:\Users\{Environment.UserName}\Downloads", string.Concat(fileName, ".pdf"));

static void Main(string[] args)
{
     _chromeOptions = new ChromeOptions();
     _chromeOptions.AddArguments("headless"); //your chrome driver needs run in headless!

     //creating webdriver
     _driver = new ChromeDriver(_chromeOptions);

     //go to the website
     _driver.Navigate().GoToUrl("https://www.google.com/");

     //defining configurations for de printing
     PrintOptions printOptions = new PrintOptions
     {
          Orientation = PrintOrientation.Portrait
     };

     //printing...
     PrintDocument printDocument = _driver.Print(printOptions);

     //saving the file
     printDocument.SaveAsFile(printFinalPath);
}

Original reply Selenium 4, has some new features like, "Executing Command" via ChromeDevTools. With this feature, we can call something like "PdfAsync" directly from chrome (like Puppersharp, but using selenium). But unfortunately, we don't have this option enable yet in c#. 'Print-pdf' will be more easy in the future.

However, using selenium 3.141.0, doing some searching in topics from web, I solved this problem with help of your code. I have some problems to convert strings C# to json object.

Use Logging in chrome, to help.

Update 27/07/2021 : Unfortunately, using argument "headless" the "window.print()" will not work.

My final code is :

public class Program
...

static void Main(string[] args)
{
     private static IWebDriver _driver;
     private static ChromeOptions _chromeOptions;
     private static ChromeDriverService _chromeService;
     private static string pathLogChromeDriver = "chrome_driver_logs";
     private static string nameFileLog = "chromedriver.log";

     //creating chrome service, to logging
     _chromeService = ChromeDriverService.CreateDefaultService(".");

     //using to see the modifications in google chrome arguments
     _chromeService.LogPath = Path.Combine(Directory.GetCurrentDirectory(), pathLogChromeDriver, nameFileLog); 
     _chromeService.EnableVerboseLogging = true;

     //creating chromeOptions, to set the profile preferences
     _chromeOptions = new ChromeOptions();

     //using Dictionary to pass parameter name (string) and json object to AddUserProfilePreference.
     Dictionary<string, object> prefs  = new Dictionary<string, object>();
     prefs.Add("downloadFile", "{\"recentDestinations\": [{\"id\": \"Save as PDF\", \"origin\": \"local\", \"account\": \"\" }],\"version\":2,\"isGcpPromoDismissed\":false,\"selectedDestinationId\":\"Save as PDF\"}");
     prefs.Add("pathFinalFile", "C:\\Users\\" + Environment.UserName + "\\Downloads\\");

     //using the dictionary values to set the parameters
     _chromeOptions.AddUserProfilePreference("printing.print_preview_sticky_settings.appState", prefs["downloadFile"])
     _chromeOptions.AddUserProfilePreference("savefile.default_directory", prefs["pathFinalFile"]); 

     //disable 'chrome is being controlled by automated test software' bar
     _chromeOptions.AddUserProfilePreference("useAutomationExtension", false);
     _chromeOptions.AddExcludedArgument("enable-automation");

     //using --kiosk-printing to enable "silent printing"
     _chromeOptions.AddArgument("--kiosk-printing");

     //creating webdriver
     _driver = new ChromeDriver(_chromeService, _chromeOptions);
     _driver.Navigate().GoToUrl("https://applitools.com/blog/selenium-4-chrome-devtools/");
     _driver.Manage().Window.Maximize();

     //run javascript to print
     _driver.ExecuteJavaScript("window.print();");

     //is done!
}

If window "Save As" still open, some argument is incorrect.

Upvotes: 4

Related Questions