I can call the console app from the asp.net web forms but if I have input one by one like below once I got the first argument from user input then they have another input please enter another number then user need to input another argument in console app. I have 2 arguments but both will take one by one. If single argument at first time then I can pass as below but with 2 I could not. How this possible If some one help then that would be good. I want to pass both argument.
Asp.net web form
Process p1 = new Process();
p1.StartInfo.FileName = "ConsoleEx.exe"; // actual file name
p1.StartInfo.Arguments = "1 ";
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.RedirectStandardOutput = true;
p1.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p1.Start();
p1.WaitForExit();
if (p1.HasExited)
{
string output = p1.StandardOutput.ReadToEnd();
lblConsoleOutput.Text = output;
p1.Dispose();
}
Console App
static void Main(string[] args)
{
int num1, num2;
int add, sub, mul;
float div;
Console.Write("Enter 1st number\t");
num1 = Convert.ToInt32(Console.ReadLine());
Console.Write("\nEnter 2nd number\t");
num2 = Convert.ToInt32(Console.ReadLine());}
Here is the image
Redirect the standard input and stream the values by code.
You can find an example here; http://msdn.microsoft.com/en-gb/library/system.diagnostics.processstartinfo.redirectstandardinput%28v=vs.110%29.aspx
Related
I need to use standard input/output on process, so I created simple app "test":
var line = String.Empty;
do
{
Console.Write($"previous input ==> {line}, type next input> ");
line = Console.ReadLine();
}
while (!String.IsNullOrWhiteSpace(line) && line != "quit");
Console.WriteLine("End");
which receives something on standard input and writes on output. Then I created new app which needs to start that app "test" and use standard iput/output like:
var process = new Process
{
EnableRaisingEvents = false,
StartInfo = new ProcessStartInfo
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
Arguments = Arguments,
CreateNoWindow = true,
FileName = Name,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = WorkingDirectory
},
};
process.Start();
String? input;
do
{
Thread.Sleep(10000); // Sleep to be sure that "test" app generated output
var line = String.Empty;
while (process.StandardOutput.Peek() > -1)
line += (char)process.StandardOutput.Read();
Console.Write($"[Standard Output]{line}\t[New Input]");
input = Console.ReadLine();
process.StandardInput.WriteLine(input);
}
while (input != "quit");
The problem is that I get this as output:
[Standard Output]previous input ==> , type next input> [New Input]test
[Standard Output] [New Input]
The "process.StandardOutput.Peek()" second time is returning -1 and there exist output of "test" app. Is it possible to get next what is generated on standard output by "test" app from app that started that process.
I need to get second output generated from "test" app, so I expect to see line:
[Standard Output]previous input ==> test, type next input> [New Input]
If your platform is Windows, try PeekNamedPipe.
static string ReadAvailableString(StreamReader reader)
{
[DllImport("kernel32.dll")]
static extern bool PeekNamedPipe(
SafeFileHandle hNamedPipe,
IntPtr lpBuffer,
int nBufferSize,
IntPtr lpBytesRead,
out int lpTotalBytesAvail,
IntPtr lpBytesLeftThisMessage
);
var stream = (FileStream)reader.BaseStream;
if( !PeekNamedPipe(stream.SafeFileHandle, IntPtr.Zero, 0, IntPtr.Zero, out var totalbytesAvail, IntPtr.Zero) || totalbytesAvail<=0 )
return String.Empty;
Span<byte> buf = stackalloc byte[totalbytesAvail];
stream.Read(buf);
return reader.CurrentEncoding.GetString(buf);
}
Here is an example of getting StandardOutput.
var output = ReadAvailableString(process.StandardOutput);
Problem is Peek is non-blocking call which does not wait for data to become available. You start new process and then immediately proceed checking its standard output with Peek, but it might be nothing there yet. This is what you observe. Instead - you should read until some stopping point, but in this case there is no such point, so you can introduce it - use Console.WriteLine instead of Console.Write here:
Console.WriteLine($"previous input ==> {line}, type next input> ");
Now on receiving end you can read until you meet newline character:
line = process.StandardOutput.ReadLine();
Note that this is blocking read. It will read until newline, and if data is not available yet - it will wait until it's there. Now "messages" in your communication have clear boundaries.
I would even say that you should forget that Peek() exist and never use it. I've never used it in my practice and all usages I ever saw lead to bugs like this.
After trying a lot of things it seams that Process.StandardOutput.Peek is not working. You can use the "PeekNamedPipe" (answer from radian) for Windows OS.
I managed to work it on Windows and Linux using CliWrap (https://github.com/Tyrrrz/CliWrap). The problem here is that for input stream you need Stream that has blocking read() method, so I creted/implemented one for me. I will not put here the implementation of that stream, you can use any stream that satisfy that condition. So, here is the final version of above example using CliWrap library
var stdOutBuffer = new StringBuilder();
var stdErrBuffer = new StringBuilder();
// The CliStream is my own implementation of Stream class.
// The CliWrap library is calling method: int Read(byte[] buffer, int offset, int count)
// with parameters offset = 0 and count = 131072
// it is important that this method is blocking if nothing is in stream (it done it using Semaphores)
// if it is not blocking then you will have some unexpected behaviour
var stream = new CliStream();
var cmd = CliWrap.Cli.Wrap(ExecName)
.WithArguments(Arguments)
.WithStandardErrorPipe(CliWrap.PipeTarget.ToStringBuilder(stdErrBuffer))
.WithStandardOutputPipe(CliWrap.PipeTarget.ToStringBuilder(stdOutBuffer))
.WithStandardInputPipe(CliWrap.PipeSource.FromStream(stream))
.WithWorkingDirectory(WorkingDirectory);
cmd.ExecuteAsync();
String? input;
do
{
Thread.Sleep(10000); // Sleep to be sure that "test" app generated output
Console.Write($"[Standard Output]{stdOutBuffer}\t[New Input]");
stdOutBuffer.Clear();
input = Console.ReadLine();
var buffer = Encoding.UTF8.GetBytes(input + Environment.NewLine);
stream.Write(buffer);
}
while (input != "quit");
Thanks to everyone for contributing.
I am new to this secure push to Git.
I did a research and I found that someother languages use Envirenement variables to securely hide sensative data while pushing the project to Git.
So here is my test app and how I defined my varible envirenements in my Console App :
static void Main(string[] args)
{
ConverInput input = new ConverInput();
Calculate calc = new Calculate();\
try
{
double firstNumber = input.ConvertValueToDouble(Console.ReadLine());
double SecondNumber = input.ConvertValueToDouble(Console.ReadLine());
string operation = Console.ReadLine();
double result = calc.Calculation(firstNumber, SecondNumber, operation);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
//Test of securing data push to git using variable envirenement
string variableConfidentiel = "Here my password";
System.Environment.SetEnvironmentVariable("var1", variableConfidentiel, EnvironmentVariableTarget.User);
String var = System.Environment.GetEnvironmentVariable("var1", EnvironmentVariableTarget.User);
MessageBox.Show(var);
Console.ReadKey();
}
}
Now, It seems working but I dont know if it is the right way to do it . Secondly, I dont know where should I declare my System.Environment.SetEnvironmentVariable so I could be able later to use .gitignore on that file.
Thank you very much in advance.
I wanna pass arguments to c# console app with this specific format.
Suppose my app's exe name is SmsSender,
I wanna this format in my cmd:
SmsSender -m message -p phonenumber
How can I do this?
Refer to this Microsoft Docs How to Display arguments
So in your case in you console app in your Main method you will have something like this:
class CommandLine
{
static void Main(string[] args)
{
// The Length property provides the number of array elements.
Console.WriteLine($"parameter count = {args.Length}");
// Get values using the `args` array in your case you will have:
// args[0] = "-m";
// args[1] = "message";
// args[2] = "-p";
// args[3] = "phonenumber";
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine($"Arg[{i}] = [{args[i]}]");
}
}
}
You just write that command into a command prompt window, exactly as you have written in there
Inside your c# app you have a static void Main(string[] args) and the args array will have 4 elements:
args[0] = "-m";
args[1] = "message";
args[2] = "-p";
args[3] = "phonenumber";
But be aware that if you don't wrap your message in "quotes" (in the command prompt) then every word in the message will be a different entry in args
In java you can pass parameters to the program through batch. How can I do that in C#?
Like if I needed the program to receive a file name how can I get it to the program?
Supposing you have created a C# console application (exe), it will be created with a main static method that receives an array of strings. Those strings will be the arguments passed to the program.
For example:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(string.Join("\n", args));
}
}
If your console application is named "MyApp.exe", you could pass parameters is this way:
MyApp.exe "first arg" second
And you should get this output:
The Main() routine in your application receives an array of strings which contain the arguments which were passed in on the command line.
static void Main(string[] args)
{
foreach (string s in args)
{
Console.WriteLine(s);
}
Console.ReadLine();
}
Outside of Main you can use Environment.GetCommandLineArgs().
string[] args = Environment.GetCommandLineArgs();
If you are trying to read the output from *.bat files this will help you..`
Process thisProcess = new Process();
thisProcess.StartInfo.CreateNoWindow = true;
thisProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
thisProcess.StartInfo.WorkingDirectory = #"C:\Users\My User Name\Documents";
thisProcess.StartInfo.FileName = "ipconfig";
thisProcess.StartInfo.Arguments = "/h";
thisProcess.StartInfo.UseShellExecute = false;
thisProcess.StartInfo.RedirectStandardOutput = true;
thisProcess.Start();
thisProcess.WaitForExit();
//Output from the batch file
string myOutput = thisProcess.StandardOutput.ReadToEnd();
I am writing a console application and I need to know, how to write in current line with shift of lines. I try to explain this on the next example:
Let It console lines with their numbers and contents along with cursor position.
Hello!
This is my command shell.
Please write something: _
When I call my method for writing in console text "lalala", i want to see that:
Hello!
This is my command shell.
lalala
Please write something: _
If I use Console.WriteLine method I see the next:
Hello!
This is my command shell.
Please write something: lalala
_
Please, help me to realise this feature.
Console.SetCursorPosition is the poison you are look for.
More details on http://msdn.microsoft.com/en-us/library/system.console.setcursorposition.aspx
As you didn't provide any code i assume you're using Console.WriteLine("Please write something"); to print out text. Since this will add an \n to the text you want to print you should rather use Console.Write("Please write something") then do an Console.ReadLine(); to get the input and handle the \n by yourself.
Console.WriteLine("1.Hello!");
Console.WriteLine("2.This is my command shell.");
Console.WriteLine("3.lalala");
Console.Write("4.Please write something:");
Console.Read();
If I understand your question right I think you need to use
Console.Write("text");
This will write on the same line as the cursor is currently on.
Rather than:
Console.WriteLine("text");
This will create a new line in the console each time it is called.
Please find the code for the above scenario:
private static void ReadAndWriteToConsole()
{
var mystrings = new List<string>();
mystrings.Add("Hello!");
mystrings.Add("This is my command shell.");
var input = WriteToConsole(mystrings);
while (input.ToLower() != "exit")
{
mystrings.Add(input);
Console.Clear();
input = WriteToConsole(mystrings);
}
}
private static string WriteToConsole(IEnumerable<string> variables )
{
foreach (var str in variables)
{
Console.WriteLine(str);
}
Console.Write("Please write something:");
return Console.ReadLine();
}
Hope that helps.
NOTE: If you want the number of each string then use a for loop instead of foreach and just print the variable used in the console.writeline.
try something like this
Console.Write("Hello\nThis is My Command Shell\nlalala\nPlease Enter Something:___");
if course that would end up having them all appear at the same time, but if your good with that this will work
Will look like this
I realize that this is an old question, however I have been searching this stuff and here is how it can be coded:
Console.WriteLine("Hello!");
Console.WriteLine("This is my command shell.");
string text = "";
string toWrite = "Please write something: ";
while (text != "quit")
{
Console.Write(toWrite);
text = Console.ReadLine();
Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.WriteLine(text.PadRight(text.Length + toWrite.Length));
}
The Console.SetCursorPosition puts the cursor back to the line that was written into, then overwrite what is written with the text and a padding equivalent to how many chars the text had.