c# console: how can i read piped input from the command line - c#

I'm a bit confused. I've been looking through previous answers to the above question and NONE of them actually work for me, so I'm not sure what i'm doing wrong.
I have a simple c# console app: (outputsomething.exe)
static void Main(string[] args) {
Console.Out.Write("This is a test");
}
And another one that takes some args and piped input from the above code, like this:
dostuffwithinput.exe some args |outputsomething.exe
First problem is that I can't work out how to "read" the piped input, as I said above none of the existing answers work for me, reading from stdin (Console.In) just doesn't capture anything.
Secondly, after piping something in I can no longer write anything out to stdout (Console.Out).
The code I have is very simple it just writes out the args to a file, together with a few console attributes and tries to read from Console.In - which it does but it only reads input that I type in.
But with piped input it just never manages to capture what is piped in and the last output is never sent to the console.
static void Main(string[] args) {
bool ior = Console.IsInputRedirected;
bool keyavail = Console.KeyAvailable;
char[] chrs = new char[4];
int chr = Console.In.ReadBlock(chrs, 0, 4);
using (StreamWriter stream = new StreamWriter("fred.txt")) {
foreach (var arg in args) {
stream.WriteLine(arg);
Console.WriteLine(arg);
}
stream.WriteLine("input = " + new string(chrs));
stream.WriteLine("io redirectirected = " + ior);
stream.WriteLine("is key available = " + keyavail);
}
Console.WriteLine("fin");
Console.Out.Flush();
}
(I'm also having serious problems with this pile-of-crap editor that keeps showing a red warning about indentation show i've have to remove a lot of examples to get it in a sendable form!)
What am I doing wrong? (this is on windows 10/9879)
TIA

Tried the same with the below example codes. It is working for me.
WriteText
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Test Line1");
Console.WriteLine("test Line2");
}
}
ProcessInput
class Program
{
static void Main(string[] args)
{
string s=Console.In.ReadToEnd();
Console.WriteLine("Redirected Text: " + s);
}
}
I invoked the app using WriteText.exe | ProcessInput.exe
It showed the output string exactly passed by the WriteText.exe
Please let me know, if this helps.

If you want to pipe from outputsomething.exe to dostuffwithinput.exe it should be
outputsomething.exe|dostuffwithinput.exe some args

Related

Can't input data with Console.ReadLine

I'm trainning in C# alone for this moment, and encounter my first problem.
I use VSCode as IDE.
What I Am Try To Do
Create two functions, the first, data like name and return it. the second return full name. All in one in a class.
What I Do From Here
using System
namespace Helloworld
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
Console.WriteLine(p.getFullName())
}
public string getName(string message)
{
string? name;
do
{
Console.WriteLine(message);
name = Console.ReadLine();
}
while (string.IsNullOrEmpty(firstName)); // For avoid null or empty string, I'm not found another solution.
return name;
}
public string getFullName()
{
const string firstNameMessage = "Enter your first name: ";
const string lastNameMessage = "Enter yout last name: ";
string result = $"{getName(firstNameMessage)} {getName(lastNameMessage)}"
return result;
}
}
}
I Have Encountered Any Problems
1 - When I launch the command dotnet run, my program follow instructions while the first Console.WriteLine. When I type an random name in VSCode's Debug Console. Nothing happens...
My questions: Does this problem come my code ? Am I using an unsuitable IDE ? Or Am I not working with the good VSCode's Tools ?
2 - When I want restart or build I have a message like The process cannot access the file C:\Users\Username\ Documents\Work\learningCSharp\bin\Debug\net6.0\learningCSharp.dll' because it is being used by another process.
My question: How I kill process which use my DLL file ?
I solve all my problem finally alone. I read here the solution.
I'm posting the solution anyway.
in your launch.json replace "console": "internalConsole" by "console": "integratedTerminal.
If you are senior in C#, Can you tell us if is it same for all IDEs ?

The variable is declared but never used

I am currently working on a project that is creating a rapid translating program to mess up text using google's API. But I keep running into warning CS0168 and don't know how to fix it. The code is here:
using System;
using Google.Cloud.Translation.V2;
namespace Program
{
public partial class Translate
{
[STAThread]
private static void Main()
{
Console.WriteLine("Write text to become cursed");
string Phrase = Console.ReadLine();
string TranslateText() //this variable is the problem
{
TranslationClient client = TranslationClient.Create();
//this block repeats with the language changing each time
var response = client.TranslateText(
text: Phrase,
targetLanguage: "language",
sourceLanguage: "language");
Console.WriteLine(response.TranslatedText);
Phrase = response.TranslatedText;
//end of reapeat
return response.TranslatedText;
}
}
}
}
Even if I ignore the warning the program wont run.
There are two main problems with your code:
As others have indicated, you declared a local function but you never used it.
The application exits right away because it's done all its work. You need to add Console.ReadLine(); or Console.ReadKey(); at the end to prevent it from closing.
Try something like this:
static void Main(string[] args)
{
Console.WriteLine("Write text to become cursed");
string Phrase = Console.ReadLine();
string TranslateText()
{
TranslationClient client = TranslationClient.Create();
//this block repeats with the language changing each time
var response = client.TranslateText(
text: Phrase,
targetLanguage: "language",
sourceLanguage: "language");
Console.WriteLine(response.TranslatedText);
Phrase = response.TranslatedText;
//end of reapeat
return response.TranslatedText;
}
string translatedText = TranslateText();
Console.WriteLine("The translated text is: " + translatedText);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
With that being said, a local function might not be the best way to handle this. Instead, you could move it outside the Main and add a string parameter to it so that you can pass the phrase as an argument to it. In this case, your code would look something like this:
static void Main(string[] args)
{
Console.WriteLine("Write text to become cursed");
string phrase = Console.ReadLine();
string translatedText = TranslateText(phrase);
Console.WriteLine("The translated text is: " + translatedText);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
static string TranslateText(string phrase)
{
TranslationClient client = TranslationClient.Create();
//this block repeats with the language changing each time
var response = client.TranslateText(
text: phrase,
targetLanguage: "language",
sourceLanguage: "language");
Console.WriteLine(response.TranslatedText);
//end of reapeat
return response.TranslatedText;
}

How to pass a file path to the program via command line argument

I have 5 files, which I have parsed. They are text files, and I dont know how to pass them to the program via command line arguemnt. I am using visual studio, and C sharp. When I go into Project>Properties>Debug>Command Line Argument> Do I just type in the files? Like File01.txt,File02.txt etc...
The simplest way is to realise that command line arguments are passed to you as an array of strings in your Main(...) method.
class TestClass
{
static void Main(string[] args)
{
// Display the number of command line arguments:
System.Console.WriteLine(args.Length);
foreach(var arg in args)
{
System.Console.WriteLine(arg);
}
}
}
(Broadly from: https://msdn.microsoft.com/en-us/library/acy3edy3.aspx)
Specifically in answer to your question -- yes, in the debug tab, but they need to be space-separated, not comma separated.
If you actually want to open and read the files, you'll need something like (assuming they're text files):
int counter = 0;
string line;
using(var file = new System.IO.StreamReader(arg))
{
while((line = file.ReadLine()) != null)
{
Console.WriteLine (line);
counter++;
}
}
(Broadly from: https://msdn.microsoft.com/en-GB/library/aa287535%28v=vs.71%29.aspx)
In your Main method, you can process your arguments in the following way:
static void Main(string[] args)
{
if (args.Length > 0)
{
foreach (string p in args)
{
Console.WriteLine(p);
}
}
else
{
Console.WriteLine("Empty input parameters");
}
}
When you run your program from command line, you have to use the following syntax:
C:\>yourprogram.exe firstfile.txt secondfile.xls thridfile.dat

C#/.NET console applications that behave like normal Unix tools

This question is regarding designing console applications in .NET that behave like normal Unix tools. The basic fundamental of Unix tools is that they can be chained together with 1 tool being able to take input from any compatible stream and giving output to any compatible stream.
If I'm writing console applications in .NET for Windows, what are the general things I need to follow for my tools to be of the same type?
"Do only one thing" is definitely one, but there are more:
Do only one thing and do it well
Output nothing on success (other than the result, of course)
Use stdin for the input, stdout for the output, and stderr for errors
Use non-zero exit codes to communicate failure
With this in mind, here's what is, in my opinion, a more "unixy" "to-uppercase" program in C#:
using System;
class Program
{
static int Main(string[] args)
{
try
{
var buf = new char[4096];
while (true)
{
int read = Console.In.Read(buf, 0, buf.Length);
if (read == 0)
break;
for (int i = 0; i < read; i++)
buf[i] = char.ToUpper(buf[i]);
Console.Out.Write(buf, 0, read);
}
return 0;
}
catch (Exception e)
{
Console.Error.WriteLine("ERROR: " + e.Message);
return 1;
}
}
}
Like a typical unixy program, you can run it without arguments and then it will be interactive, allowing you to type input manually on the console, terminated with Ctrl+Z, printing output whenever it receives a chunk of your input. Or you could pass it a file to process: uppercase.exe <input.txt and it will print the output to the console. Or you could redirect the output to a file too. Or you could pipe the input into it. Etc.
The main principle behind *nix tools is do one thing, and do it well.
Let's say I set out to create a *nix style tool that converted the input to uppercase. It's a trivial example, but that allows me to post the whole program here.
Here's the source code:
using System;
using System.Diagnostics.Contracts;
namespace Upperc {
class Program {
static void Main(string[] args) {
var input = Console.ReadLine();
Contract.Assert(input != null);
Console.WriteLine(input.ToUpperInvariant());
}
}
}
I took advantage of the fact that Console methods handle input and output and the standard streams. Example usage is:
> type example.txt | Upperc.exe > uppercased.txt
The input file is a plain text file:
example text file before processing
and the output file:
EXAMPLE TEXT FILE BEFORE PROCESSING

Redirecting Command-line Arguments for Bootstrapping

I am trying to rewrite the following program in C instead of C# (which is less portable). It is obvious that "int system ( const char * command )" will be necessary to complete the program. Starting it with "int main ( int argc, char * argv[] )" will allow getting the command-line arguments, but there is still a problem that is difficult to understand. How do you successfully escape arguments with spaces in them? In the program below, arguments with spaces in them (example: screensaver.scr "this is a test") will be passed to the script as separate arguments (example: screensaver.scr this is a test) and could easily cause problems.
namespace Boids_Screensaver
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
System.Diagnostics.Process python = new System.Diagnostics.Process();
python.EnableRaisingEvents = false;
python.StartInfo.FileName = "C:\\Python31\\pythonw.exe";
python.StartInfo.Arguments = "boids.pyw";
foreach (string arg in args)
{
python.StartInfo.Arguments += " " + arg;
}
python.Start();
}
}
}
Windows is all messed up. Every program has its own rules.
The correct way to do this under windows is to use _spawnv
Its equivalent under unix like OSes is fork() followed by execv.
screensaver.scr "spaced argument" nonspaced_argument
argc = 2
argv[0] = "screensaver.scr"
argv[1] = "spaced argument"
argv[2] = "nonspaced_argument"
Sorry my English :).

Categories

Resources