From an application I'm building I need to print existing PDFs (created by another app).
How can I do this in C# and provide a mechanism so the user can select a different printer or other properties.
I've looked at the PrintDialog but not sure what file it is attempting to print, if any, b/c the output is always a blank page. Maybe I'm just missing something there.
Do I need to use "iTextSharp" (as suggested else where)? That seems odd to me since I can "send the the file to the printer" I just don't have any nice dialog before hand to set the printer etc. and I don't really want to write a printing dialog from the ground up but it seems like a lot of examples I found by searching did just that.
Any advice, examples or sample code would be great!
Also if PDF is the issue the files could be created by the other app in a diff format such as bitmap or png if that makes things easier.
Display a little dialog with a combobox that has its Items set to the string collection returned by PrinterSettings.InstalledPrinters.
If you can make it a requirement that GSView be installed on the machine, you can then silently print the PDF. It's a little slow and roundabout but at least you don't have to pop up Acrobat.
Here's some code I use to print out some PDFs that I get back from a UPS Web service:
private void PrintFormPdfData(byte[] formPdfData)
{
string tempFile;
tempFile = Path.GetTempFileName();
using (FileStream fs = new FileStream(tempFile, FileMode.Create))
{
fs.Write(formPdfData, 0, formPdfData.Length);
fs.Flush();
}
try
{
string gsArguments;
string gsLocation;
ProcessStartInfo gsProcessInfo;
Process gsProcess;
gsArguments = string.Format("-grey -noquery -printer \"HP LaserJet 5M\" \"{0}\"", tempFile);
gsLocation = #"C:\Program Files\Ghostgum\gsview\gsprint.exe";
gsProcessInfo = new ProcessStartInfo();
gsProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;
gsProcessInfo.FileName = gsLocation;
gsProcessInfo.Arguments = gsArguments;
gsProcess = Process.Start(gsProcessInfo);
gsProcess.WaitForExit();
}
finally
{
File.Delete(tempFile);
}
}
As you can see, it takes the PDF data as a byte array, writes it to a temp file, and launches gsprint.exe to print the file silently to the named printer ("HP Laserjet 5M"). You could replace the printer name with whatever the user chose in your dialog box.
Printing a PNG or GIF would be much easier -- just extend the PrintDocument class and use the normal print dialog provided by Windows Forms.
Good luck!
Although this is VB you can easily translate it. By the way Adobe does not pop up, it only prints the pdf and then goes away.
''' <summary>
''' Start Adobe Process to print document
''' </summary>
''' <param name="p"></param>
''' <remarks></remarks>
Private Function printDoc(ByVal p As PrintObj) As PrintObj
Dim myProcess As New Process()
Dim myProcessStartInfo As New ProcessStartInfo(adobePath)
Dim errMsg As String = String.Empty
Dim outFile As String = String.Empty
myProcessStartInfo.UseShellExecute = False
myProcessStartInfo.RedirectStandardOutput = True
myProcessStartInfo.RedirectStandardError = True
Try
If canIprintFile(p.sourceFolder & p.sourceFileName) Then
isAdobeRunning(p)'Make sure Adobe is not running; wait till it's done
Try
myProcessStartInfo.Arguments = " /t " & """" & p.sourceFolder & p.sourceFileName & """" & " " & """" & p.destination & """"
myProcess.StartInfo = myProcessStartInfo
myProcess.Start()
myProcess.CloseMainWindow()
isAdobeRunning(p)
myProcess.Dispose()
Catch ex As Exception
End Try
p.result = "OK"
Else
p.result = "The file that the Document Printer is tryng to print is missing."
sendMailNotification("The file that the Document Printer is tryng to print" & vbCrLf & _
"is missing. The file in question is: " & vbCrLf & _
p.sourceFolder & p.sourceFileName, p)
End If
Catch ex As Exception
p.result = ex.Message
sendMailNotification(ex.Message, p)
Finally
myProcess.Dispose()
End Try
Return p
End Function
You will need Acrobat or some other application that can print the PDF. From there you P/Invoke to ShellExecute to print the document.
You could also use PDFsharp - it's an open source library for creating and manipulating PDFs.
http://www.pdfsharp.net/
I'm doing the same thing for my project and it worked for me
See if it can help you...
Process p = new Process();
p.EnableRaisingEvents = true; //Important line of code
p.StartInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
Verb = "print",
FileName = file,
Arguments = "/d:"+printDialog1.PrinterSettings.PrinterName
};
try
{
p.Start();
}
catch
{
/* your fallback code */
}
You can also play with different options of windows
PRINT command to get desired output...Reference link
After much research and googling about this task Microsoft has released a great KB to print a pdf without any other applications necessary. No need to call adobe or ghostprint. It can print without saving a file to the disk makes life very easy.
http://support2.microsoft.com/?kbid=322091
Related
I use the following method to compress the pdf:
private bool CompressPDF(string Input, string Output, string CompressValue)
{
try
{
Process proc = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.FileName = string.Concat(Path.GetDirectoryName(Application.ExecutablePath), "\\ghost.exe");
string args = "-sDEVICE=pdfwrite -dCompatibilityLevel=1.4" + " -dPDFSETTINGS=/" + CompressValue + " -dNOPAUSE -dQUIET -dBATCH" + " -sOutputFile=\"" + Output + "\" " + "\"" + Input + "\"";
psi.Arguments = args;
//start the execution
proc.StartInfo = psi;
proc.Start();
proc.WaitForExit();
return true;
}
catch
{
return false;
}
}
I put the pdf settings on "Printer" by default. I cant figure out why the file size of my pdf files increase sometimes.
Ghostscript (more accurately its pdfwrite device) doesn't 'compress' files.
It is possible, by judicious use of settings which will do things like downsample images to trade quality for file size, to get a smaller file produced but there is absolutely no guarantee that this is the case.
Without seeing the input file, there is no possible way to comment on why your file increases in size, but (for example) a PDF 1.5 file can use compressed streams and xref, and the pdfwrite device never uses those, so that could be one reason.
The canned 'PDFSETTINGS' cover a multitude of different controls, you should read those and understand what is actually going on. If your original file happens to already have traded quality for size, then it's entirely likely that the printer settings (which are reasonably conservative) will not actually do anything at all.
my client wants me to do one task. which is whenever I print ctrl+P from the browser it will go automatically that contents to the database which is sql.
Now, Let me explain what I have tried to achieve this. Usually printerPlusPlus which is third party tool. Which adds virtual printer and prints the files PS to the temp directory than I can read the contents of that postscript file and save it to the database.
My real question is there anything from which I can convert this post script files to text or read them and save the texts to the database?
Or is there any better way to achieve this task?
Ghostscript is the alternate and ow-some feature to convert the postscripts to the text or pdf. But, I am completely clueless about the documentation and how to execute their commands.
_viewer.Interpreter.RunFile("C:\\PrinterPlusPlus\\Temp\\ankit_SONY-VAIO_sony_20151227_185020_3.ps");
GhostscriptPngDevice dev = new GhostscriptPngDevice(GhostscriptPngDeviceType.Png16m);
dev.GraphicsAlphaBits = GhostscriptImageDeviceAlphaBits.V_4;
dev.TextAlphaBits = GhostscriptImageDeviceAlphaBits.V_4;
dev.ResolutionXY = new GhostscriptImageDeviceResolution(96, 96);
dev.InputFiles.Add(#"C:\\PrinterPlusPlus\\Temp\\ankit_SONY-VAIO_sony_20151227_185020_3.ps");
dev.OutputPath = #"C:\\PrinterPlusPlus\\Temp\\ankit_SONY-VAIO_sony_20151227_185020_3.txt";
dev.Process();
_preview.Activate();
I tried this but this seems to be not working and adding ASCII text to the txt file.
I found ghostscript little confusing. But, I found the solution from here
string inputFile = #"E:\gss_test\test_postscript.ps";
GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput();
// pipe handle format: %handle%hexvalue
string outputPipeHandle = "%handle%" + int.Parse(gsPipedOutput.ClientHandle).ToString("X2");
using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dQUIET");
switches.Add("-dSAFER");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOPROMPT");
switches.Add("-sDEVICE=pdfwrite");
switches.Add("-o" + outputPipeHandle);
switches.Add("-q");
switches.Add("-f");
switches.Add(inputFile);
try
{
processor.StartProcessing(switches.ToArray(), null);
byte[] rawDocumentData = gsPipedOutput.Data;
//if (writeToDatabase)
//{
// Database.ExecSP("add_document", rawDocumentData);
//}
//else if (writeToDisk)
//{
// File.WriteAllBytes(#"E:\gss_test\output\test_piped_output.pdf", rawDocumentData);
//}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
gsPipedOutput.Dispose();
gsPipedOutput = null;
}
}
This reads the postscript files easily :)
I was trying to print a pdf document in the background using a console application. I used the process for doing it. The console application sends the pdf file to the printer, But the adobe reader that is opened in the background in minimized mode is throwing the following error "There was an error opening this document. This file cannot be found". As a result of this while printing multiple times, I was not able to kill the process. Is there any possibility of getting rid of this error?
My requirement is to print the pdf file using process and while doing that the pdf file must be opened in the minimized mode and once done printing the reader needs to be closed automatically. I have tried the following code, but still throws the error..
string file = "D:\\hat.pdf";
PrinterSettings ps = new PrinterSettings();
string printer = ps.PrinterName;
Process.Start(Registry.LocalMachine.OpenSubKe(#"SOFTWARE\Microsoft\Windows\CurrentVersion"+#"\App Paths\AcroRd32.exe").GetValue("").ToString(),string.Format("/h /t \"{0}\" \"{1}\"", file, printer));
since you want to have Acrobat reader open in the background when you want to print the document, you could use something like:
private static void RunExecutable(string executable, string arguments)
{
ProcessStartInfo starter = new ProcessStartInfo(executable, arguments);
starter.CreateNoWindow = true;
starter.RedirectStandardOutput = true;
starter.UseShellExecute = false;
Process process = new Process();
process.StartInfo = starter;
process.Start();
StringBuilder buffer = new StringBuilder();
using (StreamReader reader = process.StandardOutput)
{
string line = reader.ReadLine();
while (line != null)
{
buffer.Append(line);
buffer.Append(Environment.NewLine);
line = reader.ReadLine();
Thread.Sleep(100);
}
}
if (process.ExitCode != 0)
{
throw new Exception(string.Format(#"""{0}"" exited with ExitCode {1}. Output: {2}",
executable, process.ExitCode, buffer.ToString());
}
}
You can print your PDF by incorporating the above code into your project and using it as follows:
string pathToExecutable = "c:\...\acrord32.exe";
RunExecutable(pathToExecutable, #"/t ""mytest.pdf"" ""My Windows PrinterName""");
this code was taken from http://aspalliance.com/514_CodeSnip_Printing_PDF_from_NET.all
If you do not need to have Acrobat Reader open in the background, and just print the pdf like any other document, you can have a look at the PrintDocument class:
http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.print.aspx
I am a newbie to C#, I have a "Save to File" option in my program which saves the output of a richtextbox in a word document and when the user chooses this option, I have used saveFileDialogue box for the user to chose the filename and the location.
What I want is that every time when the user chooses this option the word document in which the output is saved has a pre-defined header and footer images...
Thanks a lot for your help in advance!
below is my 'Save to File" code.
private void menuItem7_Click(object sender, EventArgs e)
{
// Create a SaveFileDialog to request a path and file name to save to.
SaveFileDialog saveFile1 = new SaveFileDialog();
// Initialize the SaveFileDialog to specify the RTF extension for the file.
saveFile1.DefaultExt = "*.rtf";
saveFile1.Filter = "RTF Files|*.rtf";
// Determine if the user selected a file name from the saveFileDialog.
if (saveFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
saveFile1.FileName.Length > 0)
{
// Save the contents of the RichTextBox into the file.
richTextBox1.SaveFile(saveFile1.FileName,
RichTextBoxStreamType.PlainText);
}
}
First of all, create a function to take an image, width and height and return the rtf:
This is for a png
public string GetImage(string path, int width, int height)
{
var stream = new MemoryStream();
var img = Image.FromFile(path);
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
var bytes = stream.ToArray();
var str = BitConverter.ToString(bytes, 0).Replace("-", string.Empty);
var mpic = #"{\pict\pngblip\picw" + img.Width.ToString() + #"\pich" + img.Height.ToString() +
#"\picwgoa" + width.ToString() + #"\pichgoa" + height.ToString() +
#"\hex " + str + "}";
return mpic;
}
Now you need to insert this 'image' into the right place in the rtf. If you open your rtf file in notepad you should see something like this:
{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\fnil\fcharset0
Microsoft Sans Serif;}} \viewkind4\uc1\pard\f0\fs17 MYTEXT\par }
If you wanted a quick and dirty method then get the rtf from the richTextBox into a string,
and insert your header image string after the deflang2057 followed by a '/par' to make a new line. Then insert your footer image string just before the closing '}'
something like this:
// Determine if the user selected a file name from the saveFileDialog.
if (saveFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
saveFile1.FileName.Length > 0)
{
var rtf = richTextBox1.Rtf.Insert(richTextBox1.Rtf.IndexOf("deflang2057") + 11, GetImage(#"c:\a.png", 5, 5) + #"\par");
using (var rtfFile = new StreamWriter(saveFile1.FileName))
{
rtfFile.Write(rtf);
}
}
I hope that gets you started.
Here is an example how to use Open XML SDK ...
Source Code
you will have to plug-in your text where it says "Original Text Here".
You have picked a very difficult task for a "newbie". To mix images and text you will need a complex format like PostScript, PDF, DocX, or RTF. Controlling pagination, for example to specify your header and footer images only once and have them automatically show up on the top and bottom of each page, is an even more difficult task.
You have not given us enough information to tell you where to start. For example, what is "my program"? Is it like a word processor? You will have to use the System.Drawing.Printing.PrintDocument classes to define a print document, draw headers and footers when you reach the appropriate place on each page, perform line layout, breaks and pagination. This is a large job for a professional programmer.
Or do you just want to produce a file that another program can output, with headers and footers? You could output RTF; the specification is here. This is an easier task; you may be able to leverage exisiting RTF interpreters.
Or do you want to display these documents on-screen? Han's suggestion to use an existing application via automation is a good one.
Break your task into smaller requirements and investigate each requirement.
I use tesseract to get text from captcha image.
I use this code
Process p = new Process();
p.StartInfo.FileName = Server.MapPath("~/app/tesseract.exe");
p.StartInfo.Arguments = imgSavePath + " " + txtSavePath;
p.Start();
p.WaitForExit();
bool exist = File.Exists(txtSavePath);
The txtSavePath is created in windows explorer, i can open it and can read the text in it. But the exist variable is false. It is so strange.
Can anybody tell me why? How can i use StreamReader to read text in created file?
Tesseract appends a ".txt" extension to the output text file; so in your case, it should be:
bool exist = File.Exists(txtSavePath + ".txt");