Print PDF and reading the error output of the Process - c#

Well, my objective is to print a PDF file without asking for user confirmation.I can't force my users to use a specific PDF reader (such as Adobe Acrobat or Foxit) and need to print the file without any user interaction.
My current code is the following:
String strFile = "pdf_file.pdf";
String strPrinter = "Printer Name";
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = strFile;
p.StartInfo.Arguments = strPrinter;
p.StartInfo.Verb = "PrintTo";
p.StartInfo.CreateNoWindow = true;
p.Start();
p.CloseMainWindow();
I have some code to kill the process if it don't exit, but it doesn't matter now.
This code works mostly well, but i can't get the error messages that occur in the process.
The try catch block won't help in this case, because the error occur in the process "p", not in the main process.
Searching the net i found out that to recover the errors i need to set the following:
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
// Start process, kill it, etc...
String s = p.StandardError.ReadToEnd();
But applying this code gives me another error: the file is not a valid win32 application.
Obviously, the file I'm oppening is a PDF file, not a EXE.
Anyone knows another way to recover the errors that occur in the process?
Such as the printer is not found, etc...

If I understood it right, you are trying to print a PDF file using the default PDF reader installed in the client machine.
As you said, this code is trying to actually run a .pdf file. You could use a C# PDF library, but I dont know how it'll send the raw PDF data to the printer, so I would try using a PDF command line tool, put it in the bin/Release folder of the project (and also bin/Debug, for testing purposes) and then call it using a command line.
If you want it to be totally transparent and PDF-Reader independent, maybe you should try it. In the command line, you explicitly tell what executable you want to run, so it wont make Adobe Acrobat Reader pop up in the screen, and the user won't freak out =D
Here is an example of PDF printer:
http://pdfbox.apache.org/commandline/#printPDF
The command line is: java -jar pdfbox-app-x.y.z.jar PrintPDF [OPTIONS] <inputfile>
It needs Java to run, if this is not a problem, you can try it. You could also search for a native or .NET managed solution, I think you got the idea.
Good luck!

Related

How to programatically send openoffice writer odt file to printer from C# Windows Forms Application

I'd like to send an OpenOffice writer document to the default printer from within a C# WinForms application. The purpose is to print customer receipts. I plan on opening a prepared OpenOffice file, substitute dynamic customer information and then print the modified document. It is important that OO not necessarily be installed so solutions which depend on OO or open up an OO prompt won't work. Any suggestions would be appreciated.
I too use open office for printing customer generated invoices, I do so in bulk and below is the method that I use.
What you are seeking is achievable by using "ProcessStartInfo" from the Systems.Diagnostics namespace found here:
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo(v=vs.110).aspx
the important part is ensuring you have set "CreateNoWindow" to true as well as settings the "WindowStyle" to "ProcessWindowStyle.Hidden".
Simply pass in the location of the file to print, and ensure you include the file extension after the location. I use this snippet regularly so if you have any problems just let me know.
void printDoc(String fileLocation) {
ProcessStartInfo info = new ProcessStartInfo(fileLocation);
info.Verb = "print";
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info);
}

How can I capture the console output of dpinst when running silently?

I've got a process (written in C#) that runs with administrative rights and invokes dpinst.exe to perform an automated driver installation. It writes its own custom dpinst.xml file to specify things like suppressing the EULA page, suppressing the wizard, running a "quiet install," and searching in all subdirectories.
When I invoke this manually from the command line (see example below), it seems to work fine. Because of the command line switches I'm using it prints a bunch of INFO level log messages in the console.
C:\Path\To\Drivers> dpinst.exe /C /L 0x409
I want to log what gets printed in the console, so my C# code looks something like this:
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"C:\Path\To\Drivers\dpinst.exe",
Arguments = "/C /L 0x409",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
Verb = "runas"
}
};
string output;
process.Start();
using (var reader = process.StandardOutput)
{
output = reader.ReadToEnd();
reader.Close();
}
However, when I run that code, the value of output is always blank. So, for my next experiment, I tried using the command line directly to pipe the output to a file, like this:
C:\Path\To\Drivers> dpinst.exe /C /L 0x409 > test.log 2>&1
That created the test.log file, but it was also blank. Interestingly enough I could still see all of the console output that dpinst.exe generates in that same console window; for some reason it didn't get redirected to the file that I specified. So the symptom is the same regardless of how I invoke the dpinst executable; it doesn't want to redirect output. I'm not sure what the underlying reason for that is, nor how to solve it. How can I capture the console output?
EDIT: If anyone wants a copy of dpinst.exe to run locally and test out themselves, I've provided one at this link, bundled with the dpinst.xml file I'm using. Remember that you need to invoke it with the /C command line switch in order to generate any command line output. Alternatively, if you're paranoid and don't want to download an executable from some random Stack Overflow question, you can get the dpinst.exe utility as part of the Windows Driver Kit from Microsoft. It's a free download, but you have to extract the utility (which is only 500 KB) from the full WDK ISO (which is ~700 MB). Up to you. :)
Your code runs perfectly fine with standard tools (like "ping") for example. So maybe for some reason dpinst writes to standard error instead? You can set RedirectStandardError = true and read StandardError to check if that is the case.
UPDATED in case anyone else will hit this problem:
It seems dpinst does not write to standard output but logs messages to console in some other way. Only way to achieve your goal which comes to my mind is: remember size of "%SystemRoot%\DPINST.LOG" file, run your command, wait for exit, then read everything between remembered position and end of file. This way you will get your logs.
I my answer will help other. When you run Dpinst.exe and you add the swicth /C to dump the log to console, it also creates a log file in this directory "C:\Windows\DPINST.LOG"
You can locate the log file there..

PDF Printing happens in random order

I am using Foxit Reader (a PDF Reader) and passing command line arguments to print a pdf pro-grammatically. I understand that we cannot specify the number of copies through command line as from this discussion.
I am developing a win-forms desktop application and for printing multiple copies of PDF document I am using the below code
string foxitReaderInstalledPath = GetFoxitReaderInstalledPath();
while (noOfCopies > 0)
{
Process process = new System.Diagnostics.Process();
process.EnableRaisingEvents = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = foxitReaderInstalledPath;
string arguments = String.Format(#"-t ""{0}"" ""{1}""", this.Path, printerName);
process.StartInfo.Arguments = arguments;
process.Start();
process.WaitForExit();
noOfCopies = noOfCopies - 1;
}
Issue happens when multiple users are giving muliple copies of print to the same printer. The issue is the printed documents gets mixed up in the order in which they get printed. Anyone please let me know how I can avoid this issue?
Many thanks.
You can't avoid this client-side...
IF you really want to avoid it the "client" app which is used by the users has to just send the file to some "centralized server process" with all relevant params... this "centralized process" can then "serialize" the printing so it occurs in correct order...
BUT if the printer you are printing to is accessible from the users systems then it could still happen that a user sends something to the printer (like an image or word document...) which will be printed and disturbing the order a bit...
I think it would make much more sense if you described what your goal is... perhaps there is some better way to solve all this... are you implementing a print server ?
EDIT - as per comment:
Put the location for the PDF files on a network share... and run your printing code on the same machine which provides the share... ideally the printer is directly connected to that machine... this should provide enough performance and since it is only one central application accessing the printer it should work fine...
I would strongly recommend the use of a PDF library or Acrobat reader so that the printing can use a parameter for NumberOfCopies !
EDIT 2 - as per comment:
Some PDF Libraries:
.NET library to print PDF files
http://www.gnostice.com/PDFOne_dot_NET.asp
http://www.gdpicture.com/products/dotnet/plugins/pdf-plugin.php
http://itextpdf.com/

Java and .net interoperability

I have a c# program through which i am opening cmd window as a a process. in this command window i am running a batch file. i am redirecting the output of that batch file commands to a Text File. When i run my application everything seems to be ok.
But few times, Application is giving some error like "Can't access the file. it's being used by another application" at the same time cmd window is not getting closed. If we close the cmd process through the Task Manager, then it's writing the content to the file and getting closed. Even though i closed the cmd process, still file handle is not getting released. so that i am not able to run the application next time onwards.Always it's saying Can't access the file. Only after restarting the system, it's working.
Here is my code:
Process objProcess = new Process();
ProcessStartInfo objProInfo = new ProcessStartInfo();
objProInfo.WindowStyle = ProcessWindowStyle.Maximized;
objProInfo.UseShellExecute = true;
objProInfo.FileName = "Batch file path"
objProInfo.Arguments = "Some Arguments";
if (Directory.Exists(strOutputPath) == false)
{
Directory.CreateDirectory(strOutputPath);
}
objProInfo.CreateNoWindow = false;
objProcess.StartInfo = objProInfo;
objProcess.Start();
objProcess.WaitForExit();
test.bat:
java classname argument > output.txt
Here is my question:
I am not able to trace where the problem is..
How we can see the process which holding handle on ant file.
Is there any suggestions for Java and .net interoperability
In situations like this I start up the Process Explorer ( by Sysinternals, awesome tool btw ) click Ctrl+F, and enter the name of the file. It will search across all running processes and will list the file handles to this file by the applications that have it open.
You can then either drop the handle, or kill the app - whatever you think is better )
You can try forking and attaching file descriptor from C# rather than launching a bat file.
I think the problem is because the java program is accessing the text file when the C# program is writing something on it, and hence a "file cannot access" problem.
If I were you, I would do everything in C#-- I won't use Java to read the state of the C# program. And I would access the file only after I've completed whatever the C# needs to do.
As for to see what process is locking up your file, you can use Process Explorer for this purpose.

C# System.Diagnostics.Process verb issue

I have a Windows Application written in C# VS 2008. The purpose of this application is to convert any file to PDF files. I have found code that works on converting the files however there is a small issue that I am coming across.
First here is the code:
private void PrintToAdobePDF(string strInputFilePath)
{
ProcessStartInfo pProcInfo = new ProcessStartInfo();
bool blResult;
blResult = SetDefaultPrinter(D2P_Adobe_Printer);
if (blResult)
{
pProcInfo.FileName = strInputFilePath;
pProcInfo.Verb = "Print";
pProcInfo.CreateNoWindow = true;
pProcInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process pProc = Process.Start(pProcInfo);
pProc.WaitForExit(1000);
pProc.CloseMainWindow();
pProc.Close();
}
The issue I am having is that when the Process.Start() method is invoke it is running with TWO verbs instead of the one verb I specified ("Print"). It is running "Open" and "PrintTo" which is making the application that the original file is derived from open up and hang the application (i.e. jpg opens the Windows Fax and Picture Viewer).
My question is how do I just use the "Print" verb within the Process.Start() method?
Thank you in advance
Have you tried researching if it's possible to execute Adobe Reader with a command line parameter that accomplishes the same thing? Relying on the shell is iffy sometimes.
What are sending in for strInputFilePath? The documentation says to only send the filename so if you are sending the whole path that could be causing the issue.
No, sending the filename without the extension will fail.
Ultimately using System.Diagnostics.Process to print any arbitrary file is going to be unpredictable at best. It's all up to how your operating system handles each type of file, and whether or not your registry is properly configured to handle that file.
I'd guess that printing .doc files in this manner probably works OK, while other file types may not work so well.
In my opinion, you should find some constraint about the kinds of files you'll allow to "automagically" print, and build working solutions per type of file. Otherwise, you'll find a lot of unpredictable behavior.

Categories