Sending file to print not working using System.Drawing.Printing - c#

I'm trying to send a file to print without opening it trough Adobe as suggested by several Answers here; instead, I'm using the PrintQueue library (from System.Drawing.Printing).
What I've accomplished so far:
I have the correct PrintQueue referenced as pq:
PrintQueue pq; //Assume it's correct. The way to get here it isn't easy and it is not needed for the question.
// Call AddJob
PrintSystemJobInfo myPrintJob = pq.AddJob();
// Write a Byte buffer to the JobStream and close the stream
Stream myStream = myPrintJob.JobStream;
Byte[] myByteBuffer = ObjectIHave.ToArray(); //Ignore the ObjectIhave, it actually is Linq object which is correct as well.
myStream.Write(myByteBuffer, 0, myByteBuffer.Length);
myStream.Close();
As I understood from the Microsoft Library it's correctly done but it is not working. Any ideas?
EDIT: Debugging the code I can see that something is being send to the printer but it seems the file is not sent.

You need to render your PDF to the printer. Calling the shell print verb on the file would be the ideal means to do that. If you insist on doing the low level rendering yourself then I recommend using a library like Ghostscript.NET and choose the mswinpr2 device as output.
The mswinpr2 device uses MS Windows printer drivers, and thus should work with any printer with device-independent bitmap (DIB) raster capabilities. The printer resolution cannot be selected directly using PostScript commands from Ghostscript: use the printer setup in the Control Panel instead.
See SendToPrinterSample.cs for example:
string printerName = "YourPrinterName";
string inputFile = #"E:\__test_data\test.pdf";
using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dPrinted");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOSAFER");
switches.Add("-dNumCopies=1");
switches.Add("-sDEVICE=mswinpr2");
switches.Add("-sOutputFile=%printer%" + printerName);
switches.Add("-f");
switches.Add(inputFile);
processor.StartProcessing(switches.ToArray(), null);
}
If the file has to be printed in both sides you just need to add:
switches.Add("-dDuplex");
switches.Add("-dTumble=0");

You can not just write PDF bytes to a print job. The printer doesn't know how to handle it. The RAW data you send to the printer must describe the document in a printer language specific to the printer. That's what the printer driver does.
You can not print a PDF by just sending it to the printer. You need some piece of software that renders the PDF and then sends the rendered image to the printer.
As the documentation states:
Use this method to write device specific information, to a spool file, that is not automatically included by the Microsoft Windows spooler.
I enhanced the important part of this information.

Related

Printing Excel file

xlWorkSheet.PrintOut();
This should work but according to the documentation, this is going to use the printer by default. Is it possible to give the user the ability to choose a printer like this:
In WinForms, I believe It's possible to achieve such a thing by using a PrintDialog like this:
var pd = new PrintDialog();
var settings = pd.PrinterSettings;
var name = settings.PrinterName
What's the equivalent for that in WPF? I don't see PrinterSettings/PrinterName
EDIT (more details):
I'm creating an excel file using Interop. The first code I posted will print the file using the default printer. I want from the user to be able to choose a printer. I realize there is ActivePrinter option but I will have to know the name of the printer in this case I believe.
What I want to do is make a printer dialog and get the Selected printer name and set it to ActivePrinter

Set page scaling in PJL

I have to write a functionality that takes a PDF-document and sends it to a printer with some PJL commands. So far so good, I take the document, convert it to Postscript, send the postscript file to the printer with the required commands and the printer prints the document.
Now to the actual problem: Most of the document that needs to be printed by our software are invoices, therefore they are carefully made, such that every element is precisely positioned, and if it's off by millimeters the printed document is invalid. When printing the document directly through Adobe or any pdf viewing software, I can select the actual size option and everything is fine. Although if I print it via C# and PJL the document has different margins depending on the printer it has been printed on. Until now we used pdfprinting.net, and that option could be selected through pdfPrint.Scale = PdfPrint.ScaleTypes.None, but how can I do it via PJL?
// This are all the commands that I've tried, none of which achieved what I need
var parameters = new Dictionary<string, string>
{
{ "SET USERNAME",userName},
//{"SET PAPER", "A4" },
//{"SET MEDIATYPE", "PAPER" },
//{"SET TOPMARGIN", "TM6MM" },
//{"SET PRINTAREA", "INKEDAREA" },
{"SET MARGINS", "SMALLER" },
//{ "ENTER LANGUAGE","PDF"},
{ "ENTER LANGUAGE","POSTSCRIPT"},
};
var documentText = "\x1B%-12345X#PJL JOB NAME=" + jobName + " DISPLAY=" + jobDisplay;
foreach (var parameter in parameters)
{
documentText += "\r\n#PJL " + parameter.Key + "=" + parameter.Value;
}
documentText += "\r\n";
documentText += pdfString;
documentText += "\r\n\x0D\x0A\x1B%-12345X\r\n";
RawPrint(printerAddress, documentText, documentName);
// RawPrint() calls the printer methods found in 'winspool.drv', imported via 'DllImport'
Checking the PJL Reference Manual (Edition 12, which is the latest I have seen) there is simply no way to scale the page content in PJL.
Even if there were, I'd be surprised if it carried over to the PostScript (as opposed to PCL) interpreter environment, because PostScript has a rich feature set to handle this sort of setup. So basically you're going to need to get the PostScript correct.
Now, when you take a PDF file and produce PostScript from it, you are almost certainly producing generic PostScript; its device-neutral so it doesn't take account of aspects of the physical device.
Most obviously this will be things like hardware margins and unprintable areas. Many devices have limitations on which parts of the media they can print on, due to the paper handling. These will, of course, be different between different printers.
Of course, when you print from the operating system, the printer device driver knows what the printable area of the media is (because its the specific driver for the printer in question), and so it can arrange for the content to be scaled to the actual media.
Ghostscript certainly can produce PostScript (using the ps2write device) which is suitably scaled and translated for a given printer, provided you know what the characteristics of that printer are. In fact if the printer is sophisticated enough, the PostScript program may be able to interrogate the printer to retrieve some of these characteristics (ImagingBBox, PageOffset, Margins, ImageShift) and its then possible to write a PostScript program to dynamically resize the content of the page, based on these values (the PostScript produced by ps2write does not do this...).

Print to PDF with Microsoft Print to PDF printer

I try to print a ms project file to pdf without any additional action needed.
I have tried several solutions without success.
PrintDocument doc = new PrintDocument()
{
//DocumentName = safeDir + fileName,
PrinterSettings = new PrinterSettings()
{
// set the printer to 'Microsoft Print to PDF'
PrinterName = "Microsoft Print to PDF",
// tell the object this document will print to file
PrintToFile = true,
// set the filename to whatever you like (full path)
PrintFileName = safeDir + fileName,
}
};
doc.Print();
If i try this approach like showed here, I get an empty pdf file.
Manually printing to PDF works fine.
Any suggestions to solve this problem?
My Spidey Senses tells me this is most likely caused by commas in the file name
This is a known bug when printing to PDF. Use a different driver or
don't put a comma in the file name
Note : Its not only from code, its in general in certain situations.
Disclaimer : this is a complete and utter guess
Check these other links out
Bug in "Print to PDF" and "Print to XPS" in Windows 10? comma in filename results in zero-byte file
Microsoft Print to PDF not working
Found a bug in Microsoft Print to PDF
Microsoft Print to PDF in Windows 10

Printing from Datecs FML 10KL

I am using .NET CF and my task is to print fiscal and non-fiscal receipt.
So I need to connect to the FML 10 KL via bluetooth.
I am using SerialPort to do this, but after sending commands nothing happens.
I tried sending the commands like this :
byte[] buf = new byte[218];
using (StreamWriter writer = new StreamWriter(inPort.BaseStream))
{
writer.Write(buf);
//inPort.NewLine = "\n";
//var msg = inPort.ReadLine();
}
I populate "buf" with my command.
After that I try to read the responce but everytime I get timeout.Also I tried to "write" with text and not byte array, but I get the same result.
If anyone can give me some advice that would be great.
Most serial devices including Bluetooth SPP and Socket controlled devices do not support Unicode. If you have a string, you need to use Encoding ASCII (or UTF8) getBytes to get a byte arry suitable for the serial or direct socket connection. If you do not care for this, you may get a byte sequence of {0x00, 0x41} (Unicode) for an 'A' instead of the needed {0x41} only.
If you try to print something, verify that the code you send is valid by writing the data to a file and send the file as it is using a terminal application (former HyperTerminal).
Most printers support a Dump mode. Verify that the code you build is transmitted un-altered to the printer by using the dump mode and compare with the validated code that you used to print.
The Operating System and the target device may use a buffer. Ensure the buffer is flushed and then close the Stream before disconnecting.
With the Serial Port class ensure the device and the class use the same parameters, ie both 8Bit etc. For Bluetooth SPP the baud rate is adopted, you may use 115200 or 57600 without failing.
I found a Class that supports the Datecs Fiscal Printing Protocol: https://github.com/wqweto/UcsFiscalPrinters/blob/master/Samples/Demo1/Program.cs you should probably use this or look at how the class does print on the Datecs.
I figured out my problem.It was the connection to the mobile printer.
I am connecting and writing like this:
SerialPort inport = new SerialPort("COM5", 115200, Parity.None, 8,
StopBits.One);
inport.Write(buf, 0, buf.Length);
Thread.Sleep(1000);
I need to use Thread.Sleep because the buffer is getting full and some of data is not getting printed.

How to convert a png file to .GRF file used for zebra printer

I use Zebraprinter for printing the labels. My printer is 203dpi. For last couple of days i was searching in internet and i found there are Zebraprint utilities.. to convert to DFR format.. which sucks.. they are not fully explaining how to do this.. They just says convert to ~DG format. any print it, which is not happening!!
Rather I would like to convert a png file to a .GRF file and send to the printer for printing.. IS there any deadly available free software in internet which does my needs,
Also, i tired to develop a software which does the job for printing the letters.. which is wiring fine. i don't know how to print pictures using this printer.
I need to convert this image https://imageshack.com/i/pb0BArbep to .GRF format. How can i do all this under a single button press.. Any helps..
Thanks a lot.
Code snippet:-
private void button2_Click(object sender, EventArgs e)
{
string s = Print();
PrintFactory.sendTextToLPT1(s);
}
private string Print()
{
string s = "";
s += "^XA^LH"+ text.textbox + ".GRF,1,1^FS";
s += "^FO250,294^FD^FS";
s += "^XZ";
return s;
}
It's been a month since this was asked, so I don't know if an answer is still needed or not, but I'll have a go at it. I've actually been doing a lot of research on ZPL lately, (one of the reasons I came across this question), and I had to do something similar. With a 203 dpi printer as well, actually. I'm not sure how to convert a PNG to GRF, but I was able to print out a graphic using just a PNG:
^XA
^MNY
^LL203
~DYE:{name},P,P,{file size},,{data}
^XZ
The ^MN has to do with Media Tracking, and you may have to change it a bit to suit your needs, depending on the label. Same thing with ^LL, which specifies the label length. For an 8 dots/mm (203 dpi), the value you use as an argument is calculated by 203.2 * length of label in inches. After that, there's a few values to plug into ~DY (Download graphics, page 112 on the manual), the first of which is the name you want to use to reference the file. I didn't add a file extension, as the printer seemed to do that for me, since I specified it was a PNG in the arguments. The second is the size, in bytes, of the PNG file. And lastly, the actual data from the file in the form of ASCII hex. Now with the file being saved on the printer, I was then able to print the graphic in a script using:
^IME:{name}.PNG
^FS
Note: After uploading the file to the printer, I was able to confirm it did save as a PNG file by connecting to the printer VIA IP in a browser and going to "Directory Listing". I'm not sure if all those printers have this feature, but the one I used did. If it does, you can use this to confirm that the file properly uploaded. (It should be in Onboard Flash)
Hope this helps!
The manual I used is here.
I also came across numerous other StackOverflow questions that helped out a bit, and a few threads on other forums. One question that was also in C# that helped me quite a bit can be found here.

Categories