This article is currently in the process of being translated into Russian (~3% done).
Starting applications with the Process class
Очень полезно иметь возможность из вашего приложения запускать другое приложение. Для примера, можно включить в приложение ссылку на свой веб-сайт, но вместо того чтобы заставлять пользователя вручную копировать адрес и вставлять его в браузер, можно сделать ссылку интерактивной. Пользователь просто кликает на нее, и ваш сайт открывается браузером по умолчанию.
In this tutorial, we use mostly Console applications, because they are less complex and can better demonstrate the syntax of the language without too much clutter. The above example is obviously more relevant for a GUI-based application, using one of the .NET GUI frameworks like WinForms or WPF, but it may still be useful to start another application from your Console application, and if not, you will at least have learned the technique for later.
Using the Process class
To instantiate another application, you can use the Process class. The Process class lives in the System.Diagnostics namespace, so you will have to include this:
In its most basic form, you can simply use the static Start() method to start an application:
You will notice that I supply a URL here - this could just as well have been the path to a local application, e.g. Notepad (if you work on Microsoft Windows):
The reason why both things work is that the Process class simply passes the instruction to the operating system, basically saying "run this!". The operating system will then examine the provided information and see whether it has a supported action or not. If a path to an executable file is provided, it will be started - if something else is provided, e.g. a URL or path to some kind of local file, it will try to handle it with an associated application. This also means that you can tell your program to execute a path to a local folder - if you're using Windows, this will result in Windows File Explorer being started, showing you the requested path.
Starting applications with arguments/parameters
It's often useful to provide one or several arguments/parameters when starting an application. Console applications usually take a wide variety of parameters, but even Windows applications can usually handle parameters provided through the command line. For instance, if you start Notepad, you can supply it with a file you want to edit, like this:
This works because Notepad is designed to look at the command line for a parameter - it will use the first parameter, if provided, as a path to the file that is to be opened. You can easily replace the path to win.ini with the path to one of your own files to test this out!
Using the ProcessStartInfo class
The Process class is quite a complex class, which can do a lot more than just starting an application. We won't go through it all in this article, where we focus mainly on its ability to start a new process. When doing that, you sometime need a bit more control of how its done and that's where the ProcessStartInfo class comes into play. Instead of providing the Start() method with a path, you can pass an instance of the ProcessStartInfo class, like this:
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = @"C:\Windows\notepad.exe";
processStartInfo.Arguments = @"C:\Windows\win.ini";
This will simply do what we have already accomplished, so lets look into some of the interesting properties of the ProcessStartInfo class, besides the Filename and Arguments properties which we just used in the example above, which will give us more control:
Us the WindowStyle property to control how the window of the started application appears. For instance, you can start it as maximized or minimized, like this:
processStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
The CreateNoWindow property accomplishes exactly what the name implies: When set to true, a window will not be generated for the application being started. This is of course only relevant for applications capable of doing stuff without user interaction, e.g. a Console application taking input, doing something with it and returning a result to the calling application.
This property allows you to control whether the system shell should be used to start the process - otherwise the process is created directly from the executable file. This property is true by default if you're working with the .NET framework before .NET Core, but false by default if you're using .NET Core. We'll use this property in an extended example later on.
Use this property to set the path of the directory from where you wish to execute things from. However, please be aware that it's used differently depending on whether UseShellExecute is set to true or false. When UseShellExecute is set to true, the WorkingDirectory property simply specifies the location of the executable and the working directory of the application that starts the executable is also the working directory of the executable. When UseShellExecute is set to false, the WorkingDirectory property is not used to find the executable - instead, its value is applied to the process started and only has meaning within the context of the new process.
RedirectStandardInput, RedirectStandardOutput and RedirectStandardError
These properties, when set to true, can redirect input/output and errors from the executed process to the calling process. This is, for instance, useful in combination with CreateNoWindow, because it allows you to start a process and provide it with input and/or receive errors and output from it. I will use it in the final example below, where we combine several of the described properties.
Combining it all
There are a bit more properties which we could discuss, but the ones highlighted are definitely the most interesting. Instead, I'll show you one last example, where we combine several of the techniques we just discussed into something pretty cool. First, I'll give you the entire example code and then we'll discuss it:
Console.WriteLine("Press any key to run CMD...");
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = @"C:\Windows\system32\cmd.exe";
processStartInfo.Arguments = "/c date /t";
processStartInfo.CreateNoWindow = true;
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardOutput = true;
Process process = new Process();
process.StartInfo = processStartInfo;
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine("Current date (received from CMD):");
We start out by creating the ProcessStartInfo object. We use the Filename and Arguments properties to specify that we want to run a Windows command, using the cmd.exe (the default Windows Command Line Interpreter) file. The command we want to run is specified as the Arguments - in this case we use the date command with the /t argument, which will simply output the current date.
You will also notice that I use three properties we just discussed: CreateNoWindow = true (we want to capture the output without displaying a cmd window), UseShellExecute = false (we need it like that to be able to execute this type of command) and RedirectStandardOutput = false (again, we want to capture the output).
Next, we create the Process instance, assign the StartInfo and then we call the Start() method to start the process.
In the next two lines, we ask to receive the output generated, by calling the Process.StandardOutput.ReadToEnd() method. We store it in a string variable and then we call the WaitForExit() method, to make sure that the process we started is allowed to finish.
In the last two lines, we simply write the output we received - it should result in the current date. Now obviously, this was a LOT of work to output the current date - we could have done that with a single line of code. But this demonstrates a pretty powerful technique, allowing you to call other applications and use their work inside your own application.
The Process class is a very powerful tool, allowing you to start other processes and even control them. We have only demonstrated some of its many abilities in this article, but hopefully it has shown you just how versatile a tool it is, so that you may go ahead and experiment more with it.