Printer spooler api number of copies - c#

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?

Related

Programatic truncation of large file names (zipped) for different Windows editions

So I'm bugfixing on a program that allows a user to create an Excel document, which it first zip compresses before serving to the customer. One of the client complaints is that, while the zip file can always be downloaded, sometimes the user must copy the Excel file out of the archive (or extract it) before opening it, using the standard Windows compressed tools. Standard "File name too long" error.
The algorithm is, of course, setting the .zip archive name to the same as the report - which can be 100+ character long strings.
The solution I'm implementing is to check the length of the potential report to see it if it violate MAX_PATH, naturally, and truncate the .zip name as needed.
Testing it on Windows 7, this works perfectly. But something odd happens when testing it under 8.1
It still throws an error trying to open from the archive - but this error is a bit more enigmatic.
"Sorry, we couldn't find C:\Users{My user name}\AppData\Local\Temp\Temp1_{Rest of the truncated archive name}.zip{Full file name}.xlsx. Is it possible it was moved, renamed or deleted?"
This error keeps popping up, regardless of whether the file is "Open"ed or "Save"d from the browser.
Normally, I'd just try further tweaking, but testing on the Windows 8.1 platform involves a lot of overhead at the moment, and it doesn't look like the problem is the path name length.
What is going on? Does Windows 8 have problem with the length of names within archives, or...?
Also, the reason I am posting this here, and not, say, User Experience, is because I feel like the solution will be programmatic - something in the code of the program. I readily concede that "allow the end user to skip hitting the Extract button" is about providing an easy user experience, but truncating the length of the entire path solved the problem on Windows 7.
Just not 8.1, and googling/searching the SO site family provides no help - ironically, because of the keyword Excel.
So, as I found in the link above (http://answers.microsoft.com/en-us/office/forum/office_2013_release-excel/sorry-unable-to-find/595333d0-1463-499f-967e-4da8ac2e2047?auth=1) the crux seems to be that, although MAX_PATH is 260 characters, Excel 2013 can't handle anything over 212.
I still haven't been able to give this the rigorous testing it deserves, but if anyone else encounters this problem, and finds this page in their quest for a fix, just truncate until the entire path is under 212 and you should be good.

Reconnect to a disconnected Excel COM Interop instance

I have a 3rd party app that is exporting data to Excel using the Excel COM Interop. There is a bug in their program causing it to fail before it makes the Excel instance visible. However from where the exception is happening, according to the displayed stack trace, the information I need has already been written out to the Excel Worksheet.
Is there any way to use the Microsoft.Office.Interop.Excel namespace to connect to a existing excel instance instead of it generating it's own? Or is there any other way I could make that orphaned Excel instance visible so I can save what it completed?
As a note, the EXCEL.exe is still visible in task manager after the program closes so the instance is still live and running after the app has disconnected.
More Details: What the program is doing is exporting a report from it's own (proprietary) database, however for some reason some record in the database became malformed and causes a Integer Overflow error to occur while the report is generating. Looking at the stack trace it appears this integer overflow is happing while it is generating the summery at the end of the report.
For my uses I do not need the summary just the line items from the report, so I hoped to see what work it had done so far but the EXCEL.exe instance it was communicating with is not visible.
If I run the report for a different date range the report generates fine, it is just something about one record on one day that causes this specific set of inputs that causes it to fail.
The support contract with the provider of the app as expired and management is not interested in renewing it as we are in the process of switching to a new vendor (that is why the report is being generated, to be used as the data-source for the data conversion). So I have been tasked with "fixing it" so the data can be moved over.
Final Update: The reason I asked the question was solved. I was able to go through each record via the program itself and I found the record that had one of it's fields set to 16274176.00 (normal values are in the 100's (and don't ask me why what appears to be a float causes a Integer Overflow error)), once I changed that to 0.00 the report printed fine. However I still would like to know if there is a answer to my original question as I think it would be a useful tool in my toolbox.
In regards to your original question, I think it actually might be a possible duplicate of what have been asked here: Get instance of Excel application with C# by Handle
A couple of the answers given points to this blog post: Launching Office Apps Programmatically which gives you a palette of options of how to connect to an already running Office application from managed code.
The blog post as well as the answers given also contains sample code to illustrate how this can be done.

General file attribute to identify file without its path or even name

I am working on an application that keeps track and uses files stored on the file system. Users are allowed to open, create, delete and move files in the file system. Meanwhile my application is not constantly running so I can't keep track of all changes real-time. Afterwards my application has to find out what file is whom (i.c. as identified in my application).
The most preferred solution for the users is that the application solves every change itself. Each user-interaction is less preferred.
One of my ideas was to use an attribute of a file and assign a key-value to it so when it has been identified once, it can always been recognized afterwards. But I don't know if there is such an attribute. This article didn't give much hope: There is in Windows file systems a pre computed hash for each file?.
Does somebody know if there is such an attribute I can use? And how can I used it in C#?
Is there anyone who is running up against this problem? And how did you solve it?
I'd like to hear good suggestions.
regards, Jaap
If your files don't leave NTFS, this is easily achievable by alternative data streams, where you can store your data along with files. This is more-or-less good article about ADS: http://www.flexhex.com/docs/articles/alternate-streams.phtml
There is another suitable method - it's very efficient, but also very complicated to use, it requires quite good knowledge about NTFS internals - USN Change Journal; see http://msdn.microsoft.com/en-us/library/windows/desktop/aa363798.aspx. With USN Change Journal, you can "get" very efficiently all files that were changed (even all change events) within specified time period.
Nevertheless, if your files leave NTFS realm, e.g. if it's copied to FAT32, contents of ADS is lost.
Relying on a File attribute is "dangerous" in that some user could alter the attribute while your program isn't running. This could lead you to believe that a certain file is (or isn't) tracked by the program while it really isn't.
I would suggest to keep track of the files in a database, XML, or some other file. When your application starts you read the file/db and check for new/deleted/editted files.
You could store a Hash of the files to find out if a file has been moved/editted. Keeping track of files that are moved AND editted is going to be pretty difficult. (I have no clue how you could achieve it)
PS: Have you considered making your application a Windows service? Having the file-management running in the background no matter if the GUI part of your application is running or not?

C# PrintDialog.PrinterSettings.CanDuplex Reports Wrongly

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.

Transferring Print Jobs Between Printers

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.

Categories