Mechanics of printing - c#

I am changing default print settings using winspool.drv before printing. Do the altered default printing settings get embedded with the print job when it is printed? Or are they saved somewhere else? If I change a setting, what happens when the print job is sent to the printer? What information goes with the print job? Am I even asking the right questions? I am batch printing a lot of files and changing settings between pages in each job.
Edit:
My understanding is this:
I make changes to default printer settings
Print document, default printer settings are embedded in spool file and sent to printer
Printer prints using spool file
Is my understanding is correct? Do I need to wait until the print job is over before changing the printer settings?

Changing default settings for a simple task is usually a no-go and should never be done. If your program crashes or does something wrong, the user's settings are lost, which might even get pretty expensive considering high quality print settings, photo paper, etc.
You should change the settings per job using the provided API (if possible) to only affect the current/to be printed document.
Once the print job is done/spooled (i.e. it's only waiting for the printer to start or getting online), updated settings no longer affect the document.

Related

Printer spooler api number of copies

I really could use some help, this is a question that alot of people are asking on the internet. I have different setups, tried different ways of testing, it's very frustrating.
First setup:
local printers
local running code
print from pdf or notepad: SUCCES (number of copies are 2)
print from word: FAILED (numberof copies is 1)
Second setup:
local printers that are shared
local running code
print from other computer to shared printers
number of copies isalways 1
Sowhat is everyone missing? What happens that some fields are missing while the printer still should know what to print? What does word that also happen when you print from another computer? Can someone tell me why somethings in windows are so terrible? Everythingshould pass the spooler, sowhy isthedata wrong?
Kinds regards!
A printer prints sheets and pages, so copies is converted to pages at some stage.
The notification data you get depends on both the application that is printing and the system and driver components handling the spooling and rendering. In my experience the data cannot be relied on, and the best data is obtained by parsing the spool file. This may or may not contain the number of copies.
Word has had the "copies problem" for a long time. There was a patch to supposedly fix this, but another opinion is that it's because it uses an unusual way of printing. I'll quote some of the link contents here:
With the infamous Word Copy Count bug… the dmCopies filed is 1 in the
SHD. The correct value is found in the DEVMODE record in the SPL file
(if it's an EMF spool).
The only other way i found was to monitor the PrintedPages field of
the JOB_INFO_2 structure, when the job has been sent to the printer,
and see if it is a multiple of TotalPages.
[...]
What happens is not a Word bug, but a Windows bug. Word calls startDoc
always with copies set to 1. After that calls DocumentProperties and
makes the change in dmCopies and calls ResetDC to make the update. It
is a strange way of printing but not wrong. The problem is that the
shd file and printer_info is not updated with this information, just
keeps the Devmode info set on the StartDoc call.
But the call to the ResetDC generating a new DevMode is kept on the
SPL file. You can get that info too if you hook DocumentProperties
API calls.
Thank you for the answer. Is there a way of catching the document properties when they change?
The JOB_INFO_2 structure does have the same total_pages as pages_printed. So that is not a solution.
The SPL File does contain the QTY for the printer i tested on which is correct. BUT we tested on a lot of printers and we see the QTY is not Always set. So not a 100% solution. But already a good fallback.
So if i can catch the document properties without calling the SPL file that would be wonderful because i guess that's where everything is correct. Isn't it?

How to Run a Program and Get its Output

In C#, I want to run a program and wait for the user to exit in order to get what was saved. For example, I want to run Photoshop or MSpaint, wait for the user to finish editing and, after saving, to get the file (jpg, png, etc) or at least the path of the file.
I have been unable to determine how to go about this.
It's probably going to depend heavily on the program you wish to use. If you use a program with an API to make calls and get feedback, then maybe you can do this. For Photoshop and MSPaint, I'm a bit skeptical they'd have this feature. In the end, what you might wish to do, is keep some kind of input box open and await the user to paste the path themselves. Either that or find such a program with the API you're looking for or make your very own image editor.

Using C# to detect a printer's power status

I did a lot of search and it comes with nothing.Such as below:
c# check printer status
how do i check if a printer is installed and ready using C#?
I tried all the code I found in here but none of them can tell the status of a printer's power is on or off.
The printer is always plugged in and sometimes it's powered off, so I need to make sure it's powered on and then do the print job.
Real need some help here!
question update
the windows still send the print job to print spool when my printer is off, I don't need this, because my client sometimes will deliberately turn off the printer to avoid print something that he don't need. but windows still send it to spool, when my client turn on the printer again, it prints the thing that exactly he want to avoid.
The legacy code uses kernel32.dll's CreateFile function to open LPT1 as a file and directly write string to it to accomplish then printing function. It got no way to know the status of the printer, it just write string to the parallel port. so when the printer is off, the write function got no return, hence the following code after that will never get executed.
hopefully u can understand what I am trying to do here. I want to avoid the situation to print when the printer is off.

PrintTicket scopes (default, user, job, document, page etc)

I'm completing the construction of a webservice that builds and prints out XPS documents sending them to various print queues on various print servers. The webservice runs in 2 modes depending on site deployment. The first is using the app pool identity account as the print user, the second mode uses user impersonation for "follow me" type printers, so that the user is registered against the print job. This all works fine.
I have to target particular trays on the printqueues and set various other parameters for each job, so I've generated printickets adding the tray namespace to the xml and this also appears to work.
My concern is this (and is where I need some hand holding), because I'm doing all this STA threaded server side, say Bob running as Bob prints 200 documents of a mix (A4, A5, envelope) and the tickets switch off say duplexing on the printer and my app pool identity account is running say 20 printing threads with multiple documents of various target trays with various parameters at once, am I going to get any issues or am I going to knacker the default printer queue settings?
According to MS, MergeAndValidatePrintTicket can be scoped at various levels (I'll settle for job level) but I just wonder if anyone with experience of this scenario can validate this as true and if there any gotchas out there, because this whole .Net printing malarkey seems to be riddled with them.
'lil tip for anyone doing this. If your target printers are simple with say only 3 trays of different sizes, just set the media size (ISOA4 or whatever) in the ticket and set the input bin to unknown and the printer will work it out. Unfortunately, the printers I'm targeting have about 7 bins, so I have to target the exact tray.
Thanks for reading.
Edited to show solution
Jon...this is the relevant section...
PrintTicket ptclone = pqTarget.UserPrintTicket*.Clone();* <--remove Clone()
//my method below for specifying the tray to use for the job and other settings. poj is my printJob class
PrintTicket pt = GetPrintTicketForJob(ptclone, poj.trayMediaSize, poj.trayNameSpace, poj.trayUri);
ValidationResult vr= pqTarget.MergeAndValidatePrintTicket(ptclone, pt, PrintTicketScope.JobScope);
pqTarget.UserPrintTicket = vr.ValidatedPrintTicket; <--remove this
//pqTarget.Commit() // the print server in localPrintServer mode didn't like that under user impersonation
PrintSystemJobInfo pj = pqTarget.AddJob(poj.id, poj.fileName, false) <--don't do this
I tried using the .Net 4.5 overload that has the print ticket in it, but the server in localPrintServer mode didn't understand the method even though the server has .Net 4.5 on it and which was...
PrintSystemJobInfo pj = pqTarget.AddJob(poj.id.ToString(), poj.fileName, false, vr.ValidatedPrintTicket) <--do this instead .Net 4.5 and it all works
Everything works fine with the following exceptions....
1) on the mfds which are controlled by 3rd party software and use user impersonation, the default duplex setting stays active for the first document printed, after that, it's fine. It works OK for the Lexmarks (app pool idenity used). Trays are properly assigned on both types as are the other settings.
2) Dates and numbers (which are inserted as strings into the documents) and appear OK in the XPS viewer get reformatted as san serif even if the paragraph they are in is in say Times New Roman which is baffling.
Can you spot any screw ups?
regards
Neil

Modifying a printers default settings from C#

Here's my situation:
I'm developing a C# add-in for a 3rd party program
This program (Revit) uses its own printing methods and exposes them through its API
I am writing a printing utility that uses these methods to print to various locations, including a PDF printer
I'm using PDF995 as a printer and modifying its .ini file to automate it.
Basically I'm calling the print method in the API which prints the active drawing to a specified printer.
My problem is that on PDF995, if you go to printing preferences in Windows the orientation is by default set to 'portrait'. I need landscape. These settings seem to override anything I set in the Revit API, so I need a way of changing the windows settings.
I've tried this code:
PrintDocument printDocument = new PrintDocument();
printDocument.PrinterSettings.PrinterName = "PDF995";
printDocument.DefaultPageSettings.Landscape = true;
before calling the print function in the API, but it makes no difference. I can't see a way to edit the pdf995 ini to set these settings either. It's a windows setting that I need to override.
I've seen some C++ code on the net I can call to do things with printers but can't find an example of changing the default settings.
Can anyone point me in the right direction?
I've had good success using these components:
http://www.merrioncomputing.com/Download/PrintQueueWatch/index.htm
http://printqueuewatch.codeplex.com/Wiki/View.aspx?title=Home
This collection makes available all sorts of useful printing options. It's mainly focused on monitoring a print queue, but from memory there are options available to change printer settings and job properties.
I think many of the settings from a use of Autodesk.Revit.DB.PrintManager are "placeholders", but that if the printer is controlling these settings, the value ported to it by Revit is ignored. I have tried setting .PrintToFileName with a full path, but making a PDF in BlueBeam still sends the file to MyDocuments, from where I have to copy it. Have you tried copying your PDF995 to PDF995X (for example) and modifying it to have a default of Landscape (while PDF995 retains the default of Portrait)? I have used this method in the past when a printer insists on using stored defaults instead of those requested.

Categories