Как я могу отправить файл документа на принтер и распечатать его?
Вот основная предпосылка:
Мой пользователь нажимает некоторые вещицы, и PDF-файл выплевывается на его рабочий стол. Можно ли как-нибудь отправить этот файл в очередь принтера и распечатать его на локально подключенном принтере?
string filePath = "filepathisalreadysethere";
SendToPrinter(filePath); //Something like this?
Он сделает этот процесс много раз. Для каждого ученика в классе он должен распечатать небольшую табель успеваемости. Поэтому я создаю PDF для каждого студента, и я хотел бы автоматизировать процесс печати вместо того, чтобы пользователь генерировал PDF, печатал, генерировал PDF, печатал, генерировал PDF, печатал.
Любые предложения о том, как подойти к этому? Я работаю на Windows XP с Windows Forms .NET 4.
Я нашел этот вопрос Stackru, где принятый ответ предполагает:
Создав файлы, вы можете распечатать их через командную строку (для этого вы можете использовать класс Command, находящийся в пространстве имен System.Diagnostics)
Как бы я это сделал?
11 ответов
Вы можете указать Acrobat Reader напечатать файл, используя (как уже упоминалось здесь) глагол "печать". После этого вам также необходимо будет программно закрыть Acrobat Reader:
private void SendToPrinter()
{
ProcessStartInfo info = new ProcessStartInfo();
info.Verb = "print";
info.FileName = @"c:\output.pdf";
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = info;
p.Start();
p.WaitForInputIdle();
System.Threading.Thread.Sleep(3000);
if (false == p.CloseMainWindow())
p.Kill();
}
При этом откроется Acrobat Reader и отправит PDF-файл на принтер по умолчанию, а затем через три секунды завершит работу Acrobat.
Если вы хотите поставлять другие продукты вместе с вашим приложением, вы можете использовать GhostScript (бесплатно) или принтер PDF для командной строки, например http://www.commandlinepdf.com/ (коммерческий).
Примечание. Пример кода открывает PDF-файл в текущем приложении, зарегистрированном для печати PDF-файлов, что на большинстве компьютеров является программой Adobe Acrobat Reader. Однако, возможно, что они используют другой просмотрщик PDF, такой как Foxit ( http://www.foxitsoftware.com/pdf/reader/). Пример кода все еще должен работать, хотя.
Добавление нового ответа на этот вопрос, так как вопрос печати PDF в.net существует давно, и большинство ответов предшествует библиотеке Google Pdfium, в которой теперь есть оболочка.net. Что касается меня, я сам исследовал эту проблему и все время терял сознание, пытаясь найти хакерские решения, такие как порождение Acrobat или других программ для чтения PDF-файлов, или наткнуться на коммерческие библиотеки, которые дороги и не очень совместимы с условиями лицензирования. Но библиотека Google Pdfium и оболочка PdfiumViewer.net с открытым исходным кодом, поэтому являются отличным решением для многих разработчиков, включая меня. PdfiumViewer лицензируется под лицензией Apache 2.0.
Вы можете получить пакет NuGet здесь:
https://www.nuget.org/packages/PdfiumViewer/
и вы можете найти исходный код здесь:
https://github.com/pvginkel/PdfiumViewer
Вот простой код, который будет молча печатать любое количество копий файла PDF из его имени. Вы также можете загружать PDF-файлы из потока (как мы обычно это делаем), и вы можете легко понять это, взглянув на код или примеры. Существует также вид файла WinForm PDF, так что вы также можете визуализировать файлы PDF в виде или сделать предварительный просмотр на них. Для нас мне просто нужен был способ напечатать файл PDF на определенный принтер по требованию.
public bool PrintPDF(
string printer,
string paperName,
string filename,
int copies)
{
try {
// Create the printer settings for our printer
var printerSettings = new PrinterSettings {
PrinterName = printer,
Copies = (short)copies,
};
// Create our page settings for the paper size selected
var pageSettings = new PageSettings(printerSettings) {
Margins = new Margins(0, 0, 0, 0),
};
foreach (PaperSize paperSize in printerSettings.PaperSizes) {
if (paperSize.PaperName == paperName) {
pageSettings.PaperSize = paperSize;
break;
}
}
// Now print the PDF document
using (var document = PdfDocument.Load(filename)) {
using (var printDocument = document.CreatePrintDocument()) {
printDocument.PrinterSettings = printerSettings;
printDocument.DefaultPageSettings = pageSettings;
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
}
}
return true;
} catch {
return false;
}
}
Я знаю, что тег говорит Windows Forms
... но, если кто-то заинтересован в WPF
метод применения, System.Printing
работает как шарм.
var file = File.ReadAllBytes(pdfFilePath);
var printQueue = LocalPrintServer.GetDefaultPrintQueue();
using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
{
stream.Write(file, 0, file.Length);
}
Просто не забудьте включить System.Printing
ссылка, если она еще не включена. Теперь этот метод не очень хорошо ASP.NET
или же Windows Service
, Не следует использовать с Windows Forms
как оно System.Drawing.Printing
, У меня нет ни одной проблемы с моей печатью PDF с использованием приведенного выше кода.
Однако следует отметить, что если ваш принтер не поддерживает Direct Print for PDF, то вам не повезло с этим методом.
Следующий фрагмент кода представляет собой адаптацию кода Кендалла Беннетта для печати PDF-файлов с использованием библиотеки PdfiumViewer. Основное отличие состоит в том, что используется поток, а не файл.
public bool PrintPDF(
string printer,
string paperName,
int copies, Stream stream)
{
try
{
// Create the printer settings for our printer
var printerSettings = new PrinterSettings
{
PrinterName = printer,
Copies = (short)copies,
};
// Create our page settings for the paper size selected
var pageSettings = new PageSettings(printerSettings)
{
Margins = new Margins(0, 0, 0, 0),
};
foreach (PaperSize paperSize in printerSettings.PaperSizes)
{
if (paperSize.PaperName == paperName)
{
pageSettings.PaperSize = paperSize;
break;
}
}
// Now print the PDF document
using (var document = PdfiumViewer.PdfDocument.Load(stream))
{
using (var printDocument = document.CreatePrintDocument())
{
printDocument.PrinterSettings = printerSettings;
printDocument.DefaultPageSettings = pageSettings;
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
}
}
return true;
}
catch (System.Exception e)
{
return false;
}
}
В моем случае я генерирую PDF-файл, используя библиотеку PdfSharp, а затем сохраняю документ в Stream следующим образом:
PdfDocument pdf = PdfGenerator.GeneratePdf(printRequest.html, PageSize.A4);
pdf.AddPage();
MemoryStream stream = new MemoryStream();
pdf.Save(stream);
MemoryStream stream2 = new MemoryStream(stream.ToArray());
Одна вещь, на которую я хотел бы обратить внимание, которая может быть полезна другим разработчикам, заключается в том, что мне пришлось установить 32-битную версию ddf pdfuim native для того, чтобы печать работала, даже несмотря на то, что я использую 64-битную Windows 10. Я установил следующие два пакета NuGet с помощью диспетчера пакетов NuGet в Visual Studio:
- PdfiumViewer
- PdfiumViewer.Native.x86.v8-РФ
Простой способ:
var pi=new ProcessStartInfo("C:\file.docx");
pi.UseShellExecute = true;
pi.Verb = "print";
var process = System.Diagnostics.Process.Start(pi);
Это слегка измененное решение. Процесс будет убит, если он простаивал не менее 1 секунды. Возможно, вам следует добавить время X секунд и вызвать функцию из отдельного потока.
private void SendToPrinter()
{
ProcessStartInfo info = new ProcessStartInfo();
info.Verb = "print";
info.FileName = @"c:\output.pdf";
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = info;
p.Start();
long ticks = -1;
while (ticks != p.TotalProcessorTime.Ticks)
{
ticks = p.TotalProcessorTime.Ticks;
Thread.Sleep(1000);
}
if (false == p.CloseMainWindow())
p.Kill();
}
System.Diagnostics.Process.Start может использоваться для печати документа. Установите для UseShellExecute значение True, а для глагола - "печать".
Я знаю, что Эдвин ответил на это выше, но он печатает только один документ. Я использую этот код для печати всех файлов из данного каталога.
public void PrintAllFiles()
{
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
info.Verb = "print";
System.Diagnostics.Process p = new System.Diagnostics.Process();
//Load Files in Selected Folder
string[] allFiles = System.IO.Directory.GetFiles(Directory);
foreach (string file in allFiles)
{
info.FileName = @file;
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p.StartInfo = info;
p.Start();
}
//p.Kill(); Can Create A Kill Statement Here... but I found I don't need one
MessageBox.Show("Print Complete");
}
По сути, он циклически перебирает каждый файл в заданной переменной каталога Directory - > для меня это был @"C:\Users\Owner\Documents\SalesVaultTesting\" и распечатывает эти файлы на вашем принтере по умолчанию.
Вы можете попробовать с GhostScript, как в этом посте:
Это поздний ответ, но вы также можете использовать метод File.Copy в пространстве имен System.IO top, чтобы отправить файл на принтер:
System.IO.File.Copy(filename, printerName);
Это отлично работает
Вы можете использовать метод DevExpress PdfDocumentProcessor.Print (PdfPrinterSettings).
public void Print(string pdfFilePath)
{
if (!File.Exists(pdfFilePath))
throw new FileNotFoundException("No such file exists!", pdfFilePath);
// Create a Pdf Document Processor instance and load a PDF into it.
PdfDocumentProcessor documentProcessor = new PdfDocumentProcessor();
documentProcessor.LoadDocument(pdfFilePath);
if (documentProcessor != null)
{
PrinterSettings settings = new PrinterSettings();
//var paperSizes = settings.PaperSizes.Cast<PaperSize>().ToList();
//PaperSize sizeCustom = paperSizes.FirstOrDefault<PaperSize>(size => size.Kind == PaperKind.Custom); // finding paper size
settings.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 600);
// Print pdf
documentProcessor.Print(settings);
}
}
public static void PrintFileToDefaultPrinter(string FilePath)
{
try
{
var file = File.ReadAllBytes(FilePath);
var printQueue = LocalPrintServer.GetDefaultPrintQueue();
using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
{
stream.Write(file, 0, file.Length);
}
}
catch (Exception)
{
throw;
}
}