1

I am trying to determinate if my program was launched by an Administrator with admin rights or by a normal user with Administrator rights using the following code:

   private void Form1_Load(object sender, EventArgs e)
    {
      WindowsIdentity identity = WindowsIdentity.GetCurrent();
      WindowsPrincipal principal = new WindowsPrincipal(identity);
      bool isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);

      if (isAdmin)
      {
          ini();
          MessageBox.Show("The user is an admin with admin rights");
      }
      else
      {
          MessageBox.Show("Error The user is a normal user with admin rights", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
          Application.Exit();
      }

    }

But when I test this code using a normal user account with admin rights, it fails, telling me The user is an admin with admin rights.

I am using .Net 3.5 and the code needs to be compatible with Windows Vista and up.

Can anybody give me some idea to solve this, please? Thank you!!!

To clarify a little bit more, another way to see this problem is this: How can I determinate if my program (running with admin rights by the admin) is running inside the standard user account context.

ccarmona1981
  • 78
  • 1
  • 8
  • What are your definitions of "a normal user with Administrator rights" and of "an Administrator"? They seem like two different terms for the same concept to me. –  Feb 25 '15 at 19:36
  • For me, what I call a normal user is a standard user that does not belong to the administrators group, and does not have any power at all. For instance, a normal user needs to give the administrator password to install a program. An Administrator, is a power user that belongs to the administrator group, has many powers in the system, and for instance, only have to click allow to UAC messages when he wants to install a program. – ccarmona1981 Feb 25 '15 at 19:44
  • I've tried your code and it works for me. I don't know, maybe there's something you're missing about that particular user's role/permissions (like what RobDev said). – Orif Khodjaev Feb 25 '15 at 19:45
  • Ah, okay, but in that case, the normal user is not the user that's running your program. Your program is running as the administrator account that the normal user let it run as. (I'd call that "a normal user *without* administrator rights", for whatever it's worth.) –  Feb 25 '15 at 19:45
  • @hvd Ok I understand that, then what I really need to know is the following: the context. How can I determinate if my program (running with admin rights by the admin) is running inside the standard user account context. – ccarmona1981 Feb 25 '15 at 20:10
  • Sounds like duplicate of http://stackoverflow.com/questions/1220213/detect-if-running-as-administrator-with-or-without-elevated-privileges – Peter Ritchie Feb 25 '15 at 20:16

3 Answers3

0

mmm you need to know is if the user connected to that computer has Admin Rights but an user that is part of a domain control ? (active Directory?) not the BuiltIn ones ? please Clarify., take a look to this post https://social.msdn.microsoft.com/Forums/vstudio/en-US/c2166023-fcfc-4c3c-ba8f-200977971c5d/how-to-check-if-given-user-have-admin-rights-in-c

RobDev
  • 45
  • 1
  • 9
  • Thank you for your answer! To clarify, I don't need to deal with domain controls or active directory. I am thinking only in stand alone computers. – ccarmona1981 Feb 25 '15 at 20:00
0

There are more variables to account for, for instance Operating System. Which version of Microsoft Window's are you utilizing? Remember, the User Access Control (UAC) was introduced in a later version, which can impact the code. Another massive impactor will be a Domain Policy which is regulated through Active Directory.

To avoid those constraints, I would do the following:

private static bool IsElevated()
{
     var user = WindowsIdentity.GetCurrent();
     var role = WindowsPrincipal(user);
     if(Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Version.Major > 6)
           if(user != null)
                if(role.IsInRole(WindowsBuiltInRole.Administrator))
                     return true;

     return false;
}

This was a quick recreation, but you'll want to test the code to ensure it correctly queries the Operating System and User.

Greg
  • 11,302
  • 2
  • 48
  • 79
0

I did solved it!!!

Explanation

I realized that what I needed was the session ID (the enviroment) to get somehow the Logged in Username (owner of the context).

Getting the session Id was really easy:

int session = System.Diagnostics.Process.GetCurrentProcess().SessionId;

By this time, my goal was getting the username linked to this session, then I found this

Get Windows user name from SessionID

Now, with the username I thought it was really easy to check if this username belongs to an Administrator group. I was wrong. The easiest way that I found requeried to use wmi and pinvoke.

The main problem was, in order to make the queries, I must know the name of the administrators group in the current OS, that is language-dependent.

The solution was this:

http://www.pinvoke.net/default.aspx/advapi32.lookupaccountsid

I tweaked the code, put all pieces together and that was it.

Summarizing, I found the sessionid, found the username linked to session, found the OS Administrators group name, and did some Wmi queries to check if the user is an Administrator.

This solution works fine for me, but I must say that runs slow.

If anybody can improve this code, or if it is useful to anybody else, I left it here.

Just remember to add a reference to System.Management; I used Visual Studio C# Express 2010. The project was a Windows Forms Application.

Happy coding!!!

//Make sure to add a reference to System.Management; 


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management;
using System.Security.Principal;
using System.Collections;
using System.Runtime.InteropServices;



namespace RealUSer
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Getting the session id
            int session = System.Diagnostics.Process.GetCurrentProcess().SessionId;
            //Getting the username related to the session id 
            string user = GetUsernameBySessionId(session, false);
            try
            {
                //Cheching if the user belongs to the local admin group using wmi
                if (CheckAdminRights(user))
                {
                    MessageBox.Show("The logged in User "+user+" is an Admin");
                }
                else
                {
                    MessageBox.Show("The logged in User " + user + " is not an Admin");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

            }

        }
        /// <summary>
        /// This method checks if the context user, belongs to the local administrators group
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>

        public  bool CheckAdminRights(string username)
        {
            bool result = false;
            List<string> admins = new List<string>();
            //SelectQuery query = new SelectQuery("Select AccountType from Win32_UserAccount where Name=\"" + username + "\"");
            SelectQuery query = new SelectQuery("SELECT * FROM win32_group WHERE Name=\"" + getAdministratorGroupName() + "\"");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            ManagementObjectCollection OC = searcher.Get();
            IEnumerator enumerator = OC.GetEnumerator();
            enumerator.MoveNext();
            ManagementObject O = (ManagementObject)enumerator.Current;
            ManagementObjectCollection adminusers = O.GetRelated("Win32_UserAccount");
            foreach (ManagementObject envVar in adminusers)
            {
                admins.Add(envVar["Name"].ToString());
                //Console.WriteLine("Username : {0}", envVar["Name"]);
                //foreach (PropertyData pd in envVar.Properties)
                //    Console.WriteLine(string.Format("  {0,20}: {1}", pd.Name, pd.Value));
            }
            if (admins.Contains(username))
                result = true;
            return result;
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ///This code will find the administrators group name, independent of the OS language using the LookupAccountSid function with the BUILTIN\Administrators sid

        #region


        const int NO_ERROR = 0;
        const int ERROR_INSUFFICIENT_BUFFER = 122;

        enum SID_NAME_USE
        {
            SidTypeUser = 1,
            SidTypeGroup,
            SidTypeDomain,
            SidTypeAlias,
            SidTypeWellKnownGroup,
            SidTypeDeletedAccount,
            SidTypeInvalid,
            SidTypeUnknown,
            SidTypeComputer
        }

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool LookupAccountSid(
          string lpSystemName,
          [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,
          StringBuilder lpName,
          ref uint cchName,
          StringBuilder ReferencedDomainName,
          ref uint cchReferencedDomainName,
          out SID_NAME_USE peUse);

        public  string getAdministratorGroupName()
        {
            String result = "";
            StringBuilder name = new StringBuilder();
            uint cchName = (uint)name.Capacity;
            StringBuilder referencedDomainName = new StringBuilder();
            uint cchReferencedDomainName = (uint)referencedDomainName.Capacity;
            SID_NAME_USE sidUse;
            // Sid for BUILTIN\Administrators
            byte[] Sid = new byte[] { 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2 };

            int err = NO_ERROR;
            if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
            {
                err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                if (err == ERROR_INSUFFICIENT_BUFFER)
                {
                    name.EnsureCapacity((int)cchName);
                    referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
                    err = NO_ERROR;
                    if (!LookupAccountSid(null, Sid, name, ref cchName, referencedDomainName, ref cchReferencedDomainName, out sidUse))
                        err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                }
            }
            if (err == 0)
            {
                result = name.ToString();
            }

            return result;
        }

        #endregion


        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void Form1_Load(object sender, EventArgs e)
        {

        }



        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ///This code will retrieve user name given the session id

        #region
        [DllImport("Wtsapi32.dll")]
        private static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out int pBytesReturned);
        [DllImport("Wtsapi32.dll")]
        private static extern void WTSFreeMemory(IntPtr pointer);

        public static string GetUsernameBySessionId(int sessionId, bool prependDomain)
        {
            IntPtr buffer;
            int strLen;
            string username = "SYSTEM";
            if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, out buffer, out strLen) && strLen > 1)
            {
                username = Marshal.PtrToStringAnsi(buffer);
                WTSFreeMemory(buffer);
                if (prependDomain)
                {
                    if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSDomainName, out buffer, out strLen) && strLen > 1)
                    {
                        username = Marshal.PtrToStringAnsi(buffer) + "\\" + username;
                        WTSFreeMemory(buffer);
                    }
                }
            }
            return username;
        }
        public enum WTS_INFO_CLASS
        {
            WTSInitialProgram,
            WTSApplicationName,
            WTSWorkingDirectory,
            WTSOEMId,
            WTSSessionId,
            WTSUserName,
            WTSWinStationName,
            WTSDomainName,
            WTSConnectState,
            WTSClientBuildNumber,
            WTSClientName,
            WTSClientDirectory,
            WTSClientProductId,
            WTSClientHardwareId,
            WTSClientAddress,
            WTSClientDisplay,
            WTSClientProtocolType
        }
        #endregion
    }
}
Community
  • 1
  • 1
ccarmona1981
  • 78
  • 1
  • 8
  • A doubt ,with the above code did you get the result(access of admin rights)only for the logged in user rights or for all the users that has been created @ccarmona1981 – TechBrkTru Jun 09 '15 at 06:08