17

I'm trying to get a list of processes currently owned by the current user (Environment.UserName). Unfortunately, the Process class doesn't have any way of getting the UserName of the user owning a process.

How do you get the UserName of the user which is the owner of a process using the Process class so I can compare it to Environment.UserName?

If your solution requires a pinvoke, please provide a code example.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175

7 Answers7

16

Thanks, your answers put me on the proper path. For those who needs a code sample:

public class App
{
    public static void Main(string[] Args)
    {
        Management.ManagementObjectSearcher Processes = new Management.ManagementObjectSearcher("SELECT * FROM Win32_Process");

        foreach (Management.ManagementObject Process in Processes.Get()) {
            if (Process["ExecutablePath"] != null) {
                string ExecutablePath = Process["ExecutablePath"].ToString();

                string[] OwnerInfo = new string[2];
                Process.InvokeMethod("GetOwner", (object[]) OwnerInfo);

                Console.WriteLine(string.Format("{0}: {1}", IO.Path.GetFileName(ExecutablePath), OwnerInfo[0]));
            }
        }

        Console.ReadLine();
    }
}
Hand-E-Food
  • 12,368
  • 8
  • 45
  • 80
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
12

The CodeProject article How To Get Process Owner ID and Current User SID by Warlib describes how to do this using both WMI and using the Win32 API via PInvoke.

The WMI code is much simpler but is slower to execute. Your question doesn't indicate which would be more appropriate for your scenario.

Martin Hollingsworth
  • 7,249
  • 7
  • 49
  • 51
3

You will have a hard time getting the username without being an administrator on the computer.

None of the methods with WMI, through the OpenProcess or using the WTSEnumerateProcesses will give you the username unless you are an administrator. Trying to enable SeDebugPrivilege etc does not work either. I have still to see a code that works without being the admin.

If anyone know how to get this WITHOUT being an admin on the machine it is being run, please write how to do it, as I have not found out how to enable that level of access to a service user.

Wolf5
  • 16,600
  • 12
  • 59
  • 58
  • https://social.msdn.microsoft.com/Forums/vstudio/en-US/aeff7e41-a4ba-4bf0-8677-81162040984d/retrieving-username-of-a-running-process?forum=netfxbcl – TomO Feb 09 '16 at 21:35
  • 1
    Checked that one. Problem is it gets the username for a Session. And if I open up 2 CMD windows with 2 different users, they both have the same Session ID (2). And both resolve to the same user, which is wrong. Taskmanager shows them correctly. – Wolf5 Feb 10 '16 at 10:09
  • I've been away from this problem for a bit, but wouldn't they have different ProcID's? Can't remember what it returns, but just thinking out loud here. – TomO Mar 10 '16 at 15:25
  • 1
    Yup. Diff proc Ids but same session ID. The lookup maps 1 session ID to 1 user. So several different processes with different process users will map to the same user with this method. – Wolf5 Mar 11 '16 at 08:47
2

Props to Andrew Moore for his answer, I'm merely formatting it because it didn't compile in C# 3.5.

private string GetUserName(string procName)
{
    string query = "SELECT * FROM Win32_Process WHERE Name = \'" + procName + "\'";
    var procs = new System.Management.ManagementObjectSearcher(query);
    foreach (System.Management.ManagementObject p in procs.Get())
    {
        var path = p["ExecutablePath"];
        if (path != null)
        {
            string executablePath = path.ToString();
            string[] ownerInfo = new string[2];
            p.InvokeMethod("GetOwner", (object[])ownerInfo);
            return ownerInfo[0];
        }
    }
    return null;
}
sean.net
  • 735
  • 8
  • 25
2

You might look at using System.Management (WMI). With that you can query the Win32_Process tree.

palehorse
  • 26,407
  • 4
  • 40
  • 48
2

here is the MS link labelled "GetOwner Method of the Win32_Process Class"

Oskar
  • 2,234
  • 5
  • 28
  • 35
0

You'll need to add a reference to System.Management.dll for this to work.

Here's what I ended up using. It works in .NET 3.5:

using System.Linq;
using System.Management;

class Program
{
    /// <summary>
    /// Adapted from https://www.codeproject.com/Articles/14828/How-To-Get-Process-Owner-ID-and-Current-User-SID
    /// </summary>
    public static void GetProcessOwnerByProcessId(int processId, out string user, out string domain)
    {
        user = "???";
        domain = "???";

        var sq = new ObjectQuery("Select * from Win32_Process Where ProcessID = '" + processId + "'");
        var searcher = new ManagementObjectSearcher(sq);
        if (searcher.Get().Count != 1)
        {
            return;
        }
        var process = searcher.Get().Cast<ManagementObject>().First();
        var ownerInfo = new string[2];
        process.InvokeMethod("GetOwner", ownerInfo);

        if (user != null)
        {
            user = ownerInfo[0];
        }
        if (domain != null)
        {
            domain = ownerInfo[1];
        }
    }

    public static void Main()
    {
        var processId = System.Diagnostics.Process.GetCurrentProcess().Id;
        string user;
        string domain;
        GetProcessOwnerByProcessId(processId, out user, out domain);
        System.Console.WriteLine(domain + "\\" + user);
    }
}
Jesus is Lord
  • 14,971
  • 11
  • 66
  • 97