Click here to Skip to main content
15,887,175 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Hi there,

There are numerous ways to obtain the username of the current user. What I am interested in is, how can I obtain the username of the user that runs my program when the user invokes it with "run as administrator"?

Cheers,
--Alex
Posted

Below is the class that will provide the username of the process that runs my application as an administrator.

It's slow, but it's all managed code. Links to the souces of various pieces are included in the comments.

Cheers,
--Alex


Usage:
C#
int currentProcessID = Process.GetCurrentProcess().Id;
int parentID = ParentProcess.GetID(currentProcessID);
string parentOwner = ParentProcess.GetOwner(parentID);


Code:
C++
using System;
using System.Collections.Generic;
using System.Text;
//
using System.Diagnostics;
using System.Management;

public static class ParentProcess
{
    public static int GetID(int processID)
    {
        return Process.GetProcessById(processID).Parent().Id;
    }

    public static string GetOwner(int processId)
    //From: http://stackoverflow.com/questions/777548/how-do-i-determine-the-owner-of-a-process-in-c
    {

        string query = "Select * From Win32_Process Where ProcessID = " + processId;
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
        ManagementObjectCollection processList = searcher.Get();

        foreach (ManagementObject obj in processList)
        {
            string[] argList = new string[] { string.Empty };
            int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
            if (returnVal == 0)
            {
                return argList[0];
            }
        }

        return "NO OWNER";
    }
}

//from: http://stackoverflow.com/questions/394816/how-to-get-parent-process-in-net-in-managed-way
public static class ProcessExtensions
{
    private static string FindIndexedProcessName(int pid)
    {
        var processName = Process.GetProcessById(pid).ProcessName;
        var processesByName = Process.GetProcessesByName(processName);
        string processIndexdName = null;

        for (var index = 0; index < processesByName.Length; index++)
        {
            processIndexdName = index == 0 ? processName : processName + "#" + index;
            var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
            if (processId.NextValue().Equals(pid))
            {
                return processIndexdName;
            }
        }

        return processIndexdName;
    }

    private static Process FindPidFromIndexedProcessName(string indexedProcessName)
    {
        var parentId = new PerformanceCounter("Process", "Creating Process ID", indexedProcessName);
        return Process.GetProcessById((int)parentId.NextValue());
    }

    public static Process Parent(this Process process)
    {
        return FindPidFromIndexedProcessName(FindIndexedProcessName(process.Id));
    }
}
//from: http://yacsharpblog.blogspot.com/
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(
        AttributeTargets.Assembly
        | AttributeTargets.Class
        | AttributeTargets.Method,
        Inherited = false,
        AllowMultiple = false)
    ]
    public class ExtensionAttribute : Attribute
    {
    }
}
 
Share this answer
 
I would have expected that if an user is running an application under a different name from the current windows user, then the application should correctly report the correct SecurityPrincipal object for that instance.

Edit: 1st link didn't work??
Edit2: 2nd link didn't work?? MSDN copy and paste is fkd up. :-/

Go search for My.User.Name on MSDN. (i'm fed up fannying about with the links.....

VB:
VB
Function GetUserName() As String
    If TypeOf My.User.CurrentPrincipal Is _
    Security.Principal.WindowsPrincipal Then
        ' The application is using Windows authentication.
        ' The name format is DOMAIN\USERNAME.
        Dim parts() As String = Split(My.User.Name, "\")
        Dim username As String = parts(1)
        Return username
    Else
        ' The application is using custom authentication.
        Return My.User.Name
    End If
End Function
 
Share this answer
 
v3
Comments
AlexKrist 22-Sep-10 20:20pm    
I tried it and, unfortunately, it does not return the original username either.

If in Win7/Vista a Standard User runs an app under Administrator, then still the Administrator username gets returned, and I want the Standard User's username.

Thanks,
--Alex
I think you should use

System.Security.Principal.WindowsIdentity.GetCurrent.Name

or
Environment.UserName
 
Share this answer
 
v2
Comments
AlexKrist 23-Sep-10 9:04am    
I tried both and it also does not give me the username of the calling process. They both return the current username, which is the Administrator.

Thanks,
--Alex
 
Share this answer
 
Comments
AlexKrist 24-Sep-10 13:37pm    
That thread deals with obtaining the privies of the current user, which is not what I'm looking for. I just want to know who the parent user is that is running my program as administrator.

I have figurred out how to do it and will write a class that will do this. I'll post it to this thread.

Many thanks,
--Alex
Create a manifest file. Add the manifest to the application.

Put the code below in your manifest :

XML
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
            If you want to change the Windows User Account Control level replace the
            requestedExecutionLevel node with one of the following.
        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
            If you want to utilize File and Registry Virtualization for backward
            compatibility then delete the requestedExecutionLevel node.
        -->
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
      <applicationRequestMinimum>
        <defaultAssemblyRequest permissionSetReference="Custom" />
        <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
      </applicationRequestMinimum>
    </security>
  </trustInfo>
</asmv1:assembly>


Once you place requestedExecutionLevel to requireAdministrator in manifest your applcation will only run in admin mode.
 
Share this answer
 
Comments
AlexKrist 24-Sep-10 14:57pm    
And that too will not obtain the username I of the process that runs my application as an administrator.

Thanks,
--Alex

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900