Finding the owner of a Process in C#

The System.Diagnostics.Process class provides lots of information about any running process, but unfortunately not its owner's identity. We need to invoke unmanaged code to get that. Every process executed on behalf of a user has a copy of its access token. That token is returned by the OpenProcessToken function, and can then be used in a WindowsIdentity constructor. I created a wrapper around this functionality as an extension method to the Process class. This allows you to get the associated Windows Identity of a Process by simply calling aProcess.WindowsIdentity.

Here's how you use the new method:

            ////
            // 'WindowsIdentity' Extension Method Demo: 
            //   Enumerate all running processes with their associated Windows Identity
            ////
 
            foreach (var p in Process.GetProcesses())
            {
                string processName;
 
                try
                {
                    processName = p.WindowsIdentity().Name;
 
                }
                catch (Exception ex)
                {
 
                    processName = ex.Message; // Probably "Access is denied"
                }
 
                Console.WriteLine(p.ProcessName + " (" + processName + ")");
            }


Here's the corresponding class:

//-----------------------------------------------------------------------
// <copyright file="ProcessExtensions.cs" company="DockOfTheBay">
//     http://www.dotbay.be
// </copyright>
// <summary>Defines the ProcessExtensions class.</summary>
//-----------------------------------------------------------------------
 
namespace DockOfTheBay
{
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
 
    /// <summary>
    /// Extension Methods for the System.Diagnostics.Process Class.
    /// </summary>
    public static class ProcessExtensions
    {
        /// <summary>
        /// Required to query an access token.
        /// </summary>
        private static uint TOKEN_QUERY = 0x0008;
 
        /// <summary>
        /// Returns the WindowsIdentity associated to a Process
        /// </summary>
        /// <param name="process">The Windows Process.</param>
        /// <returns>The WindowsIdentity of the Process.</returns>
        /// <remarks>Be prepared for 'Access Denied' Exceptions</remarks>
        public static WindowsIdentity WindowsIdentity(this Process process)
        {
            IntPtr ph = IntPtr.Zero;
            WindowsIdentity wi = null;
            try
            {
                OpenProcessToken(process.Handle, TOKEN_QUERY, out ph);
                wi = new WindowsIdentity(ph);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (ph != IntPtr.Zero)
                {
                    CloseHandle(ph);
                }
            }
 
            return wi;
        }
 
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);
 
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr hObject);
    }
}

2 reacties:

  1. Great post, and what I was looking for, BUT, it needed the following to get it working for me:
    I'm sure you can work out the tidyup and const definition code:-)

    OpenProcessToken(process.Handle, TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, out ph);

    wi = new WindowsIdentity(DuplicateToken(ph, SecurityImpersonation, ref dupeTokenHandle)?dupeTokenHandle:ph);

    ReplyDelete
  2. Just to clarify, I was using your class like this:
    using (Process ownerProcess = Process.GetProcessById((int) info.ProcessId))
    {
    using (WindowsImpersonationContext impersonationContext = ownerProcess.WindowsIdentity().Impersonate())
    {
    // Do Access / ACL stuff
    }
    }

    ReplyDelete