CLI Commands + Arguments are not executing correctly. - c#

I`m working in the CLI commands in my Visual Studio C# application. This application does the interface with the Flash Programmer 2 (Texas Instruments Software to bootload the firmware in CC2560) using CLI ( Command-Line interface).
I checked some examples in StackOverflow, but I didn't have success to implement the solutions.
Steps of my application:
Select the serial port
Open the console
execute the srfprog.exe
execute the command line (srfprog -t soc(COM84,CC2650) -e -p -v -f c:\test.bin )
Check if the programming was a success
My file is located in: D:\Projects\Test_Fixture\Test_Fixture_Visual_Studio\SmartRF Tools\Flash Programmer 2\bin\srfprog.exe
When I execute this in my CMD (windows) the Prompt window shows
After this screen pop up I sent the commands to program the chip
srfprog -t soc(COM84,CC2650) -e -p -v -f c:\test.bin
This command will program and verify the code in the microcontroller CC2650 as show in the screenshot below:
The programming is perfect.
However when I run(Click the button - Load Firmware) my application open and close Shell window immediately. As shown in the figure below
My code is below:
private void button2_Click(object sender, EventArgs e)
{
System.Diagnostics.Process CC2650 = new System.Diagnostics.Process();
CC2650.StartInfo.FileName = #"D:\Projects\Test_Fixture\Test_Fixture_Visual_Studio\SmartRF Tools\Flash Programmer 2\bin\srfprog.exe";
CC2650.StartInfo.Arguments = "srfprog -t soc(COM84,CC2650) -e -p -v -f c:\test.bin"; //argument
CC2650.StartInfo.UseShellExecute = false;
CC2650.StartInfo.RedirectStandardOutput = true;
CC2650.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
CC2650.StartInfo.CreateNoWindow = false; //not diplay a windows
CC2650.Start();
string output = CC2650.StandardOutput.ReadToEnd(); //The output result
CC2650.WaitForExit();
}
In this test I`m using the fixed COM port. Later I will select the port.
Why my software is falling and doesn`t load the firmware?
Thank you for your attention and time.

Your code seems to be doubling up on srfprog by including it in the arguments. Filename defines the executable and Arguments should just be the stuff that comes after the Filename.
CC2650.StartInfo.Arguments = "-t soc(COM84,CC2650) -e -p -v -f c:\test.bin";

As mentioned before you don't need to pass the program name again in the arguments. To inspect what is happening please use code below. It will read the output and the errors in an async approach so we can analyse the output while the srfprog.exe is running.
I don't have any C# compiler here so I could not test this code before writing here, maybe you will have to change something to make it work. Please try it and let my know what will be printed in your Visual Studio output console.
// Add "using System.Diagnostics;"
private void button2_Click(object sender, EventArgs e)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"D:\Projects\Test_Fixture\Test_Fixture_Visual_Studio\SmartRF Tools\Flash Programmer 2\bin\srfprog.exe";
startInfo.Arguments = "-t soc(COM84,CC2650) -e -p -v -f c:\test.bin";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
Process process = new Process();
process.StartInfo = startInfo;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine.Data);
}

Related

How to wait for ADB output in C#?

I want to receive information from a device connected in USB via a C# program using ADB commands then flush the output.
Process process = new Process();
process.StartInfo.FileName = "adb.exe";
process.StartInfo.Arguments = "logcat -d -b main -v raw -s Command:I"; // get data in Log.I() with name == "Command"
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
string output;
do {
process.StandardInput.WriteLine("logcat -d -b main -v raw -s Command:I");
output = process.StandardOutput.ReadToEnd();
} while (output.Length < 1);
Console.WriteLine(output);
process.StandardInput.WriteLine("logcat -c"); // flush logcat
process.WaitForExit();
Doing that I understand that the program is constantly executing adb logcat -d -b main -v raw -s Command:I, isn't there a way to call a command one time and wait for the output?
I can do that in windows prompt using :
adb shell 'logcat -b main -v raw -s UNIQUE_TAG:I | (read -n 1 && kill -2 $((BASHPID-1)))'
but is this doable in C#?
Also the output doesn't seem to be flushed
You can't read to the end more than once; ReadToEnd ultimately means "until the pipe is closed and I've consumed everything, and no more data will ever ever arrive". ReadToEnd will also never finish until adb.exe either intentionally signals that it is done writing (and will never write again), or terminates - so this is why you aren't getting as far as flushing.
What you can do is read (a byte/character at a time, if needed) until you have, say, a single line - so if the expectation here is "one command in, one line out" then it is simple enough. If there isn't a way of knowing how many lines will come back, then you would usually use two threads, and have a dedicated reader thread that takes data from the process.StandardOutput (byte/character at a time, or line by line) and does whatever is needed with it.
This is how i used to code for such things
Here is my code Hope u understand it
//to run the all the cmd,adb.fastboot.exe command using these function
//here in startfunc pass the .exe file u want to execute,Arguments which u want to pass
//string msg = It is nothing Extra message if u want to add to your final output
private static string Execute(string Startfunc, String Arguments,string msg)
{
string text = null;
Process p = new Process();
p.StartInfo.FileName = Startfunc;
p.StartInfo.Arguments = Arguments;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.EnableRaisingEvents = true;
p.Start();
do
{
Application.DoEvents();
string output = p.StandardOutput.ReadToEnd();
text += output;
string err = p.StandardError.ReadToEnd();
text += err;
}
while (!p.HasExited);
text += msg;
return text;
}
//now i will call above function and make it wait until we get the result
private void normal_reboot_Click(object sender, EventArgs e)
{
txt_Log.Text = "rebooting" +Environment.NewLine;
Task t = Task.Factory.StartNew(() =>
{
txt_Log.Text=Execute("adb.exe","reboot","Done");
});
do { Application.DoEvents(); } while (!t.IsCompleted);
}
You can also look for output/error messages asyncly. So you don't need a (blocking) loop:
This example just outputs the messages, but can be extended by full methods
p.OutputDataReceived+= (s, e) => Console.WriteLine(e.Data);
p.BeginOutputReadLine();//This is important, otherwise the event won't be fired
p.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
p.BeginErrorReadLine();
This should print every line received by adb
Working code below, we don't call adb.exe directly but through cmd.exe with a command waiting for any information log coming from logcat with the title "Command" : adb shell logcat -b main -v raw -s Command:I
private Process listeningProc;
public someClass(){
listeningProc = new Process();
listeningProc.StartInfo.FileName = "cmd.exe";
listeningProc.StartInfo.UseShellExecute = false;
listeningProc.StartInfo.RedirectStandardOutput = true;
listeningProc.StartInfo.RedirectStandardInput = true;
listeningProc.Start();
listeningProc.OutputDataReceived += new DataReceivedEventHandler(
(s, e) => {
if (e.Data == "SPECIFIC_COMMAND") {
// do something
}
}
);
listeningProc.BeginOutputReadLine();
}
private void ListenToCommands(){
listeningProc.StandardInput.WriteLine("adb shell logcat -b main -v raw -s Command:I"); //Listening for Info Logs titled "Command"
while (true) { }
}
To flush logcat or send any command from the PC through ADB, I open another process and send the commands from there.
Edit:
You might want to add System.Threading.Thread.Sleep(2000); //pause for 2 seconds after each commands sent from the PC through ADB otherwise the device sometimes doesn't execute all commands when sent successively too quickly

C# Process removes quoted arguments

The command I'm trying to execute is
"C:\Program Files (x86)\MyAPP\solr-6.2.0\bin\solr" start -f -c -z "10.195.42.93:2181,10.195.42.92:2181" -h 10.195.42.92
And this works just fine on the command Line.
I'm trying to execute this as C# process.
NOTE: Below code works fine if i remove the quotes surrounding IPList
var IPList="10.195.42.93:2181,10.195.42.92:2181";
var hostIP="10.195.42.92"
string command = #"/c ""C:\Program Files (x86)\MyApp\solr-6.2.0\bin\solr"" start -f -c -z """ + IPList + #""" -h " + hostIP;
Process process = new Process();
log.Info("Starting " + command);
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = command;
process.StartInfo = startInfo;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += (s, e) => log.Info(e.Data);
process.ErrorDataReceived += (s, e) => log.Info(e.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
This throws error :
'C:\Program' is not recognized as an internal or external command,...
I have looked at the similar issue posted Here and tried the /s option but no heed.
What am i missing here ?
As the error says, it is trying to execute C:\Program which basically means something is wrong with the way you are escaping quotes. May be try to escape " using - \"
You're asking cmd.exe to run the command C:\Program Files (x86)\MyApp\solr-6.2.0\bin\solr. It will not run "C:\Program Files (x86)\MyApp\solr-6.2.0\bin\solr" because the quotes are consumed by the invocation of cmd.exe.
I do not know the proper way to fix this. You probably need to add escaped quotes somehow.
Enclosing the command with "(quotes) after /c solves the issue.
Example :
"/c ""c:\prog files\xyz\solr" start -c -z "blah,blah,blah" -h
IP "
Basically the command that is getting executed is
> cmd.exe /c "C:\Program Files (x86)\MyAPP\solr-6.2.0\bin\solr" start -f -c -z "10.195.42.93:2181,10.195.42.92:2181" -h 10.195.42.92
This command fails, and this has nothing to do with c# process api or .net.

How Do I Get The Command Console To Write Lines In Windows Forms Application? (Visual c#)

Basically i want the user to press a button and then the console will write all the appropriate lines for the user.
Here's the code i've written:
private void button6_Click(object sender, EventArgs e)
{
Process Cmd = new Process();
Cmd.StartInfo.FileName = #"C:\windows\system32\cmd.exe";
Cmd.Start();
StreamWriter sw = new StreamWriter(#"C:\windows\system32\cmd.exe");
{
sw.WriteLine = ("hello");
}
}
I tried StreamWriter but doesn't seem to be co-operating.
What you want can't be done, because you need to redirect StandardInput to send commands to cmd and when you do this, the cmd window will close. You still don't explain what exactly you want to archieve, but i can only think of two options:
Create a batch file with all the commands you want to execute and pass it as an argument to Process.
Redirect StandardInput and StandardOutput. This way you should take care of showing all the cmd messages. This is a bit messy and could lead you to deadlocks.
Edit
So at last, what you want is just run a console application with parameters. This is a sample using makecert:
Process ppp = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = #"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\makecert.exe";
psi.Arguments = "-n 'CN=TempCA' -r -sv TempCA.pvk TempCA.cer";
ppp.StartInfo = psi;
ppp.Start();
you can do something like this
Process Cmd = new Process();
Cmd.StartInfo.FileName = #"makecert.exe"; // enter the correct path
cmd.StartInfo.Argument = "" // pass your aarguemnt
Cmd.Start();

execute asterisk cli command C#

I need a help with executing asterisk cli commands using C#. I'm able to open terminal window and start asterisk (see the code below), but dont know how to for example execute "sip show peers" command in CLI. Is there any possible way to do it?
using System;
using System.Diagnostics;
namespace runGnomeTerminal
{
class MainClass
{
public static void ExecuteCommand(string command)
{
Process proc = new System.Diagnostics.Process ();
proc.StartInfo.FileName = "/bin/bash";
proc.StartInfo.Arguments = "-c \" " + command + " \"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start ();
while (!proc.StandardOutput.EndOfStream) {
Console.WriteLine (proc.StandardOutput.ReadLine ());
}
}
public static void Main (string[] args)
{
ExecuteCommand("gnome-terminal -x bash -ic 'cd $HOME; sudo asterisk -vvvvr; bash'");
}
}
}
All you triing to do is overkill. You just need ask asterisk for command, no need in bash or terminal.
Process proc = new System.Diagnostics.Process ();
proc.StartInfo.FileName = "/usr/sbin/asterisk";
proc.StartInfo.Arguments = "-rx \" " + command + " \"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start ();
But please note, that command start NEW asterisk process, so not optimal. Best way is use asterisk AMI interface(which is just tcp connection, so much less resources use) and issue AMI action COMMAND.
There are number of already developed AMI interfaces, including C# one.
You can execute asterisk cli commands directly from bash, just -x to the asterisk command.
For example ExecuteCommand("gnome-terminal -x bash -ic 'cd $HOME; sudo asterisk -rx "sip show peers"; bash'");.

Cannot see the results of command line

Previously somebody has asked how to run a command line command in C# from visual studio and the beneath was the answer.
I tried the same intended to call a tool called cccc which can run on command line. But when I run the beneath code I do not get any results and nothing shows wrong.
Stating generally how can we run the same commands from C# as it was in command line and get the same results. Say I call a program (it could be any program that is able to run on command line, for instance, cccc, ccm, and so on) on command line and get some results. How to call the command line and give the arguments so it will call in its turn the cccc or whatever and do the same thing as it was without C#.
string strCmdText;
strCmdText = "/C d: cd D:\\Exercises\\npp52\\PowerEditor\\src && dir /s /b | cccc - --outdir=d:\\myfolder";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
Add 'pause' to the end of your command:
string strCmdText;
strCmdText = "/C d: cd D:\\Exercises\\npp52\\PowerEditor\\src && dir /s /b | cccc - --outdir=d:\\myfolder & pause";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
or redirect console standard output to a stream.
Here need more magic with OutputDataReceived handler
void Main()
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName="cmd.exe";
proc.StartInfo.Arguments = "/c ping 127.0.0.1";
proc.StartInfo.UseShellExecute = false;
proc.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
proc.Close();
}
private void SortOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
{
if (!String.IsNullOrEmpty(outLine.Data))
{
// Do what You need with out
Console.WriteLine(outLine.Data);
}
}
Instead of trying to put everything inside a string you could take advantage of the ProcessStartInfo class to better define your arguments
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "CMD.EXE";
psi.WorkingDirectory = "D:\\Exercises\\npp52\\PowerEditor\\src ";
psi.Arguments = "/C dir /s /b | cccc - --outdir=d:\\myfolder"";
psi.WindowStyle = ProcessWindowStyle.Normal;
Process.Start(psi);
Also with the command window open you could see if there are syntax errors in your command
Another problem is that you are not using RedirectStandardOutput, so output is discarded. Take a look at this answer.

Categories

Resources