I have the following code:
strCmdText = "/C cppcheck.exe --enable=all " + StrFile1 + " 2> " + StrfolderOut + "\\fileOut.txt";
//Console.WriteLine(strCmdText);
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
but when I'm trying to read it afterwards is like the program executes it after finishing the execution
I ran 2 test:
First one I use as an input "file1.txt" (fileOut does not exist) the file is created by cmd redirecting the output using ">". When trying to read it it says "the file does not exist"
Secondly, I use "file2.txt" as an input (fileOut does existe and has the info of file2.txt) and it reads but the content of "file1.txt".
So I think that the cmd command runs after finishing the execution. I triple checked the paths so is not a problem since im reading the path using file folder gui.
I'm using this code to read
public List<Error> LeerArchivo()
{
List<Error> listaErrores = new List<Error>();
string #folderLocation = StrfolderOut + "\\fileOut.txt";
Console.WriteLine(#folderLocation);
//OpenFileDialog openFileDialog = new OpenFileDialog();
//openFileDialog.ShowDialog();
if (File.Exists(#folderLocation))
{
try
{
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
using (StreamReader sr = new StreamReader(#folderLocation))
{
string line = "";
// Read and display lines from the file until the end of
// the file is reached.
Console.WriteLine("reading");
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
Console.WriteLine(line);
}
}
catch (Exception e)
{
// Let the user know what went wrong.
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
else
{
Console.WriteLine("no existe");
}
return listaErrores;
}
I manage it to work, I used:
Process process = new Process();
process.StartInfo.FileName = "CMD.exe";
{do cppcheck... etc}
process.Start();
process.WaitForExit();
It works now, I think it is since the main program waits for that process to finish. Maybe I can have a deeper explanation of what happening.
Related
I have a lot of IIS logs that need to be inserted into a SQL Server database. After some research it looks like Log Parser is the way to go but I am having a hard time figuring out how to automate the process. We have hundreds of these files, some of which are up to 3Gb in size.
The console command to insert a file is
"C:\Program Files (x86)\Log Parser 2.2\LogParser.exe" "SELECT * INTO LogTable FROM C:\Logs\ex1234.log" -i:iisw3c -o:SQL -server:ServerName -database:DatabaseName -driver:"SQL Server" -createTable:ON
In order to iterate through the directories and files I created a small console app in which the main method enumerates through the directories and then sends each file to a method that runs the Log Parser:
static void RunLogParser(string fileName)
{
var logParserPath = #"""C:\\Program Files (x86)\\Log Parser 2.2\\LogParser.exe""";
var query = $"\"SELECT * INTO LogTable FROM {fileName}\"";
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = logParserPath + query + "-i:iisw3c -o:SQL -server:ServerName -database:DatabaseName -driver:\"SQL Server\" -createTable:ON",
CreateNoWindow = true,
UseShellExecute=false
};
try
{
using (var process = Process.Start(startInfo))
{
process.WaitForExit();
}
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
Console.ReadKey();
}
When I run this nothing seems to happen. Executing the command from the console takes about 20 seconds to insert a test file, but when I run this same command from the code nothing.
I have also tried using Log Parser as the FileName arg in the ProcessStartInfo but when the process executes all that happens is that the command window seems to display the arguments for the Log Parser command with an error message but I can't the window closes too fast to read the message.
Edit: Solved
It seems that I had a typo, much to my chagrin. I changed the ProcessStartInfo filename to the LogParser.exe from cmd.exe, added a space after the select statement and changed the args to a literal string and double quoted the driver argument.
static void RunLogParser(string fileName)
{
var logParserPath = #"""C:\\Program Files (x86)\\Log Parser 2.2\\LogParser.exe""";
var query = $"\"SELECT * INTO LogTable FROM {fileName}\"";
var startInfo = new ProcessStartInfo
{
FileName = logParserPath ,
Arguments = query + #" -i:iisw3c -o:SQL -server:ServerName -database:DatabaseName -driver:""SQL Server"" -createTable:ON",
CreateNoWindow = true,
UseShellExecute=false
};
try
{
using (var process = Process.Start(startInfo))
{
process.WaitForExit();
}
}
catch(Exception ex)
{
throw new Exception(ex.Message);
}
}
I am a programming teacher and I am developing an automated checker for the students HWs (All are Console Apps). Basically, I run the student code using some Process.Start() (with some input file) and check if its output is as expected.
If, for some reason, the student code did no complete succesfully, I send them the exception thrown by their code using the process Standart Error redirection.
However, I want to do better then that. I want to find the input line written to the process StandartInput afterwhich their exception took place. How can I do that? My current code is more or less:
ProcessStartInfo psi = new ProcessStartInfo(students_exe_path);
psi.UseShellExecute = false;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
String randomInputFile = randomInputFilesFolder + "\\" + "test.txt";
psi.WorkingDirectory = randomInputFilesFolder;
Process p = Process.Start(psi);
StreamWriter inputWriter = p.StandardInput;
String[] inputLines = File.ReadAllLines(randomInputFile);
foreach (String line in inputLines)
{
// here I wanted to read the standart error so far (before writing next input line)
String errorTextBefore = p.StandardError.ReadToEnd(); // can not use this because blocks progress.
inputWriter.WriteLine(line); // sending next input line to students app
// here I wanted to read the standart error so far (after writing next input line)
String errorTextAfter = p.StandardError.ReadToEnd(); // can not use because blocks
if (errorTextBefore != errorTextAfter) Console.WriteLine("Line {0} caused the exception",line);
}
Or maybe I can check from p.StandartInput which text was not "consumed" by the process?
Tamir
I am using ImageMagick C# tool to convert PDF to JPG by calling the executable from C#. I believe I set up the command correctly but it does not execute; it just passes through Process.Start(startInfo) without executing it. I do see the command prompt popping up but nothing happens.
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
string arguments = string.Format("{0} {1}", PDFfile, PNGfile);
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe");
startInfo.Arguments = arguments;
Process.Start(startInfo);
I wasn't sure if it was because of the double quotes I added to each argument before hand but after commenting it out and running it again, it still skipped over. Any thoughts?
Edit: To add some clarity, I am expecting a JPG files from a PDF but I see no output file from this part of code. I ran the following in my command prompt to convert PDF to JPG
"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.PDF" "C:\Users\rwong\Desktop\RoundPoint\1000965275\1000965275_157_Credit File_10.png"
I explicitly called the convert.exe for clarity sake in my code. The command works fine in command prompt but when coping the structure over to C# it doesn't do anything. I see the code step into it but it continues without an error.
Edit2: Upon request below is the code and output for a Process Exit code
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = '"' + Loan_list[f] + '"';
string PNGfile = '"' + PNGPath + '"';
try
{
Process myprocess = null;
string[] arguments = { PDFfile, PNGfile };
myprocess=Process.Start(#"C:\ProgramFiles\ImageMagick6.9.2Q16\convert.exe", String.Join(" ", arguments));
Console.WriteLine("Process exit code: {0}", myprocess.ExitCode);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Process exit code: 1
Assuming that you are right and there was a problem (rather than the process just executed very quickly and exited), you can check the return code as follows:
if (Process.Start(startInfo) == null)
{
int lastError = Marshal.GetLastWin32Error();
}
You then go here to look up the error code:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
Hopefully, that vendor actually sets an error code on failure (they may or may not).
I am using psexec.exe to install some software on a large amount of computers. I would like to be able to catch the %ERRORLEVEL% (or its c# equivalent) and write them to a TXT file. ( cmd.exe exited on 6440-nbpb00f51w with error code 0.)
After extensive research, I am finding several possibilities. My end-goal will be to have a .CSV file. Each row would have the computer name and the output of the psexec command. Using this data I will be able to determine which computers the update was successful on.
string[] pcnamearray = new string[] {"COMPUTERNAME1", "COMPUTERNAME2"};
foreach (string i in pcnamearray)
{
Process p = new Process();
string psexeclaunch = "psexec.exe";
p.StartInfo.FileName = psexeclaunch;
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.UseShellExecute = true;
p.StartInfo.CreateNoWindow = false;
string arg = "/silent";
p.StartInfo.Arguments = #" -i \\" + i + #" -u mydomain\admin -p mypassword -h -e cmd.exe /c start \\networkserver\sw\myfile.exe" + arg;
p.Start();
}
I am not here looking for someone to write the code for me. I am here to ask people for their advice, or past experiences with this. I know there are several different methods available. Ideally, I would prefer to have a short sweet line for each result, but if i have to take the entire output and use macros to shave them down to a more readable form, that is fine too.
So far, I have tried:
Console.WriteLine(p.StandardOutput.ReadToEnd());
And...
System.IO.File.WriteAllLines(#"C:\Users\areu2447\Desktop\UpdateDAT\Final\out.txt", lines);
And...
FileStream filestream = new FileStream(#"C:\Users\areu2447\Desktop\UpdateDAT\Final\out.txt", FileMode.Append);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
The last one seems to me like the best one but cannot seem to get it to work. I have tried including it in my foreach loop, but file is in use by another process, so after looking into it i found that it needed to be on its own. Even with it alone, i still cannot get it to work.
Please help/advise!
I was able to get it to actaully modify my TXT file, even though there was nothing added to it, by using the following:
System.IO.StreamReader reader = p.StandardOutput;
String sRes = reader.ReadToEnd();
StreamWriter SW;
SW = File.CreateText(#"C:\Users\areu2447\Desktop\UpdateDAT\Final\out.txt");
SW.WriteLine(sRes);
SW.Close();
Console.WriteLine("File Created Successfully");
reader.Close();
I would recommend using System.Management.Automation to create a PowerShell pipeline and run the script in process.
Executing PowerShell scripts from C#
so I have a small chunk of code that detects files in a folder and systematically zips them after they become a certain age. I'm now working on a piece of code to unzip files of a certain date-range at user request for use in the software.
My issue is that the command-line string to zip files works great, but the unzip does not... below is the excerpt of code showing how I unzip, please let me know what I should do differently to ensure unzipping. thanks!
private void UnZipFile()
{
if (myRecord == null)
{
if (File.Exists(zipInfo.FullName))
{
Process LogUnzipper = new Process();
//32-bit system
if (File.Exists("c:\\Program Files\\WinZip\\WZZIP.exe"))
{
//WZZIP.exe being the WinZip executable
LogUnzipper.StartInfo.FileName = "c:\\Program Files\\WinZip\\WZZIP.exe";
}
//64-bit system
else if (File.Exists("c:\\Program Files (x86)\\WinZip\\WZZIP.exe"))
{
//WZZIP.exe being the WinZip executable
LogUnzipper.StartInfo.FileName = "c:\\Program Files (x86)\\WinZip\\WZZIP.exe";
}
//here is where I think I'm screwing up something..
string action = "-e " + "\"" + zipInfo.FullName + "\"" + " \"" + zipInfo.DirectoryName + "\"";
//happen in background
LogUnzipper.StartInfo.CreateNoWindow = true;
LogUnzipper.StartInfo.UseShellExecute = false;
LogUnzipper.StartInfo.Arguments = action;
LogUnzipper.Start();
while (!LogUnzipper.HasExited)
{
LogUnzipper.WaitForExit(500);// 1/2 sec
}
//adding break point at this line yields no unzipped Log file :(
}
...
my thoughts are that I'm somehow calling the cmd wrong in string action? even though if I test it in a windows command prompt that's correct formatting.
***it should be noted that ZipInfo.FullName is something along the ex: "C:\Users\16208\Software\Beta\logs\6_2013\Log_10AM_to_11AM.zip" as far as formmat, so I am giving an accurate path to the zipped Item.
You can use some free and open-source .Net library for zipping and unzipping (as SLaks suggested). For example DotNetZip.
using (ZipFile decompress = ZipFile.Read(ZipFilePath))
{
foreach (ZipEntry e in decompress)
{
e.Extract(TargetPath, ExtractExistingFileAction.OverwriteSilently);
}
}
As for your code, waiting half a second may not be enough for unzipping to complete. Also you can try running your unzip command in a command line and check the output.
If you have WinZip installed try this:
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", #"/c start winzip32 -e " + fileName + #" C:\SomeDirectory");
rocStartInfo.UseShellExecute = false;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit();
Where fileName is the full path to your *.rar file.