C# PSExec to execute multiple path from StreamReader parsing - c#

I'm trying to learn how C# could read and parsing multiple line from text file using streamReader and afterward process each of line with PSExec
Inside cocomand.txt have multiple line example
c:/command1.cmd
c:/command2.bat
c:/command3.cmd
private static void calleachline()
{
string pathx = #"c:\cocomand.txt";
using (StreamReader reader = new StreamReader(new FileStream(pathx, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.ASCII))
{
while ((!reader.EndOfStream))
{
System.Diagnostics.Process cmd = new System.Diagnostics.Process();
cmd.StartInfo.FileName = #"psexec.exe";
cmd.StartInfo.Arguments = #"\\localhost";
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.Start();
if (!cmd.WaitForExit(cmd2))
{
ExecutePSKill(cmd);
}
else
{
//
}
}
}
Trying to understand from few thread but with my lack knowledge seems this still doesn't work

Related

Edit image source C#

I'm trying to edit a image file where instead of path i should be able to provide ImageSource as parameter.
//EditCode:
Process proc = Process.Start(Path);
proc.EnableRaisingEvents = true;
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "edit";
proc.StartInfo = startInfo;
proc.Exited += new EventHandler((s, e) => myProcess_Exited(s, e, obj.ToString()));
The above code works well when i pass the Path of the image file as the parameter. But now i have only the ImageSource.
//ImageSourceCode:
private BitmapFrame LoadImage(string path)
{
BitmapDecoder decoder = null;
if (File.Exists(path) && (path != null))
{
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
return decoder.Frames.FirstOrDefault();
}
else
return null;
}
The above code gets the path and convert an image as a source(BitmapFrame) and returns it.
Now i need this BitmapFrame to be passed in some function and edit the particular image file in paint and save it.
I neeed somthing like this,
Process proc = Process.Start(`ImageSource`);// Instead of path i need to pass the Image Source.
proc.EnableRaisingEvents = true;
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "edit";
proc.StartInfo = startInfo;
How can i achieve this?
You can't.
ProcessStartInfo starts a new process that is outside the App Domain of your application. You can't pass it structures in memory within your app domain as a command line parameter.

Printing PDF using ReportViewer from C# windows

Here is my creating PDF code, which will open the PDF document .
public void createPDF(string Reportpath, ReportViewer RV)
{
Warning[] warnings;
string[] streamids;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
byte[] bytes = RV.LocalReport.Render("pdf", null, out mimeType, out encoding, out extension, out streamids, out warnings);
try
{
FileStream fs = new FileStream(Reportpath, FileMode.Create);
Thread.Sleep(1000);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
Thread.Sleep(1000);
System.Diagnostics.Process.Start(Reportpath);
}
catch (Exception ex)
{
MessageBox.Show("Report could not be created...\n" + ex.Message);
}
}
instead of opening i need to print the pdf directly using reportviewer or any other way to print that pdf document??.
I think this MSDN article gives a good solution to your problem
got some idea from the following link
http://www.codeproject.com/Tips/598424/How-to-Silently-Print-PDFs-using-Adobe-Reader-and
send the pdf to adobe reader to print....
public static Boolean PrintPDFs(string pdfFileName)
{
try
{
Process proc = new Process();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.Verb = "print";
//Define location of adobe reader/command line
//switches to launch adobe in "print" mode
proc.StartInfo.FileName =
#"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe";
proc.StartInfo.Arguments = String.Format(#"/p /h {0}", pdfFileName);
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
if (proc.HasExited == false)
{
proc.WaitForExit(10000);
}
proc.EnableRaisingEvents = true;
proc.Close();
KillAdobe("AcroRd32");
return true;
}
catch
{
return false;
}
}

Deadlock while writing to Process.StandardInput

I'm developping an application and I have a problem with a deadlock.
My code looks like that :
Process p = new Process(); // That using an other application
Then I'm sending an .xml-file to this process:
XmlSerializer xs = new XmlSerializer(data.GetType());
using (var ms = new MemoryStream())
{
var sw = new StreamWriter(ms);
XmlWriter xmlwriter = XmlWriter.Create(sw, xmlWriterSettings);
xmlwriter.WriteProcessingInstruction("PipeConfiguratorStyleSheet", processing);
xs.Serialize(xmlwriter, data);
xmlwriter.Flush();
ms.Position = 0;
var sr = new StreamReader(ms);
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
p.StandardInput.WriteLine(line);
Console.WriteLine(line);
p.BeginOutputReadLine();
p.CancelOutputRead();
}
}
So actually I can send a part of my .xml-file to my process but at some point I'll get a deadlock.
I guess I don't knoy how to use BeginOutputReadLine() correctly.
First off, why don't you use the Process.StandardInput-property directly as your target, like
var process = new Process
{
// all your init stuff
};
var xmlSerializer = new XmlSerializer(data.GetType());
var xmlwriter = XmlWriter.Create(process.StandardInput, xmlWriterSettings);
xmlSerializer.Serialize(xmlwriter, data);
Otherwise, the msdn-entry gives a clear howto for using Process.BeginOutputReadLine(), which you can remodel to
var autoResetEvent = new AutoResetEvent(false); // this mutex acts as our bouncer for the reading-part
var process = new Process
{
// all your init stuff
};
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, args) => {
// TODO you could read the content here with args.Data
autoResetEvent.Set();
};
process.Start();
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
{
var xmlSerializer = new XmlSerializer(data.GetType());
var xmlwriter = XmlWriter.Create(streamWriter, xmlWriterSettings);
xmlSerializer.Serialize(xmlwriter, data);
}
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
while (!streamReader.EndOfStream)
{
var line = streamReader.ReadLine();
process.StandardInput.WriteLine(line);
Console.WriteLine(line);
process.BeginOutputReadLine();
autoResetEvent.WaitOne();
}
}
}
// TODO closing the process.StandardInput, exiting process, ...
Anyway - I know this should be a comment - is there a specific reason why you are waiting for your process to write something?
The StandardOutput stream can be read synchronously or asynchronously.
Methods such as Read, ReadLine, and ReadToEnd perform synchronous read
operations on the output stream of the process. These synchronous read
operations do not complete until the associated Process writes to its
StandardOutput stream, or closes the stream. In contrast,
BeginOutputReadLine starts asynchronous read operations on the
StandardOutput stream. This method enables a designated event handler
for the stream output and immediately returns to the caller, which can
perform other work while the stream output is directed to the event
handler.
Which means, that if your process does not write anything (and you are waiting), you are spinning for response endlessly ...
EDIT
You should additionally add a handler to Process.ErrorDataReceived like
process.StartInfo.RedirectStandardError = true;
process.ErrorDataReceived += (sender, args) => {
// TODO do something with the response of args.Data
autoResetEvent.Set();
};
and
while (!streamReader.EndOfStream)
{
var line = streamReader.ReadLine();
process.StandardInput.WriteLine(line);
Console.WriteLine(line);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
autoResetEvent.WaitOne();
}
to handle error-cases as well (whatever that may mean).

StandardInputEncoding for ProcessStartInfo?

When i am adding service to windows manually by typing in CMD something like this:
"C:\Program Files (x86)\Windows Resource Kits\Tools\instsrv.exe" "some-pl-char-ąźńćńół" "C:\Program Files (x86)\Windows Resource Kits\Tools\srvany.exe"
... everything is good with service name, but when i try do that in c#:
ProcessStartInfo startInfo = new ProcessStartInfo();
Process myprocess = new Process();
startInfo.FileName = "cmd";
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
myprocess.StartInfo = startInfo;
myprocess.Start();
StreamWriter sw = myprocess.StandardInput;
StreamReader sr = myprocess.StandardOutput;
Thread.Sleep(200);
string command = ...
^ "C:\Program Files (x86)\Windows Resource Kits\Tools\instsrv.exe" "some-pl-char-ąźńćńół" "C:\Program Files (x86)\Windows Resource Kits\Tools\srvany.exe"
sw.WriteLine(command);
sw.WriteLine("exit");
Thread.Sleep(200);
sw.Close();
sr.Close();
then name of created service is: some-pl-char-¦č˝Š˝ˇ-
Why there is problem with code page?
There is something like StandardInputEncoding for ProcessStartInfo?
My active code page in CMD (using chcp) is 852. (Polish)
Arguments belongs assigned to the Arguments property and backslashes needs to be escaped by another one. \ -> \\
Updated:
using (var process = new Process())
{
var encoding = Encoding.GetEncoding(852);
var psi = new ProcessStartInfo();
psi.FileName = "cmd";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.StandardOutputEncoding = encoding;
process.StartInfo = psi;
process.Start();
using (var sr = process.StandardOutput)
using (var sw = new StreamWriter(process.StandardInput.BaseStream, encoding))
{
var command = "....";
sw.WriteLine(command);
// etc..
}
}
I had a very similar issue. Although I was working with VB.net, it fixed my issue. I couldnt run the command unless this was set.
startInfo.FileName = "cmd.exe /c";
instead of
startInfo.FileName = "cmd";

Process hangs when trying to read bytes from buffer to int. Wkhtmltopdf

My method creates PDF out of HTML content with Wkhtmltopdf program with Process. I can't find a reason why it hangs. When there is a big string with HTML, i suppose it hangs when there are 30 pages or more. But everything works fine if there are less pages. Wkhtmltopdf.exe process i can see at the Task Manager, it does not exit forever. When i stop my MVC project with hanged Wkhtmltopdf, it creates normally PDF like it would wait for something.. Manually, of course, Wkhtmltopdf creates everything without any problem.
This is not duplicate of this post. Here i have issues when trying to read bytes into int.
public IActionResult createPdf()
{
string html = "content";
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "...\\wkhtmltopdf.exe";
psi.WorkingDirectory = "...\\wkhtmltopdf\\bin";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.StandardOutputEncoding = System.Text.Encoding.UTF8;
psi.Arguments = "-O landscape --footer-left qwe --footer-center [page]/[topage] --footer-right --footer-font-size 9 --no-stop-slow-scripts --zoom 0.8 --dpi 300 - - ";
p = Process.Start(psi);
byte[] pdf = null;
try
{
// Get PDF as bytes without temp files
using(StreamWriter stdin = new StreamWriter(p.StandardInput.BaseStream, Encoding.UTF8))
{
stdin.AutoFlush = true;
stdin.Write(html);
}
byte[] buffer = new byte[32768];
using(var ms = new MemoryStream())
{
while(true)
{
// HANGS HERE!!!
int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if(read <= 0)
{
break;
}
ms.Write(buffer, 0, read);
}
pdf = ms.ToArray();
}
}
...
}
I managed to solve this problem through merging separated pdf files into one using PdfSharp, instead of passing concatenated content to wkhtmltopdf as one. It lasts a little bit longer, but at least it works. Except of PdfSharp library (if you use MVC as me, then PdfSharp.Core to exclude version warnings), probably you would need to install System.Text.Encoding.CodePages to exclude encoding error that PdfSharp may cause. My method does not use temp files and works only with bytes, at the end it sends created pdf to a browser.
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
public IActionResult createPdf()
{
string html = "";
byte[] pdf = null;
using(PdfDocument doc = new PdfDocument())
{
for(int i = 0; i < files.Length; i++)
{
html = "html content";
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "...\\wkhtmltopdf.exe";
psi.WorkingDirectory = "...\\wkhtmltopdf\\bin";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.StandardOutputEncoding = System.Text.Encoding.UTF8;
psi.Arguments = "-O landscape --footer-left qwe --footer-center [page]/[topage] --footer-right --footer-font-size 9 --no-stop-slow-scripts --zoom 0.8 --dpi 300 - - ";
p = Process.Start(psi);
using(StreamWriter stdin = new StreamWriter(p.StandardInput.BaseStream, Encoding.UTF8))
{
stdin.AutoFlush = true;
stdin.Write(html);
}
byte[] buffer = new byte[32768];
byte[] currentPdf = null;
using(var ms = new MemoryStream())
{
while(true)
{
int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if(read <= 0)
{
break;
}
ms.Write(buffer, 0, read);
}
currentPdf = ms.ToArray();
}
p.StandardOutput.Close();
p.WaitForExit(10000);
p.Close();
MemoryStream currentPDF = new MemoryStream(currentPdf);
// Merge separated pdfs into one
// Solves encoding errors
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using(PdfDocument pdfDoc = PdfReader.Open(currentPDF, PdfDocumentOpenMode.Import))
{
for(int j = 0; j < pdfDoc.PageCount; j++)
{
doc.AddPage(pdfDoc.Pages[j]);
}
}
currentPDF.Close();
}
// Get merged pdfs as bytes
MemoryStream rms = new MemoryStream();
doc.Save(rms, false);
pdf = rms.ToArray();
rms.Close();
}
MemoryStream PDF = new MemoryStream(pdf);
// Return PDF to browser
return new FileStreamResult(PDF, "application/x-msdownload")
{
FileDownloadName = "mergedPdfs.pdf"
};
}

Categories