In my application, the student will fill all the details and then will click the submit button.
It will show all the details of the students in studentDetails.aspx page.
In studentDetails.aspx page, there is a Print button.
What I want is that when a student clicks this print button it should show the details of the students in a PDF file format, ready to be printed.
i've tried the following, can anybody help me to come out of this...`
protected void Button1_Click(object sender, EventArgs e)
{
Uri strurl = Request.Url;
string url = strurl.ToString();
string filename = "Test";
HtmlToPdf(url, filename);
}
public static bool HtmlToPdf(string Url, string outputFilename)
{
string filename = ConfigurationManager.AppSettings["ExportFilePath"] + "\\" + outputFilename + ".pdf";
Process p = new System.Diagnostics.Process();
p.StartInfo.Arguments = Url + " " + filename;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = HttpContext.Current.Server.MapPath(#"C:\Users\$$\Documents\Visual Studio 2008\Projects\santhu") + "wkhtmltopdf.exe";
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit(60000);
int returnCode = p.ExitCode;
p.Close();
return (returnCode == 0 || returnCode == 2);
}
}
You're going to want to leverage something like the iTextSharp library for this. It's a straight forward solution. Consider the following code block:
using (Document doc = new Document(PageSize.A4, 0, 0, 0, 0))
{
using (FileStream stream = new FileStream(targetPath, FileMode.Create))
{
PdfWriter.GetInstance(doc, stream);
doc.Open();
var font = FontFactory.GetFont("Courier", 10);
var paragraph = new Paragraph(sb.ToString(), font);
doc.Add(paragraph);
doc.Close();
}
}
That takes a text file and turns it into a PDF. Now obviously you'll need to modify it for your needs, but you see how simple it is. Plus the library has classes for all of the concepts of a PDF, not just a Paragraph.
Related
So I am writing an app in c# to upscale videos to a certain resolution. It uses ffmpeg to do this. What happens is after selecting the video file, and clicking 1080p it creates the directory folder but does not actually write the upscaled video to it.
I think I must have a string format issue:
private void HD_Click(object sender, EventArgs e)
{
if (textBox1.Text == null)
{
MessageBox.Show("You've not selected your video file yet. Please do so before continuing, cheers.");
}
else
{
var originFilePath = textBox1.Text;
string name = Path.GetFileName(originFilePath);
byte[] bytes = null;
using (FileStream fileStream = new FileStream(originFilePath, FileMode.Open, FileAccess.Read))
{
using (MemoryStream ms = new MemoryStream())
{
fileStream.CopyTo(ms);
bytes = ms.ToArray();
}
var localStoragePath = Path.Combine(Path.GetTempPath(), name);
var directoryPath = Path.GetDirectoryName(localStoragePath);
Directory.CreateDirectory(directoryPath);
File.WriteAllBytes(localStoragePath, bytes);
Console.WriteLine($"File copy successful: {File.Exists(localStoragePath)}");
var readBack = File.ReadAllBytes(localStoragePath);
Console.WriteLine($"Read file Back: {readBack.Length}, {localStoragePath}");
var resizedFolderPath = #"C:\upscaledvideohere";
Directory.CreateDirectory(resizedFolderPath);
var resizedFiePath = Path.Combine(resizedFolderPath, Path.GetFileName(localStoragePath));
var psi = new ProcessStartInfo();
psi.FileName = #"C:\ffmpeg-2020-12-27-git-bff6fbead8-full_build\binffmpeg.exe";
psi.Arguments = $"-i \"{localStoragePath}\" -vf scale=1080 \"{resizedFiePath}\"";
psi.RedirectStandardOutput = false;
psi.RedirectStandardError = false;
psi.UseShellExecute = true;
Console.WriteLine($"Args: {psi.Arguments}");
try
{
using (Process exeProcess = Process.Start(psi))
{
Console.WriteLine($"process started with processId: {exeProcess.Id}");
exeProcess.WaitForExit();
Console.WriteLine($"Exit Code: {exeProcess.ExitCode}");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace.ToString());
Console.WriteLine(ex.Message.ToString());
return;
}
Console.WriteLine($"process completed");
Console.WriteLine($"Temp Out Exists: {File.Exists(resizedFiePath)}");
}
Console.ReadLine();
}
}
I am wondering where the string format error could be? Thank you.
As far as I am aware, the scale command of ffmpeg takes two dimensions. If you want scaling to remain proportional you specify one of the options as -1. As 1080 is your height, your scale command would be scale=-1:1080
To debug things like this, put a breakpoint after your arguments line, point to the variable(or use the locals window) so the tooltip appears and then right click it and copy the value. Paste the value into a command prompt and see whether ffmpeg does what you expect. Fix the arguments in the command prompt if it doesn't, and carry the changes back into your code
Is it possible to pass FFMPEG video stream to C# window? Now it opens as new process in new window, I just simply want to pass it to my own SessionWindow.
At this moment I execute ffplay like this:
public void ExecuteCommandSync(String command, String args)
{
try
{
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("\"" + command + "\"", args);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
Debug.WriteLine(result);
}
catch (Exception objException)
{
}
}
private void button2_Click(object sender, EventArgs e)
{
String runPlay = #"C:\FFMPEG\bin\ffplay.exe";
String Random = "udp://127.0.0.1:1234";
this.ExecuteCommandSync(runPlay, Random);
}
PS. I don't want to use Windows Media Player since I want this app to look and work like remote desktop.
Looks like I found answer.
Process ProcFFplay = new Process();
ProcFFplay.StartInfo.FileName = #"C:\FFMPEG\bin\ffplay.exe";
ProcFFplay.StartInfo.Arguments = #"-probesize 32 udp://192.168.88.228:12340";
ProcFFplay.StartInfo.CreateNoWindow = true;
ProcFFplay.StartInfo.RedirectStandardOutput = true;
ProcFFplay.StartInfo.UseShellExecute = false;
ProcFFplay.EnableRaisingEvents = true;
ProcFFplay.OutputDataReceived += (o, k) => Debug.WriteLine(k.Data ?? "NULL", "ffplay");
ProcFFplay.ErrorDataReceived += (o, k) => Debug.WriteLine(k.Data ?? "NULL", "ffplay");
ProcFFplay.Exited += (o, k) => Debug.WriteLine("Exited", "ffplay");
ProcFFplay.Start();
Thread.Sleep(4500);//this is time which you need to wait to get first frames approximately
SetParent(ProcFFplay.MainWindowHandle, this.panel1.Handle);
MoveWindow(ProcFFplay.MainWindowHandle, -5, -30, 1200, 800, true); //these parameteres may look weird but you hide top "stripe" using them.
Enjoy.
I'm trying to use the following C# code to compile Java using javac:
Process p = new Process();
p.StartInfo.FileName = "javac";
Directory.CreateDirectory(Application.StartupPath + #"/TempJava");
p.StartInfo.Arguments = "-d "Application.StartupPath + #"/TempJava" + files;
p.Start();
"files" represents a string variable containing the name(s) of the *.java files.
All in all, I want to create a new folder, and then take the Java files (from where ever they may be located) and compile it into a class file(s) in TempJava.
For some reason, the code doesn't work, no errors, no warnings, but when I run it and check TempJava, there's no files in it.
Just because your child process ends with a possible error, it doesn't mean your parent process must be aware of it.
Inspect the process' exit code and standard output stream, and especially the standard error stream. Your answer lies in there...
here i have 2 buttons run and compile here is some code to help.
private void comp_Click(object sender, EventArgs e)
{
string text = "javac " + label1.Text + file + "#pause" + "#stop";
text = text.Replace("#", System.Environment.NewLine);
File.WriteAllText(label1.Text + "Compile.bat", text);
Process proc = null;
try
{
proc = new Process();
proc.StartInfo.FileName = label1.Text + "Compile.bat";
proc.StartInfo.CreateNoWindow = false;
proc.Start();
proc.WaitForExit();
}
catch
{
}
}
private void runp_Click(object sender, EventArgs e)
{
string news = file.Remove(file.Length - 5);
string text = "java " + news + "#pause";
text = text.Replace("#", System.Environment.NewLine);
File.WriteAllText(label1.Text + "Run.bat", text);
Process proc = null;
try
{
proc = new Process();
proc.StartInfo.FileName = label1.Text + "Run.bat";
proc.StartInfo.WorkingDirectory = label1.Text.Remove(label1.Text.Length - 1);
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
}
catch
{
}
}
all i really do is create a batch and run it using c#.
how to pass html as a string instead of url in wkhtmltopdf using asp.net, c#?
STDIn and STDOut have been redirected in this example, so you shouldn't need files at all.
public static class Printer
{
public const string HtmlToPdfExePath = "wkhtmltopdf.exe";
public static bool GeneratePdf(string commandLocation, StreamReader html, Stream pdf, Size pageSize)
{
Process p;
StreamWriter stdin;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = Path.Combine(commandLocation, HtmlToPdfExePath);
psi.WorkingDirectory = Path.GetDirectoryName(psi.FileName);
// run the conversion utility
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
// note: that we tell wkhtmltopdf to be quiet and not run scripts
psi.Arguments = "-q -n --disable-smart-shrinking " + (pageSize.IsEmpty? "" : "--page-width " + pageSize.Width + "mm --page-height " + pageSize.Height + "mm") + " - -";
p = Process.Start(psi);
try {
stdin = p.StandardInput;
stdin.AutoFlush = true;
stdin.Write(html.ReadToEnd());
stdin.Dispose();
CopyStream(p.StandardOutput.BaseStream, pdf);
p.StandardOutput.Close();
pdf.Position = 0;
p.WaitForExit(10000);
return true;
} catch {
return false;
} finally {
p.Dispose();
}
}
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0) {
output.Write(buffer, 0, read);
}
}
}
Redirecting STDIN is probably the easiest way to accomplish what you're trying to do.
One method of redirecting STDIN with wkhtmltopdf (in ASP.Net) is as follows:
private void WritePDF(string HTML)
{
string inFileName,
outFileName,
tempPath;
Process p;
System.IO.StreamWriter stdin;
ProcessStartInfo psi = new ProcessStartInfo();
tempPath = Request.PhysicalApplicationPath + "temp\\";
inFileName = Session.SessionID + ".htm";
outFileName = Session.SessionID + ".pdf";
// run the conversion utility
psi.UseShellExecute = false;
psi.FileName = "c:\\Program Files (x86)\\wkhtmltopdf\\wkhtmltopdf.exe";
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
// note that we tell wkhtmltopdf to be quiet and not run scripts
// NOTE: I couldn't figure out a way to get both stdin and stdout redirected so we have to write to a file and then clean up afterwards
psi.Arguments = "-q -n - " + tempPath + outFileName;
p = Process.Start(psi);
try
{
stdin = p.StandardInput;
stdin.AutoFlush = true;
stdin.Write(HTML);
stdin.Close();
if (p.WaitForExit(15000))
{
// NOTE: the application hangs when we use WriteFile (due to the Delete below?); this works
Response.BinaryWrite(System.IO.File.ReadAllBytes(tempPath + outFileName));
//Response.WriteFile(tempPath + outFileName);
}
}
finally
{
p.Close();
p.Dispose();
}
// delete the pdf
System.IO.File.Delete(tempPath + outFileName);
}
Note that the code above assumes that there's a temp directory available in your application directory. Also, you must explicitly enable write access to that directory for the user account used when running the IIS process.
I know this is an older post, but I want future developers to have this option. I had the same need, and the idea of having to start a background process just to get a PDF inside of a web app is terrible.
Here's another option: https://github.com/TimothyKhouri/WkHtmlToXDotNet
It's a .NET native wrapper around wkhtmltopdf.
Sample code here:
var pdfData = HtmlToXConverter.ConvertToPdf("<h1>COOOL!</h1>");
Note, it's not thread-safe as of right now - I'm working on that. So just use a monitor or something or a lock.
I'm trying to print a PDF file using Process object. And up to certain extent I could print it successfully. But now I want to set printer properties.. like no of copies, Paper size etc. But I don't see any property to set these values.
I'm using following code to print PDFs
string fileName = "";
string arguments = "";
string verbToUse = "";
int i = 0;
ProcessStartInfo startInfo = new ProcessStartInfo();
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.Filter = "pdf files (*.pdf)|*.pdf|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if ((fileName = openFileDialog1.FileName) != null)
{
startInfo = new ProcessStartInfo(fileName);
if (File.Exists(fileName))
{
i = 0;
foreach (String verb in startInfo.Verbs)
{
// Display the possible verbs.
MessageBox.Show(i.ToString() + ". " + verb);
i++;
}
}
}
//Console.WriteLine("Select the index of the verb.");
string index = "2";
if (Convert.ToInt32(index) < i)
verbToUse = startInfo.Verbs[Convert.ToInt32(index)];
else
return;
startInfo.Verb = verbToUse;
if (verbToUse.ToLower().IndexOf("printto") >= 0)
{
//Printer Name
arguments = #"\\hydfsvt02\HPLaserJ";
startInfo.Arguments = arguments;
}
Process newProcess = new Process();
newProcess.StartInfo = startInfo;
try
{
newProcess.Start();
MessageBox.Show(newProcess.ProcessName + " for file " + fileName + " started successfully with verb " + startInfo.Verb);
}
catch (System.ComponentModel.Win32Exception ex)
{
MessageBox.Show(" Win32Exception caught!");
MessageBox.Show(" Win32 error = " + ex.Message);
}
catch (System.InvalidOperationException)
{
MessageBox.Show("File " + fileName + " started with verb " + verbToUse);
}
}
I have written an application that does batch printing of PDF files.
It's not possible to specify the printer settings that you want to use. It's not even possible if you use the COM interface with the Adobe Standard/Pro versions.
Your options are to either:
Buy a license to a third-party PDF renderer that you can use to convert the PDF to Bitmaps and use the PrintDocument to control the PrinterSettings
Use something like GhostScript to convert the PDF files to BMP files and then use the PrintDocument class to print the BMP files. You can then control the PrinterSettings.
private void startPrintingButton_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (DialogResult.OK == ofd.ShowDialog(this))
{
PrintDocument pdoc = new PrintDocument();
pdoc.DefaultPageSettings.PrinterSettings.PrinterName = "ZDesigner GK420d";
pdoc.DefaultPageSettings.Landscape = true;
pdoc.DefaultPageSettings.PaperSize.Height = 140;
pdoc.DefaultPageSettings.PaperSize.Width = 104;
Print(pdoc.PrinterSettings.PrinterName, ofd.FileName);
}
}
private void Print(string printerName, string fileName)
{
try
{
ProcessStartInfo gsProcessInfo;
Process gsProcess;
gsProcessInfo = new ProcessStartInfo();
gsProcessInfo.Verb = "PrintTo";
gsProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;
gsProcessInfo.FileName = fileName;
gsProcessInfo.Arguments = "\"" + printerName + "\"";
gsProcess = Process.Start(gsProcessInfo);
if (gsProcess.HasExited == false)
{
gsProcess.Kill();
}
gsProcess.EnableRaisingEvents = true;
gsProcess.Close();
}
catch (Exception)
{
}
}
This code will print PDF files as well as adjust the printing settings.