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
Related
I am trying to download a web page as pdf using edgewebdriver and selenium. Now, the edge is configured to a OneNote(Desktop) as seen in the image
I want to change the dropdown value in the dialog before clicking on the print button.
This is the constructor code where I am initializing the driver
public Driver(bool headLess = true)
{
var driverPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Driver");
var chromeDriverService = EdgeDriverService.CreateChromiumService(driverPath);
chromeDriverService.HideCommandPromptWindow = true;
var edgeOptions = new EdgeOptions();
edgeOptions.UseChromium = true;
var appState = new AppState()
{
recentDestinations = new List<RecentDestination>()
{
new RecentDestination(){ id = "Save as PDF", origin ="local", account = ""}
},
selectedDestinationId = "Save as PDF",
version = 2
};
edgeOptions.AddUserProfilePreference("printing.print_preview_sticky_settings", appState);
edgeOptions.AddArguments("kiosk-printing");
if (headLess)
{
edgeOptions.AddArgument("headless");
}
this._driver = new EdgeDriver(chromeDriverService, edgeOptions);
}
I have referred the following link
Chrome prefs list
I am totally stuck and can't find any solution to the problem. Every time "Print" dialog comes but the it tries to save to OneNode(Desktop).
No guarantee, but with One Note uninstalled my Edge Save as is PDF (not any of several PDF printers Inc MS) HOWEVER see my additional OneNote settings below.
Who added One Note is not really material but if this for controlling other users just beware fixing it for you alone, will not necessarily fix it for those others. (However user preference here, should not be allowed to override other users.)
Windows printing has a reliance on fall back defaults, and if Your default Printer is One Note then many Windows Apps will be told its THE Printer and its CURRENT DEFAULT page size is paramount.
If you have no other printers then One Note is the only one
You share your computer with someone else and they set it!
You share your computer With Windows 10 and it sets it for you!!
Just to compound insult to injury Windows 10 can be set to keep changing the default behind your back. So For stability hunt down Let Windows Manage Me and ensure that is off.
Then ensure the default printer is Say Microsoft Print to PDF
AND not essential but ensure default page layout is your preferred portrait or landscape for future use, ideally reboot the machine to ensure those defaults pervade through the system. For greater control on a use by use basis you need to use PrintUI.dll commands to store variable sets of preferences.
OneNote is a bundled MS component of Office and you have 3 suggested options:-
1. Just uninstall OneNote Printer (my GoTo solution, along with 2 as I already used up 3)
When you install Microsoft Office, OneNote is set as the default printer for most print jobs.
Use Win Key + X then N (for settiNgs) then pick devices or key in PR Enter
Pick Printers and Scanners, Select OneNote (It should expand) then Select Remove device OR
2. Remove OneNote from Start-up (also a favourite)
Use Win Key + X then T (for Task Manager) Enter and Pick middle start-Up tab If you see One note Enabled set it to Disabled and reboot. If that does not work use option 1
This "Disables" OneNote hogging resources at Start-up. IF you want to run OneNote, you must pick it manually in Start, or use a shortcut.
3. Remove OneNote Permanently (Not so easy as it can repeatedly reinstall)
Use Control Panel\All Control Panel Items\Programs and Features
Find Office and CHANGE (or in my case uninstall) Features should include Microsoft Office OneNote which you can select and SWITCH to Not Available
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?
I am using the Windows API Code Pack for Microsoft .NET Framework to try out of some of the new UI features of the Win7 taskbar. I am coding in C#.
I have a question regarding jumplists. All of the sample code provided assumes that the entries on the jump list are used to call out to run a particular application or open a document, e.g. a text document in a MRU list or run mspaint.exe.
I would like to implement some items which allow me to set state in my own application (i.e. the app which is interacting with the taskbar). MSN Messenger does this, for example, when you can set your status (Busy, Offline etc.).
Try as I might, I cannot create a JUmpListItem or JumpListLink to behave in this way - it treats them as applications or documents.
Does anyone have any samples of how to create an item which raises an event in the same application that created it? I am sure it is simple but I am being very daft.
Many thanks for your help.
I believe what you'd want to do is to call your application with a special set of flags (i.e. launch the executable with certain arguments). At application start up, you'd check to see what flags are set, then send a message to the main instance of the application and then exit out of the new instance.
Using the TaskBarDemo, to open an item created by your application would have to be referenced, ie if your program created a PDF file you would do this:
jumpList.AddUserTasks(new JumpListLink(Path.Combine(systemFolder, "C:\\Program Files\\Adobe\\Reader 9.0\\Reader\\AcroRD32.exe"), "Open Adobe Reader")
{
IconReference = new IconReference(Path.Combine(systemFolder, "C:\\Program Files\\Adobe\\Reader 9.0\\Reader\\AcroRD32.exe"), 0)
});
Otherwise you would have to ensure that your application registered file associations, for recent or frequent items.
I had a few problems with jumplists with the API Pack, i now use VS 2010 Beta 2 and let shell handle the jumplists.
Hope this is helpfull.
These tasks are some sort of IShellLink. Then, you should call ICustomDestinationList's AddUserTasks. Look up samples in Windows 7 Training Kit.
I'm trying to setup some code to print to different trays on a photo copier depending on what the document is (different sizes, paper colours...). It is one particular type of copier so I am not too worried about the code working in other scenarios. I still want to show the print dialog, just with the settings having better defaults for each document.
I have managed to setup the majority of what I want using properties in
PrintDialog.PrinterSettings.
However on trying to set the duplexing using
PrintDialog.PrinterSettings.Duplex = System.Drawing.Printing.Duplex.Vertical;
It fails, remaining the same as it was before. If I check if duplex is supported using
PrintDialog.PrinterSettings.CanDuplex;
It returns false which is not the case I can change it on the dialog and it prints fine. Has anyone else had this problem? Is there a work around? Perhaps something involving COM (please be gentle not used interop code much)
It's a Gestetner 2212 copier and I believe the print server is a Windows Server 2008 machine.
Edit:
I found this link
http://bytes.com/topic/c-sharp/answers/238860-using-setprinter-c-set-duplex-option-print-prefs
Which seems to be a similar problem it seems to be some kind of problem related to using a networked printer and trying to set duplex. However the link doesn't post the solution it was emailed to them (I hate it when people do that). Anyone know how I can set the duplexing using COM interop code.
Seems network printers duplex property cannot be set in .NET code easily, even when it says it has changed the property it doesn't output correctly. There is a way to do it using com interop but it still requires modifying security levels for the printer so is more hassle than it is worth.
Try implementing a handler for the PrintPage event with following code:
if (e.PageSettings.PrinterSettings.IsValid && e.PageSettings.PrinterSettings.CanDuplex)
e.PageSettings.PrinterSettings.Duplex = System.Drawing.Printing.Duplex.Vertical;
Tried it with a HP Laserjet M3035. It didn't show in the PrintDialog window but printed the document in duplex anyway.
We are assigned to develop an application using C# that can transfer print jobs between printers. I have looked on the Windows API, and System.Printing namespace but I can't find a class or function that can do this. Is there a free library out there that is suitable for this? How will you do this using .Net or the Win32 API?
If nothing exists in the Win32 API, then there will be nothing in .NET.
Unless the printer drivers are identical then you may have problems because the printer jobs go through some processing by the driver before entering the queue.
Have you considered a single queue with multiple printers associated with it (this giving more capacity and redundancy in case of printer failure)?
Isn't this a problem of load-balancing/routing a particular job to the least busy printer?
I'm pretty sure you can just CopyFile a SPL file to a new printer port if it's the same driver. If you print in EMF, you may be able to go across different drivers.
The port names might be a bit tricky depending on how the printer(s) are attached. WinObj and the rules of dev naming will be handy for tracking it down.