I have a problem, I start cygwin commands with c#, what is working fine. The Problem is to set the working directory.
pathANDcommand = C:\cygwin\bin\ls.exe";
arg = " -lisa";
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = pathANDcommand;
startInfo.Arguments = arg;
output.Enqueue(arg + "\n" + "\n");
startInfo.WorkingDirectory = #"\cygdrive\c\Users\jhb\Source\Repos\myprogramm";
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
process.StartInfo = startInfo;
process.Start();
If I set startInfo.WorkingDirectory to a windows path the program will run, but the command does not run in the path I set.
Related
I've been trying to create a simple application to backup my Windows Server databases aswell as a whole server backup.
For this I want to use batch files which are being executed by my application.
I tried several approaches but for some reason it always fails so I'd be happy if you could help me out.
Batch file BACKUPSERVER:
wbadmin start backup -backupTarget:D: -include:C: -allCritical -quiet
I have to run the bat as administrator or it fails due to missing permissions.
C# code:
static Task<int> RunProcessAsync(string fileName)
{
............
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.Verb = "runas";
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C \"D:\\SQLBACKUP\\BACKUPSERVER.bat\"";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
Debugging says 'wbadmin wasnt found'. 'runas' activated or not doesn't make any difference.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = fileName;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = false;
// startInfo.Verb = "runas";
var process = new Process
{
StartInfo = { FileName = fileName },
EnableRaisingEvents = true
};
process.StartInfo = startInfo;
process.Exited += (sender, args) =>
{
tcs.SetResult(process.ExitCode);
process.Dispose();
};
process.Start();
Also doesn't work.
Any ideas?
EDIT:
I'm able to run commands like shutdown but wbadmin doesn't work whatsoever...
This is how I solved the problem:
Make sure ure compiling for 64bit if u intend to use your application on 64bit system, otherwise it will redirect to different subfolders and wont find 'wbadmin.exe'.
Run wbadmin with ProcessStart or run a batch but without direct cmd input, so use this with filename = batch file or wbadmin with startInfo.Arguments:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = fileName;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = false;
// startInfo.Verb = "runas";
var process = new Process
{
StartInfo = { FileName = fileName },
EnableRaisingEvents = true
};
process.StartInfo = startInfo;
process.Exited += (sender, args) =>
{
tcs.SetResult(process.ExitCode);
process.Dispose();
};
process.Start();
Make sure u request administrator rights
I made myself a proof of concept to test this tool to manage audio files.My purpose is to change sample rate. My first example works fine!
public class Test
{
public void SoxMethod()
{
var startInfo = new ProcessStartInfo();
startInfo.FileName = "C:\\Program Files (x86)\\sox-14-4-2\\sox.exe";
startInfo.Arguments = "\"C:\\Program Files (x86)\\sox-14-4-2\\input.wav\" -r 16000 output.wav";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = false;
startInfo.WorkingDirectory= "C:\\Program Files (x86)\\sox-14-4-2";
using (Process soxProc = Process.Start(startInfo))
{
soxProc.WaitForExit();
}
}
}
But when I want to add this tool in my bin folder but I get the exception: The directory name is invalid
public void SoxMethod()
{
var startInfo = new ProcessStartInfo();
startInfo.FileName = "bin/sox-14-4-2/sox.exe";
startInfo.Arguments = "bin/sox-14-4-2/input.wav -r 16000 output.wav";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = false;
startInfo.WorkingDirectory= "bin/sox-14-4-2";
using (Process soxProc = Process.Start(startInfo))
{
soxProc.WaitForExit();
}
}
Maybe its very obvious but I dont know what I'm doing wrong
Your working directory is wrongly set. Use AppDomain.CurrentDomain.BaseDirectory instead. That will make the Process to start at bin folder. Then, replace your file and your arguments to work relative to the working directory (thus remove the bin part of your path).
public void SoxMethod()
{
var startInfo = new ProcessStartInfo();
startInfo.FileName = "sox-14-4-2/sox.exe";
startInfo.Arguments = "sox-14-4-2/input.wav -r 16000 output.wav";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = false;
startInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
using (Process soxProc = Process.Start(startInfo))
{
soxProc.WaitForExit();
}
}
I want to redirect standardoutput of a Process in a richTextBox. Here is my process configuration,
string command = "/K perl C:\\Server.pl ";
ProcessStartInfo startInfo = new ProcessStartInfo();
Process proc = new Process();
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = command;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
proc.StartInfo = startInfo;
proc.OutputDataReceived += (s, ea) => this.richTextBox1.AppendText(ea.Data);
proc.Start();
proc.BeginOutputReadLine();
Here is my Server.pl file
print "Server1 \n";
while(1)
{
print "Server \n";
sleep 1;
}
But when I run the program the cmd.exe is just black and nothing printed in richTextBox. but when I change the
startInfo.RedirectStandardOutput = false;
I have this out put in my cmd.exe:
Server1
Server
Server
Server
...
How I can work around this issue ?
Might be as simple as disabling output buffering in your perl script. This is done using the $| special variable (see perlvar).
$| = 1;
print "Server1 \n";
...
I have created a Process to run command in CMD.
var process = Process.Start("CMD.exe", "/c apktool d app.apk");
process.WaitForExit();
How can I run this command without displaying actual CMD window?
You can use the WindowsStyle-Property to indicate whether the process is started in a window that is maximized, minimized, normal (neither maximized nor minimized), or not visible
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
Source:
Property:MSDN
Enumartion: MSDN
And change your code to this, becaeuse you started the process when initializing the object, so the properties (who got set after starting the process) won't be recognized.
Process proc = new Process();
proc.StartInfo.FileName = "CMD.exe";
proc.StartInfo.Arguments = "/c apktool d app.apk";
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.Start();
proc.WaitForExit();
There are several issues with your program, as pointed out in the various comments and answers. I tried to address all of them here.
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "apktool";
//join the arguments with a space, this allows you to set "app.apk" to a variable
psi.Arguments = String.Join(" ", "d", "app.apk");
//leave it to the application, not the OS to launch the file
psi.UseShellExecute = false;
//choose to not create a window
psi.CreateNoWindow = true;
//set the window's style to 'hidden'
psi.WindowStyle = ProcessWindowStyle.Hidden;
var proc = new Process();
proc.StartInfo = psi;
proc.Start();
proc.WaitForExit();
The main issues:
using cmd /c when not necessary
starting the app without setting the properties for hiding it
Try this :
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.WaitForExit();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "dcm2jpg.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "-f j -o \"" + ex1 + "\" -z 1.0 -s y " + ex2;
The original location (strange behaviour on another process via Process.Start(startInfo)) doesn't allow me post test code properly. I have to start a new question here.
Our C#(V3.5) needs to call a C++ executable to process a raw data file and generate result files for us.
It worked before with the following code (without ReadToEnd() or ReadLine() call):
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
Now the input raw data file changed (bigger than before). Our call to that executable will hang forever. Based on advice, I added ReadToEnd() or ReadLine() but it will hang on those calls. So I have to either use startInfo.UseShellExecute = true; or set
startInfo.UseShellExecute = false;
// and with
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
Don't know why?
Following are cases I tested:
working case:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = false;
startInfo.RedirectStandardOutput = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = path;
startInfo.Arguments = rawDataFileName;
//startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
try
{
Process correctionProcess = Process.Start(startInfo);
correctionProcess.WaitForExit();
}
working case:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = true;
startInfo.RedirectStandardError = false;//can be commented out
startInfo.RedirectStandardOutput = false;//can be commented out
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = path;
startInfo.Arguments = rawDataFileName;
startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
try
{
Process correctionProcess = Process.Start(startInfo);
correctionProcess.WaitForExit();
}
NOT working case (using ReadLine()):
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = path;
startInfo.Arguments = rawDataFileName;
//startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
try
{
Process correctionProcess = Process.Start(startInfo);
while (!correctionProcess.HasExited)
{
Log.logItem(LogType.Performance, "read errorMsg ####", "DPTM::correctData()", "");
string errorMsg = correctionProcess.StandardError.ReadLine(); // <-- Hangs here
Log.logItem(LogType.Performance, "read errorMsg", "DPTM::correctData()", "errorMsg=" + errorMsg);
string outputMsg = correctionProcess.StandardOutput.ReadLine();
Log.logItem(LogType.Performance, "read outputMsg", "DPTM::correctData()", "outputMsg=" + outputMsg);
Thread.Sleep(100);
}
}
NOT working case (using ReadToEnd()):
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = path;
startInfo.Arguments = rawDataFileName;
//startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
try
{
Process correctionProcess = Process.Start(startInfo);
while (!correctionProcess.HasExited)
{
Log.logItem(LogType.Performance, "read errorMsg ####", "DPTM::correctData()", "");
string errorMsg = correctionProcess.StandardError.ReadToEnd(); // <-- Hangs here!
Log.logItem(LogType.Performance, "read errorMsg", "DPTM::correctData()", "errorMsg=" + errorMsg);
string outputMsg = correctionProcess.StandardOutput.ReadToEnd();
Log.logItem(LogType.Performance, "read outputMsg", "DPTM::correctData()", "outputMsg=" + outputMsg);
Thread.Sleep(100);
}
}
NOT working case:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = path;
startInfo.Arguments = rawDataFileName;
//startInfo.WorkingDirectory = Util.GetParentDirectory(path, 1);
try
{
Process correctionProcess = Process.Start(startInfo);
Log.logItem(LogType.Performance, "read errorMsg ####", "DPTM::correctData()", "");
string errorMsg = correctionProcess.StandardError.ReadToEnd(); // <-- Hangs here!
Log.logItem(LogType.Performance, "read errorMsg", "DPTM::correctData()", "errorMsg=" + errorMsg);
string outputMsg = correctionProcess.StandardOutput.ReadToEnd();
Log.logItem(LogType.Performance, "read outputMsg", "DPTM::correctData()", "outputMsg=" + outputMsg);
correctionProcess.WaitForExit();
}
you are deadlocked on the error/output buffer. Your second process is waiting for the buffer to free up while you are waiting for that process to finish. You need to asynchronously read output/error streams to prevent that.
Looking at your MSDN sample: wow that sample is really confusing... It would've been easier to follow if they just limited it to std out or std error.
You need to first set data handler
correctionProcess.OutputDataReceived += new DataReceivedEventHandler(OutputDataHandler);
and then call
p.BeginOutputReadLine();
Just like comment [confusingly] advises do no try to read output there. Use handler instead.
private void OutputDataHandler(object sendingProcess, DataReceivedEventArgs data)
{
if (data.Data != null)
{
// append data.Data to your internal buffer (StringBuilder?)
}
}