The Main Method – Part 3

Today I am going to finish the series of posts about the Main method, in this post we will see how to have more than one Main method in an application and how to choose among them before compiling the application.

We will start by creating a simple solution with two types, a class and a structure as you can see in Figure 1, both having a Main method.

Figure 1

Figure 1

The types implementation are below:

FirstProgram class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WordPress003
{
	class FirstProgram
	{
		static void Main(string[] args)
		{
			Console.WriteLine("Main method from FirstProgram class.");
			Console.Read();
		}
	}
}

SecondProgram structure

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WordPress003
{
	struct SecondProgram
	{
		static void Main(string[] args)
		{
			Console.WriteLine("Main method from SecondProgram struct.");
			Console.Read();
		}
	}
}

The important thing to note is that it is possible to switch between those two classes containing a Main method by means of Visual Studio or on a command switch using the command line compiler. Below are both methods demonstrated in Figure 2 and Figure 3 respectively:

Figure 2

Figure 2

In Figure 2 you can see the option Startup object which enables you to choose the desired type to use.

Figure 3

Figure 3

In Figure 3 you can realize that the same result is obtained through the /main command line switch.

Hope you enjoyed this last post about Main methods.

See you.

Posted in C# | Leave a comment

The Main Method – Part 2

Today I am going to continue the series of posts about the Main method, in this post we will see how to develop an application to copy or move a file (the back-end) and an application with a user interface to use it (the front-end) as I mentioned last post, we will learn how to call an application from another, pass arguments to it and retrieve its return value. Note that this post is not intended to be a tutorial step-by-step on how to create a Windows Forms Application, but the source itself is somehow self-explanatory.

First of all I created a solution with two projects, a Windows Forms Application (front-end) and a Console Application (back-end) as you can see in Figure 1.

A solution with two projects

Figure 1

In the Windows Forms Application I created a form with some controls, as you can see in Figure 2.

Form with some controls.

Figure 2

Below is the source code from the main form:

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace Front_End
{
	public enum OperationType : byte
	{
		Copy,
		Move
	}

	public enum FileType : byte
	{
		Source,
		Dest
	}

	public enum ResultType : byte
	{
		Success,
		Failure
	}

	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private void chooseFile_Click(object sender, EventArgs e)
		{
			Button button = sender as Button;

			FileType fileType = (FileType)Convert.ToByte(button.Tag);

			openFileDialog.CheckFileExists = fileType == FileType.Source;

			if (openFileDialog.ShowDialog() == DialogResult.OK)
			{
				switch (fileType)
				{
					case FileType.Source:
						sourceFileTextBox.Text = openFileDialog.FileName;
						break;
					case FileType.Dest:
						destFileTextBox.Text = openFileDialog.FileName;
						break;
				}
			}
		}

		private void executeOperationButton_Click(object sender, EventArgs e)
		{
			OperationType operationType = copyFileRadioButton.Checked ? OperationType.Copy : OperationType.Move;

			string operationTypeString = operationType == OperationType.Copy ? "copy" : "move";

			//prepare the arguments to send.
			string arguments =
				string.Format("operation=\"{0}\" sourceFile=\"{1}\" destFile=\"{2}\"",
				operationTypeString,
				sourceFileTextBox.Text,
				destFileTextBox.Text);

			//configure the back-end application to be executed.
			ProcessStartInfo processStartInfo = new ProcessStartInfo("Back-End.exe");
			processStartInfo.Arguments = arguments;
			processStartInfo.WorkingDirectory = Application.StartupPath;
			processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

			Process process = new Process();
			process.StartInfo = processStartInfo;

			try
			{
				//starts the back-end application and waits until its termination.
				process.Start();
				process.WaitForExit();

				//takes the result from the back-end application and converts to an enum type.
				ResultType resultType = (ResultType)process.ExitCode;

				//in this case 0 stands for success and 1 failure.
				switch (resultType)
				{
					case ResultType.Success:
						//here the file should be copied or moved.
						MessageBox.Show("The operation succeeded!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
						break;
					case ResultType.Failure:
						MessageBox.Show("The operation failed!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
						break;
				}
			}
			catch (Exception exception)
			{
				MessageBox.Show("An error ocurred while trying to start the back-end application:\n" + exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
	}
}

Note that the definition used in the main method, the one that accepts an array of strings and a return value of int type. Below is the code from the back-end application, note that in order to work both applications the front and back-end must be in the same directory:

using System;
using System.IO;

namespace Back_End
{
	class Program
	{
		//return of 0 indicate success 1 failure.
		static int Main(string[] arguments)
		{
			string sourceFile = null;
			string destFile = null;
			string operationType = null;

			if (arguments.Length < 3)
			{
				//Not all arguments were suplied.
				return 1;
			}
			else
			{
				foreach (var argument in arguments)
				{
					if (argument.Contains("operation"))
					{
						if (string.IsNullOrEmpty(operationType))
							operationType = ExtractValueFromArgument(argument);
						else
							//Duplicated argument;
							return 1;
					}
					else if (argument.Contains("sourceFile"))
					{
						if (string.IsNullOrEmpty(sourceFile))
							sourceFile = ExtractValueFromArgument(argument);
						else
							//Duplicated argument;
							return 1;
					}
					else if (argument.Contains("destFile"))
					{
						if (string.IsNullOrEmpty(destFile))
							destFile = ExtractValueFromArgument(argument);
						else
							//Duplicated argument;
							return 1;
					}
					else
					{
						//Invalid argument;
						return 1;
					}
				}

				try
				{
					if (File.Exists(sourceFile) && Directory.Exists(Path.GetDirectoryName(destFile)))
					{
						switch (operationType)
						{
							case "copy":
								File.Copy(sourceFile, destFile);
								break;
							case "move":
								File.Move(sourceFile, destFile);
								break;
						}

						return 0;
					}
				}
				catch (Exception)
				{
					return 1;
				}

				//Just to satisfy definite assignment (C# Language Specification Version 3.0, September 2007, Section 5.3).
				return 1;
			}
		}

		static string ExtractValueFromArgument(string argument)
		{
			int index = argument.IndexOf("=");

			return argument.Substring(index + 1, argument.Length - index - 1);
		}
	}
}

Now you should be able to copy or move files by using these two applications that uses front-end/back-end concept and understand how important the Main method is for any application, many applications uses the Main method for receiving and returning values like zip compression tools that you can use a friendly user interface or a command prompt, image conversion tools like http://www.imagemagick.org/.

Hope you enjoyed the post.

See you.

Posted in C# | Leave a comment

The Main Method – Part 1

Today I am going to talk about something simple, the Main method, but even the simplest thing has its particularities. The Main method of a program is considered by convention its entry point (C# Language Specification Version 3.0, September 2007, Section 1.1) and this entry point must be declared with the static modifier and it is case sensitive like all methods and C# language itself.

Example:

using System;

namespace WordPress001
{
	class Program
	{
		static void Main(string[] args)
		{
			Console.WriteLine("Just another hello world!");
		}
	}
}

So far, so good but is it possible to have a program without a Main method? The answer is yes, by compiling a program without a Main method we have a library to be used by other programs and a program that has at least one Main method is called an application (C# Language Specification Version 3.0, September 2007, Section 1.2).

The Main method can have the following definitions:

static void Main() {...}
static void Main(string[] args) {...}
static int Main() {...}
static int Main(string[] args) {...}

As you could see some definitions allow your program to read values as arguments and to return values, the parameter can be passed through a command prompt, by a shortcut or by other applications.

Example:

using System;

namespace WordPress001
{
	struct Program
	{
		static int Main(string[] arguments)
		{
			if (arguments.Length > 0)
			{
				foreach (var argument in arguments)
				{
					Console.WriteLine(argument);
				}
				return 0;
			}
			return 1;
		}

		static void Main(object o)
		{
			Console.WriteLine(o);
		}
	}
}

The application above reads the array arguments and prints every element of it, the arguments string array is never null but may have a length of 0 if no arguments is passed to the application. If at least one argument was passed to the application it returns 0 (generally used indicating success) otherwise it returns 1 (a code different than 0 may indicate a problem). This kind of application is generally used when developing console applications, you could write an application to copy a file and return a code of 0 indicating success or 1 indicating failure and call it from another application. This concept of writing one application and call it from another is very used on unix like systems and is known as front-ent and back-end applications.

Note that at line 5 I used a struct instead of a class and it is totally acceptable. Note as well that the Main method appears more than once, this was intentional as one class or struct may have more than one Main method, but only one can be eligible as the application entry point, that is, have one of the four definitions mentioned above.

Hope you enjoyed the post, this is the first one of a serie about the Main method.

Many more to come.

See you.

Posted in C# | 1 Comment