Command Line Arguments in C# Applications in 10 Minutes or Less
When building modern C# applications, developers often need flexibility in how programs start and behave. Instead of hardcoding every option, you can make your application dynamic by allowing users to pass command line arguments when launching it. This enables developers and users alike to provide input parameters directly through the command line, adjusting how the application runs without changing code.
In his concise 10-minute tutorial titled “Command Line Arguments in C# Applications in 10 Minutes or Less,” Tim Corey clearly demonstrates how to enable command line arguments and handle them effectively in both console applications and Windows Forms applications. This article walks through the concepts step by step as explained by Tim.
What Are Command Line Arguments?
At the beginning, Tim explains why command line arguments matter. He compares them to how we launch tools like Docker, where we specify commands such as what image to load or what task to perform. Similarly, in C# command line applications, you can pass parameters that define the program’s behavior at runtime.
For example, if you were running a console app to process files, you might want to specify the file path or mode via the command line input - instead of modifying the code.
Setting Up the Console Project
Tim begins inside Visual Studio with a basic .NET 8 Console Application project. The default code only prints a message like “Press return to exit,” using a Console.ReadLine() statement to wait for user input before closing.
Now, to handle command line input, Tim introduces the args array, which stores the arguments passed to the application when executed. Although modern C# console apps use top-level statements, behind the scenes they still have an entry point defined as:
static void Main(string[] args)static void Main(string[] args)or sometimes:
static int Main(string[] args)static int Main(string[] args)These signatures represent the main method - the entry point where execution begins. The args parameter is an array of strings (string[]), containing all the arguments supplied from the command line.
Tim demonstrates iterating over the args array using a foreach loop:
foreach (var arg in args)
{
Console.WriteLine(arg);
}foreach (var arg in args)
{
Console.WriteLine(arg);
}Here, var arg represents each string argument in the args array, and the program displays them on separate lines in the console output.
Tim notes that while top-level statements hide the boilerplate code like the class Program and Main method, everything still works the same - the args array is always available and ready to capture command line arguments.
Running the Console Application
Next, Tim shows how to test this feature. Running the program normally inside Visual Studio won’t show anything different, since no command line input has been provided.
To test properly, he manually modifies the execution process: he opens File Explorer, navigates to the project’s bin → Debug → net8.0 folder, and launches a terminal window from that path.
From there, he uses the following command:
ConsoleArgs.exe "hello world" -t timingConsoleArgs.exe "hello world" -t timingThis command demonstrates several key points:
The quoted "hello world" is treated as one string argument, not two separate words.
- The flag -t and the word timing are treated as two additional arguments.
When executed, the console output shows:
hello world
-t
timinghello world
-t
timingEach line argument represents one element in the args array. Tim explains that this confirms the correct usage of command line arguments - the console application successfully received and displayed all the arguments passed during execution.
He mentions that developers can also use dotnet run instead of the executable path when running from a project directory:
dotnet run -- "hello world" -t timingdotnet run -- "hello world" -t timingThe double dash (--) tells .NET to treat everything after it as command line parameters for your program, not for the .NET CLI itself.
Handling and Parsing Command Line Arguments
Now that we can read arguments, Tim discusses handling command line arguments intelligently.
For example, if -t is a flag that expects a value, the program must know to treat the next string argument as its value. Tim shows that you can manually parse this by checking indexes in the args array:
for (int i = 0; i < args.Length; i++)
{
if (args[i] == "-t")
{
var value = args[i + 1];
Console.WriteLine($"Timing parameter: {value}");
}
}for (int i = 0; i < args.Length; i++)
{
if (args[i] == "-t")
{
var value = args[i + 1];
Console.WriteLine($"Timing parameter: {value}");
}
}This approach lets you handle named arguments, numeric types, and even verbose mode flags. Tim notes that developers often use a switch statement or even external documentation and libraries for more advanced argument parsing, but the System namespace and args array already provide everything needed for basic cases.
Extending to a Windows Forms Application
After demonstrating console apps, Tim moves on to a Windows Forms application (WinForms).
In the generated code, the Program.cs file contains a static void Main() method, but it doesn’t yet accept parameters. To enable command line arguments, Tim manually modifies the Main method to include the args parameter:
[STAThread]
static void Main(string[] args)
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1(args.FirstOrDefault() ?? "default"));
}[STAThread]
static void Main(string[] args)
{
ApplicationConfiguration.Initialize();
Application.Run(new Form1(args.FirstOrDefault() ?? "default"));
}He explains that args.FirstOrDefault() retrieves the first input parameter from the args array (or returns "default" if no argument is provided).
Then, in the Form1 class, Tim updates the constructor to accept a string argument:
public Form1(string name)
{
InitializeComponent();
displayName.Text = name;
}public Form1(string name)
{
InitializeComponent();
displayName.Text = name;
}Here, displayName is a label defined in the Windows Forms Designer, and it now displays the argument passed through the command line.
When he runs the program without arguments, the label displays “default.” When he runs it again with:
WinFormsArgs.exe "Hello World"WinFormsArgs.exe "Hello World"the form window displays “Hello World.”
Tim explains that this technique allows Windows Forms applications to support command line arguments just like console applications - giving users the ability to change startup behavior dynamically.
Practical Uses of Command Line Arguments (7:18)
Tim concludes by discussing how versatile command line tools can become with this feature. Developers can use command line arguments to:
Launch applications in different modes (for example, dark mode vs light mode).
Provide file paths or configuration options at startup.
Enable verbose mode or debug features using simple switches like -v or --debug.
- Create shortcuts that pass specific arguments for different workflows.
By designing the main method to accept string arguments, you can easily extend your application’s flexibility and adaptability - without needing additional user input dialogs or configuration files.
Conclusion (8:15)
His example-driven explanation shows that handling command line arguments in C# isn’t complicated - it’s simply about understanding that every application has an entry point (Main) where arguments passed from the command line arrive as a string array.
Whether you’re working with console apps or Windows Forms applications, this concept empowers your programs to respond dynamically to commands, values, and parameters specified at startup.
Final Takeaway
Tim Corey’s video offers a clear, practical guide to the correct usage of command line arguments in C#. By understanding how the args parameter works in the Main method, developers can easily create, parse, and use arguments for more robust and configurable applications.
So next time you build a C# project, remember that your command line arguments are not just technical syntax - they’re the bridge between your program and its users, giving your code more power, flexibility, and real-world usability.
