I have graphviz dot.exe file that I call with parameter -Tpng (output type is png, but I don't care if it is in png, bmp, or any other). I start it in C# code:
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = path;
psi.UseShellExecute = false;
psi.Arguments = "-Tpng";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
Process p = Process.Start(psi);
Then, I write input
p.StandardInput.WriteLine(input);
input is defined before, it's a string. Input is valid, tested manually.
Then, I need to read output that graphviz prints into standart output and parse it to Image.
I've tried to read memory stream, but I was either unable to read it, or, after reading, the memory stream was locked (threw exception when tried Image.FromStream(myMemoryStream);).
I was able to load output to string
string output = "";
while (true)
{
string newOutput = p.StandardOutput.ReadLine();
output += newOutput;
if (newOutput == String.Empty)
break;
}
I've tried to parse this string as described in this answer, but it threw exception (string is not valid).
How can I get Image from the dot.exe output?
From the comments it seems the program is expecting the StandardInput to be finished before returning the content. Close the StandardInput to achieve it:
p.StandardInput.WriteLine(input);
p.StandardInput.BaseStream.Close();
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.
This is the code I use to write my file to the app_data folder:
var filename = Server.MapPath("~/App_Data") + "/" thefilename;
var ms = new MemoryStream();
file.InputStream.CopyTo(ms);
file.InputStream.Position = 0;
byte[] contents = ms.ToArray();
var fileStream = new System.IO.FileStream(filename, System.IO.FileMode.Create,
System.IO.FileAccess.ReadWrite);
fileStream.Write(contents, 0, contents.Length);
fileStream.Close();
This writes the file fine. However, if there is a virus on it, Bitdefender does not delete this file, unless I go on the IIS and manually try to open/move the file. If I do that, then it is instantly deleted.
If I copy and paste the test virus file into the app_data folder directly then Bitdefender removes it instantly.
I have tried to use various ways to read/move the file with System.IO.File.Move/Open/ReadAllLines. Yet, nothing triggers bit defender to remove the file.
The only thing I got to work was creating a new process to open the file. However, I don't want to be doing that on the server. I am looking for a different solution. This is the code that I've used to open the file, which does cause Bitdefender to scan and remove the infected file:
Process cmd = new Process();
cmd.StartInfo.FileName = filename;
cmd.Start();
A solution with System.IO.File.Open would be best for me in this situation, but I cannot figure out why it isn't working. Alternately, a way to trigger Bitdefender to instantly scan the file would also be a viable solution.
I have solved the issue with the help of #sheavens and following code:
Process cmd = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = #"C:\Program Files\Bitdefender\Endpoint Security\product.console.exe";
var args = String.Format("/c FileScan.OnDemand.RunScanTask custom path=\"{0}\" infectedAction1=delete", filename);
startInfo.Arguments = args;
cmd.StartInfo = startInfo;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.RedirectStandardError = true;
var result = cmd.Start();
This creates a new process and looks up the bitdefender exe, and then runs a command to scan the file at the provided path.
My C# program needs to send data to a 3rd-party program via its standard input. However, the program waits for the input stream to reach EOF before processing. Here my code:
// Starts the process.
var process = new Process();
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.FileName = "foo.exe";
process.Start();
// Sends data to child process.
var input = process.StandardInput;
input.WriteLine("eval('2 * PI')");
input.Flush();
input.Close();
// Reads the result.
var output = process.StandardOutput;
var result = output.ReadLine();
The child program won't do anything and my C# code becomes stuck at output.ReadLine() call. However if I kill the C# process, then the child starts to work exactly on the data I've sent. How can I make the child encounter an EOF while I'm still alive?
StreamWriter might not be sending an actual eof when it closes the stream. You could try writing your own to the stream just before you close it. Something like this might work:
input.Write((char)26);
You may have to find out what the process expects for eof.
I want to be able to read a screen shot of a web site, and am attempting to use phantomjs and ASP.NET.
I have tried using page.render which would save the screen shot to a file. It works as a console application, but not when I call it from an asp.net handler. It is probably due to file permissions, since simple applications (like hello.js) work fine.
That is okay, my preference would be not to write to a file, but to deal with the bytes and return an image directly from the handler.
I am a bit lost as to how to do that. I noticed a method called page.renderBase64, but do not know how to use it.
Currently I am using an IHttpHandler.
There is a similar question here, but that person eventualy dropped phantomjs. I like the look of it and want to continue using it if possible.
Running Phantomjs using C# to grab snapshot of webpage
According to your last comment you can do the following in phantom js file:
var base64image = page.renderBase64('PNG');
system.stdout.write(base64image);
in C#:
var startInfo = new ProcessStartInfo {
//some other parameters here
...
FileName = pathToExe,
Arguments = String.Format("{0}",someParameters),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
WorkingDirectory = pdfToolPath
};
var p = new Process();
p.StartInfo = startInfo;
p.Start();
p.WaitForExit(timeToExit);
//Read the Error:
string error = p.StandardError.ReadToEnd();
//Read the Output:
string output = p.StandardOutput.ReadToEnd();
In your output variable you can read base64 returned from phantomJS and then do what you have planned with it.
Use the wrapper for Phantomjs from here nreco wrapper
You can get js for rastor here : rastorize
And then the following code in C# would do the job.
var phantomJS=new PhantomJS();
phantomJS.Run("rasterize.js", new[] { "http://google.com","ss.pdf" });
This question stemmed from my lack of understanding of what a base64 string actually was.
In the javascript file that phantomjs runs, I can write the base64 image directly to the console like so:
var base64image = page.renderBase64('PNG');
console.log(base64image);
In the c# code that runs phantomjs, I can convert the console output back to bytes and write the image to the response, like so:
var info = new ProcessStartInfo(path, string.Join(" ", args));
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
var p = Process.Start(info);
p.Start();
var base64image = p.StandardOutput.ReadToEnd();
var bytes = Convert.FromBase64CharArray(base64image.ToCharArray(), 0, base64image.Length);
p.WaitForExit();
context.Response.OutputStream.Write(bytes, 0, bytes.Length);
context.Response.ContentType = "image/PNG";
This seems to avoid file locking issues I was having.
Using CasperJS coupled with PhantomJS , I've been getting beautiful shots of webpages.
var casper = require('casper').create();
casper.start('http://target.aspx', function() {
this.capture('snapshot.png');
});
casper.run(function() {
this.echo('finished');
});
I highly recommend you check out that tool. I'm still not sure how to do the post-backs though..
Set the 'WorkingDirectory' property of ProcessStartInfo object in order to specify the saving location of the file.
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");