Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

The .NET Process class on Linux

<p>&nbsp;</p> <quillbot-extension-portal></quillbot-extension-portal>

October 29, 2019
Tom Deseyn
Related topics:
.NETLinux

    In this article, we'll look at .NET's Process class. We'll go over the basics of how and when to use it, then cover differences in usage between Windows and Linux, and point out a few caveats. This article covers behavior in .NET Core 3.0.

    The basics

    The Process class represents an instance of a running process. You can use it to start new processes using Process.Start or get running processes via the static GetProcessById,GetProcesses,GetProcessesByName methods.

    When starting a new Process, all information to start the process is set on a ProcessStartInfo instance (PSI). PSI has properties like FileName and Arguments to set the program to execute and its arguments. UseShellExecute allows you to open documents. RedirectStandard{Input/Output/Error} allows you to write/read the standard I/O streams. Environment/EnvironmentVariables and WorkingDirectory allow you to control the environment variables and working directory.

    .NET Core 2.1 (/netstandard 2.1) added an ArgumentList property. The Arguments property is a string and requires the user to use Windows command-line escaping rules (e.g., using double-quotes to delimit arguments). The ArgumentsList property is a Collection that holds separate arguments. Process.Start will take care of passing those to the underlying platform. It's recommended to use ArgumentList over Arguments when targeting .NET Core 2.1+/netstandard2.1+.

    The following example shows launching the echo application, with a single argument hello world, and then waiting for the process to terminate.

    using var process = Process.Start(
        new ProcessStartInfo
        {
            FileName = "echo",
            ArgumentList = { "hello world" }
        });
    process.WaitForExit();
    

    Not supported on Linux

    The following properties of ProcessStartInfo aren't supported on Linux and throw PlatformNotSupportedException: PasswordInClearText, Domain, LoadUserProfile, Password.

    Retrieving processes from a remote machine using the machineName overload GetProcessById,GetProcesses,GetProcessesByName is also not supported.

    On the Process, it isn't supported to set working set limits (MinWorkingSet, MaxWorkingSet). On a ProcessThread (obtained via Process.Threads) the PriorityLevel/ProcessorAffinity cannot be set.

    Killing processes

    Processes can be stopped by calling Process.Kill. On Linux, this is implemented by sending the SIGKILL signal, which tells the kernel to terminate the application immediately. It’s not possible to send a SIGTERM signal, which requests the application to gracefully terminate.

    Since .NET Core 3.0, Process.Kill no longer throws Win32Exception/InvalidOperationException if the process is terminating or was already terminated. If you are targeting earlier .NET Core versions (or .NET Framework), you should add a try/catch block to handle these exceptions.

    .NET Core 3.0 adds an overload to the Process.Kill method that accepts a bool entireProcessTree. When set to true, descendants of the process will also be killed.

    UseShellExecute

    The ProcessStartInfo.UseShellExecute property can be used to open documents. Shell refers to the graphical shell of the user, and not a command-line shell like bash. Setting this to true means behave as if the user double-clicks the file. When ProcessStartInfo.FileName refers to an executable, it will be executed. When it refers to a document, it will be opened using the default program. For example an .ods file will open with LibreOffice Calc. You can set FileName to an http-uri (like https://redhatloves.net) to open up a browser and show a website.

    Unix shell scripts are considered real executables by the operating system (OS). This means it is not required to set UseShellExecute. This approach is unlike Windows .bat files, which need the Windows shell to find the interpreter.

    On Windows, UseShellExecute allows alternative actions on a document (like printing) by setting the ProcessStartInfo.Verb. On other OSes, this property is ignored.

    FileName resolution

    When setting a relative filename on Process.FileName, the file will be resolved. The resolution steps depend on UseShellExecute being set or not. The resolution on non-Windows platforms is implemented to behave similarly to Windows.

    When UseShellExecute is set to false:

    • Find the file in the native application directory.
    • Find the file in the process's working directory.
    • Find the file on PATH.

    The native application directory is the dotnet installation directory when executing dotnet. When using a native apphost, it’s the apphost directory.

    When UseShellExecute is set to true:

    • Find an executable file in the ProcessStartInfo.WorkingDirectory. If that is not set, the process working directory is used.
    • Find an executable file on PATH.
    • Use the shell open program and pass it the relative path.

    It's important to know that in both cases directories are searched, which may be unsafe (executable directory, working directory). You may want to implement your own resolution and always set FileName to an absolute path.

    Redirected streams

    When UseShellExecute is set to false, you can redirect standard input, output, and error using ProcessStartInfo.RedirectStandard{Input/Output/Error}. Corresponding Encoding properties (like StandardOutputEncoding) allow you to set the encoding for the streams.

    Unless you're running or starting an interactive application (like launching vi), you should redirect the streams and handle them.

    Note that asynchronous methods like Process.StandardOutput.ReadAsync and Process.BeginOutputReadLine use the ThreadPool to do asynchronous reads, which means they block a ThreadPool thread when waiting for application output. This approach can lead to ThreadPool starvation if you have many Processes that don’t output much. This is an issue on Windows, too.

    If you are using Begin{Output/Error}ReadLine and call WaitForExit, that method will wait until all standard output/error was read (and corresponding {Output/Error}DataReceived events are emitted). This approach can cause the call to block for a process that has exited when there are descendants that are keeping the redirected streams open.

    ProcessName

    On Linux, when executing a shell script, Process.ProcessName holds the name of the script. Similarly, Process.GetProcessesByName will match script names. This capability is useful to identify processes regardless of whether they are native executables, scripts, or scripts wrapping native executables.

    Process exit

    Processes hold up some resources in the kernel. On Windows, this information is reference counted, which allows multiple users to keep the information alive using a Process Handle. On Unix, there is a single owner of this information. First, it is the parent process, and when the parent dies, it is the init (pid 1) process (or a process that assumed this responsibility using PR_SET_CHILD_SUBREAPER). The owning process is the process responsible for cleaning up the kernel resources (aka reaping the child). .NET Core reaps child processes as soon as they terminate.

    When the resources are cleaned up, the information about the process can no longer be retrieved. Properties that return runtime information throw InvalidOperationException at that point. On Windows, you can retrieve StartTime, {Privileged,Total,User}ProcessorTime after the process exited. On Linux, these properties throw InvalidOperationException also.

    On Linux, the Process.ExitCode is valid only for direct children. For other processes, it returns 0 or throws InvalidOperationException depending on the state of the Process.

    If you are running in a container, often there is no init process. This means that no one is reaping orphaned children. Such child processes will keep consuming kernel resources, and .NET Core will never consider them exited. This issue occurs when an application has descendants that out-live their parents. If you are in this case, you should add an init process to your container. When using docker/podman run, you can add one using the --init flag.

    Conclusion

    In this article, we explained the behavior of .NET’s Process class on Linux. We covered basic use, non-supported behavior, differences with Windows, and other things to be aware of.

    Last updated: March 29, 2023

    Recent Posts

    • Federated identity across the hybrid cloud using zero trust workload identity manager

    • Confidential virtual machine storage attack scenarios

    • Introducing virtualization platform autopilot

    • Integrate zero trust workload identity manager with Red Hat OpenShift GitOps

    • Best Practice Configuration and Tuning for Linux and Windows VMs

    What’s up next?

     

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.