I have program pro1.exe that reads from input file, calculates result and writes it to output file.
Now I'm writing program test.exe, that tests it on different tests (fill input, run pro1 using Process.Start() and compares output with supposed)
Problem is following: after executing pro1.exe output file is empty. However, if I run it manually, it writes to output file.
Here is code how I execute pro1:
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = _applicationName;
processInfo.ErrorDialog = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
Process proc = Process.Start(processInfo);
_applicationName is a full path to exe file.
in debug I see, that process is starting, and ending without errors.
This is often caused by having a different WorkingDirectory. You likely need to set the WorkingDirectory property to match the executable's path.
Without this, when UseShellExecute == false, the working directory may not be the application's local path.
Related
I have multiple .gz files in a directory (2 or more), with at least one file missing the end of file marker. Our C# process is unable to read the file with missing end of file, but since they are coming from a third party we do not have control over how they are created.
As such, we've been running the following Linux command manually:
cat file1.gz file2.gz > newFile.gz
In order to automate this, I am looking for a way to leverage the Process functionality in C# to trigger the same command, but this would only be available in Cygwin or some other Linux shell. In my example, I'm using git bash but it could be Powershell or Cygwin or any other available Linux shell that runs on a Windows box.
The following code does not fail, but it does not work as expected. I am wondering if anyone has recommendations about how to do this or any suggestions on a different approach to consider?
Assume that the working directory is set and initialized successfully, so the files exist where the process is run from.
Process bashProcess = new Process();
bashProcess.StartInfo.FileName = #"..\Programs\Git\git-bash.exe";
bashProcess.StartInfo.UseShellExecute = false;
bashProcess.StartInfo.RedirectStandardInput = true;
bashProcess.StartInfo.RedirectStandardOutput = true;
bashProcess.Start();
bashProcess.StandardInput.WriteLine("cat file1.gz file2.gz > newFile.gz");
bashProcess.StandardInput.WriteLine("exit");
bashProcess.StandardInput.Flush();
.
.
.
bashProcess.WaitForExit();
My expectation is that newFile.gz is created
I was able to find a solution to my problem using a DOS command, and spawning a cmd Process from CSharp.
My code now looks like this, avoids having to launch a linux-based shell from Windows, and the copy command in windows does the same thing as cat:
Process proc = new Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = "cmd";
proc.StartInfo.Arguments = #"/C pushd \\server\folder && copy *.txt.gz /b
combined.gz";
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
System.Threading.Thread.Sleep(2000);
string line = proc.StandardOutput.ReadLine();
while (line != null)
{
output.Append(line);
line = proc.StandardOutput.ReadLine();
}
I am trying to run a process, hide its window and then print its output in my program. I am achieving it with this code:
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = path,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
Verb = "runas"
}
};
proc.Start();
while(!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
Console.WriteLine(line);
}
It works with other programs but for this one it's stopping at some point. My guess is that it sends too much messages, because before actually loading it spams a ton of messages that say: "Initializing... n%". It reads it until it reaches around 90-95% and then stops reading. My guess is that it can't read anymore because it sent too much messages. What can I do to read the whole output?
I found out how to make a workaround. It turns out the program actually needed input inbetween the initialization and the actual result. Thanks to #Alexandru Clonțea I decided that I would not run the process, but create a .bat file, which contains the following command:
program.exe > output.txt < input.txt
Where program.exe is the executable, output.txt is the file that is going to contain the output of the program and input.txt in my case is just an empty text file so I can just get some kind of an input and make the program finish.
I am writing a program that is running a batch file, and will need the output further in the program. this is my C# code:
public void ExecuteBatFile()
{
Process proc = null;
try
{
string targetDir = string.Format("C:\\Users"); //this is where mybatch.bat lies
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = "batch.bat";
proc.StartInfo.Arguments = string.Format("10"); //this is argument
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //this is for hiding the cmd window...so execution will happen in back ground.
proc.Start();
string output = proc.StandardOutput.ReadToEnd();
Console.WriteLine(output);
proc.WaitForExit();
}
catch (Exception ex)
{
Console.WriteLine("Exception Occurred :{0},{1}", ex.Message, ex.StackTrace.ToString());
}
}
}
Once I run I get this error though:
Exception thrown: 'System.InvalidOperationException' in System.dll
Exception Occurred :StandardOut has not been redirected or the process
hasn't started yet., at
System.Diagnostics.Process.get_StandardOutput() at
CefSharp.MinimalExample.Wpf.CallBatchFile.ExecuteBatFile() in
C:\Users\CefSharp.MinimalExamplemaster\CefSharp.MinimalExample.Wpf\CallBatchFile.cs:line
27
The batch file runs successfully, but then I'm not able to store the result into a variable. I can't get it to work in anyway. Has anyone got any suggestion?
This is my moch batch:
#echo off
cd C:\users\934874
echo.>silvio.txt
title This is your first batch script!
echo Welcome to batch scripting!
if "%errorlevel%"=="0" cls &Echo Success.
if "%errorlevel%"=="1" cls &Echo Fail
pause
The output that I'm expecting is either Success / Fail at console, and store that as a string into a variable.
Thanks in advance for your help
Need to redirect the output
proc.StartInfo.RedirectStandardOutput = true;
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx
Quoting from
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute(v=vs.110).aspx
When UseShellExecute is false, the WorkingDirectory property is not used to find the executable. Instead, it is used only by the process that is started and has meaning only within the context of the new process. When UseShellExecute is false, the FileName property can be either a fully qualified path to the executable, or a simple executable name that the system will attempt to find within folders specified by the PATH environment variable.
One of the simplest way is to make your batch file write its output to a text file. Then your main program can read the text file after the batch has finished.
If you really want to read from the standard output stream, please take a look at this other SO post:
Capturing console output from a .NET application (C#)
I need to execute a process in c:\. When I use Process.Processstartinfo it doesn't execute from c:\ and so its dependencies can't be found. It runs in my app's directory instead. How can I run it in the c:\ directory?
Have you set the WorkingDirectory?
process.StartInfo.WorkingDirectory = #"MyWorkingDirectoryPath";
e.g.:
var psi = new ProcessStartInfo();
psi.WorkingDirectory = #"MyWorkingDirectoryPath";
// set additional properties
Process proc = Process.Start(psi);
When the UseShellExecute property is false, gets or sets the working
directory for the process to be started. When UseShellExecute is
true, gets or sets the directory that contains the process to be
started.
Set ProcessStartInfo.WorkingDirectory to the working directory of the process you want to launch, i.e. in your case "C:\".
Due to the joys of UAC, I need to open an elevated command prompt programmatically and then redirect the standard input so I can use the time command.
I can open the link (a .lnk file) if I use
Process ecp = System.Diagnostics.Process.Start("c:/ecp.lnk");
however, if I use this method, I can't redirect the standardIn.
If I use the StartProcessInformation method (which works wonderfully if you are calling an exe)
ProcessStartInfo processStartInfo = new ProcessStartInfo("c:/ecp.lnk");
processStartInfo.UseShellExecute = false;
processStartInfo.ErrorDialog = false;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
Process process = new Process();
process.StartInfo = processStartInfo;
bool processStarted = process.Start();
StreamWriter inp = process.StandardInput;
StreamReader oup = process.StandardOutput;
StreamReader errorReader = process.StandardError;
process.WaitForExit();
I get the error message:
The specified executable is not a valid Win32 application.
Can anyone help me create an elevated command prompt which I can capture the standard input of? Or if anyone knows how to programatically escalate a command prompt?
In case no-one comes up with a better idea (pretty please), here is the work around one of the more devious in my office just came up with:
Copy cmd.exe (the link it pointing at this file)
Paste this file into a different directory
Rename the newly pasted file to something different
Set the permissions on this new file to Run As Administrator
You will still get the escalation dialog popping up, but at least you can capture the standardIn of this valid Win32 app!