判断进程是否以管理员权限运行
2015-05-01 15:32
465 查看
有时我们需要判断进程是否以管理员权限运行,比如在运行安装包时需要安装包进程以管理员权限运行,因为安装包将执行写注册表、注册组件等需要管理员权限的操作。如果没有申请到管理员权限,这些需要管理员权限的操作都会执行失败,则会导致安装失败。以QQ7.1安装包为例,如果当前以标准用户登录到系统中,并且UAC关闭,双击运行时将申请不到管理员权限,QQ会弹出如下的提示框:
我们的TL安装程序可以参考QQ的做法,避免出现没有管理员权限导致安装失败的问题,即如果没有申请到管理员权限,则直接弹出如上类似的提示。要弹出提示,则要判断当前安装程序的进程是否以管理员权限运行。那应该如何判断呢?
一、判断函数的实现
经查阅相关资料得知,调用GetTokenInformation函数,获取TOKEN_ELEVATION结构体信息,通过结构体中的TokenIsElevated字段就能判断出来,相关的代码如下:
二、管理员权限与当前用户的类型、UAC开关的关系
对于需要管理员权限的程序,可以通过内嵌manifest文件的方式,设置requireAdministrator(需要管理员权限),这样在程序启动时会申请管理员权限。在VS2010中,可以在工程的属性中进行配置,如下图所示:
程序在什么情况下可以申请到管理员权限,在什么情况下申请不到,在这里就各种场景简单的说明一下。考虑当前的登入的用户类型、UAC的打开与关闭、程序本身有没有设置requireAdministrator属性。
1、UAC打开
此种情况只讨论设置requireAdministrator属性如何申请到管理员权限的情形。对于没有设置requireAdministrator属性的程序,肯定是以非管理员权限运行的。
(1)登录的是超级管理员Administrator
默认情况下,超级管理员Administrator是禁用的,可以通过这样的途径来开启:右键计算机 ->管理 ->系统工具 ->本地用户和组 ->用户 ->右键Administrator ->属性 ->取消账户禁用 ->注销(不行就重启)->登陆Administrator即可。超级管理员在用户管理中是可以重命名的。
对于设置了requireAdministrator属性的程序,启动时能申请到管理员权限。由于Administrator是超级管理员,权限最高的用户,所以在提权的时候不会弹出UAC提示窗口。
(2)登录的是管理员(非超级管理员Administrator)
在启动设置了requireAdministrator属性的程序时,会弹出UAC提示框,如下所示:
(3)登录的是标准用户(非管理员)
在启动设置了requireAdministrator属性的程序时,会弹出输入管理员密码的UAC提示框,如下:
输入管理员密码后,才能正常的启动程序。
2、UAC关闭
UAC关闭,应该只是关闭了UAC提示。此种情况设置了requireAdministrator属性的程序和没有设置requireAdministrator属性的程序都要嫁衣说明。
(1)登录的是超级管理员Administrator或者管理员(普通管理员)
在启动设置了requireAdministrator属性的程序,会申请到管理员权限,且不会弹出UAC提示框。对于没有设置requireAdministrator属性的程序,启动时会以管理员权限运行还是标准权限运行呢?经研究,发现也会以管理员权限运行。比如在运行中输入cmd,打开cmd窗口,窗口的标题中会加上“管理员”的字样,如下所示:
当然还有很多示例可以拿过来加以验证。
(2)登录的是标准用户
在启动设置了requireAdministrator属性的程序,还会弹出提示输入管理员密码的提示框吗?UAC已经关闭,不会再弹出提示要输入管理员密码的提示框,那程序权限是如何处理的呢?查看系统关于UAC关闭时的说明如下:
由上可知,程序是申请不到管理员权限的,程序是可以启动的,但是所有执行需要管理员权限的操作都会返回失败。这就是QQ在申请不到管理员权限时弹出无法安装的提示的原因所在了。
三、IsRunasAdmin函数的说明
IsRunasAdmin已经在上面提到的所有的场景中验证通过。之前在《Windows核心编程》第5版的第4章第5节“管理员以标准用户权限运行时”看到,书中也给出了一个方法,如下所示:
四、判断其他的进程是否以管理员权限运行
上面的代码稍加改动一下,就可以实现判断其他进程是否以管理员权限运行了。假设我们知道目标进程的进程id(在测试时,我们可以到任务管理器中查看目标进程的进程id),则可以调用OpenProcess得到进程句柄,然后再将这个句柄传递给OpenProcessToken。相关代码如下所示:
因为获取的进程句柄是给OpenProcessToken函数使用的,所以根据MSDN中的说明,使用PROCESS_QUERY_INFORMATION参数。
我们的TL安装程序可以参考QQ的做法,避免出现没有管理员权限导致安装失败的问题,即如果没有申请到管理员权限,则直接弹出如上类似的提示。要弹出提示,则要判断当前安装程序的进程是否以管理员权限运行。那应该如何判断呢?
一、判断函数的实现
经查阅相关资料得知,调用GetTokenInformation函数,获取TOKEN_ELEVATION结构体信息,通过结构体中的TokenIsElevated字段就能判断出来,相关的代码如下:
BOOL IsRunasAdmin() { BOOL bElevated = FALSE; HANDLE hToken = NULL; // Get current process token if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) ) return FALSE; TOKEN_ELEVATION tokenEle; DWORD dwRetLen = 0; // Retrieve token elevation information if ( GetTokenInformation( hToken, TokenElevation, &tokenEle, sizeof(tokenEle), &dwRetLen ) ) { if ( dwRetLen == sizeof(tokenEle) ) { bElevated = tokenEle.TokenIsElevated; } } CloseHandle( hToken ); return bElevated; }
二、管理员权限与当前用户的类型、UAC开关的关系
对于需要管理员权限的程序,可以通过内嵌manifest文件的方式,设置requireAdministrator(需要管理员权限),这样在程序启动时会申请管理员权限。在VS2010中,可以在工程的属性中进行配置,如下图所示:
程序在什么情况下可以申请到管理员权限,在什么情况下申请不到,在这里就各种场景简单的说明一下。考虑当前的登入的用户类型、UAC的打开与关闭、程序本身有没有设置requireAdministrator属性。
1、UAC打开
此种情况只讨论设置requireAdministrator属性如何申请到管理员权限的情形。对于没有设置requireAdministrator属性的程序,肯定是以非管理员权限运行的。
(1)登录的是超级管理员Administrator
默认情况下,超级管理员Administrator是禁用的,可以通过这样的途径来开启:右键计算机 ->管理 ->系统工具 ->本地用户和组 ->用户 ->右键Administrator ->属性 ->取消账户禁用 ->注销(不行就重启)->登陆Administrator即可。超级管理员在用户管理中是可以重命名的。
对于设置了requireAdministrator属性的程序,启动时能申请到管理员权限。由于Administrator是超级管理员,权限最高的用户,所以在提权的时候不会弹出UAC提示窗口。
(2)登录的是管理员(非超级管理员Administrator)
在启动设置了requireAdministrator属性的程序时,会弹出UAC提示框,如下所示:
(3)登录的是标准用户(非管理员)
在启动设置了requireAdministrator属性的程序时,会弹出输入管理员密码的UAC提示框,如下:
输入管理员密码后,才能正常的启动程序。
2、UAC关闭
UAC关闭,应该只是关闭了UAC提示。此种情况设置了requireAdministrator属性的程序和没有设置requireAdministrator属性的程序都要嫁衣说明。
(1)登录的是超级管理员Administrator或者管理员(普通管理员)
在启动设置了requireAdministrator属性的程序,会申请到管理员权限,且不会弹出UAC提示框。对于没有设置requireAdministrator属性的程序,启动时会以管理员权限运行还是标准权限运行呢?经研究,发现也会以管理员权限运行。比如在运行中输入cmd,打开cmd窗口,窗口的标题中会加上“管理员”的字样,如下所示:
当然还有很多示例可以拿过来加以验证。
(2)登录的是标准用户
在启动设置了requireAdministrator属性的程序,还会弹出提示输入管理员密码的提示框吗?UAC已经关闭,不会再弹出提示要输入管理员密码的提示框,那程序权限是如何处理的呢?查看系统关于UAC关闭时的说明如下:
由上可知,程序是申请不到管理员权限的,程序是可以启动的,但是所有执行需要管理员权限的操作都会返回失败。这就是QQ在申请不到管理员权限时弹出无法安装的提示的原因所在了。
三、IsRunasAdmin函数的说明
IsRunasAdmin已经在上面提到的所有的场景中验证通过。之前在《Windows核心编程》第5版的第4章第5节“管理员以标准用户权限运行时”看到,书中也给出了一个方法,如下所示:
BOOL GetProcessElevation(TOKEN_ELEVATION_TYPE* pElevationType, BOOL* pIsAdmin) { HANDLE hToken = NULL; DWORD dwSize; // Get current process token if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) return(FALSE); BOOL bResult = FALSE; // Retrieve elevation type information if (GetTokenInformation(hToken, TokenElevationType, pElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize)) { // Create the SID corresponding to the Administrators group byte adminSID[SECURITY_MAX_SID_SIZE]; dwSize = sizeof(adminSID); CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &dwSize); if (*pElevationType == TokenElevationTypeLimited) { // Get handle to linked token (will have one if we are lua) HANDLE hUnfilteredToken = NULL; GetTokenInformation(hToken, TokenLinkedToken, (VOID*) &hUnfilteredToken, sizeof(HANDLE), &dwSize); // Check if this original token contains admin SID if (CheckTokenMembership(hUnfilteredToken, &adminSID, pIsAdmin)) { bResult = TRUE; } // Don't forget to close the unfiltered token CloseHandle(hUnfilteredToken); } else { *pIsAdmin = IsUserAnAdmin(); bResult = TRUE; } } // Don't forget to close the process token CloseHandle(hToken); return(bResult); }根据文中的意思,通过传出参数pIsAdmin可以得知进程是否以管理员权限运行。经测试,在标准用户登录且UAC打开时是有问题的,经调试,每次都会走到如下的分支:
*pIsAdmin = IsUserAnAdmin();这样就有问题,IsUserAnAdmin是判断当前登录用户是否是管理员用户。而在标准用户登录且UAC打开时,启动requireAdministrator的程序,会弹出输入管理员密码的提示框,也可以以管理员权限运行的,即使当前登录的用户不是管理员用户。
四、判断其他的进程是否以管理员权限运行
上面的代码稍加改动一下,就可以实现判断其他进程是否以管理员权限运行了。假设我们知道目标进程的进程id(在测试时,我们可以到任务管理器中查看目标进程的进程id),则可以调用OpenProcess得到进程句柄,然后再将这个句柄传递给OpenProcessToken。相关代码如下所示:
DWORD dwPid = 2337; // 目标进程的进程id HANDLE hProcess = ::OpenProcess( /*PROCESS_ALL_ACCESS*/PROCESS_QUERY_INFORMATION, FALSE, dwPid ); if ( hProcess == NULL ) { strTip.Format( _T("OpenProcess to get the process handle failed, possible reason: the process id doesn't exsit, GetLastError: %d"), GetLastError() ); AfxMessageBox( strTip ); return; } BOOL bRunAsAdmin = IsRunasAdmin( hProcess ); if ( bRunAsAdmin ) { strTip.Format( _T("Pid(%d) run as admin!"), dwPid ); } else { strTip.Format( _T("Pid(%d) don't run as admin!"), dwPid ); } AfxMessageBox( strTip );
BOOL IsRunasAdmin( HANDLE hProcess ) { BOOL bElevated = FALSE; HANDLE hToken = NULL; CString strTip; // Get target process token if ( !OpenProcessToken( hProcess/*GetCurrentProcess()*/, TOKEN_QUERY, &hToken ) ) { strTip.Format( _T("OpenProcessToken failed, GetLastError: %d"), GetLastError() ); AfxMessageBox( strTip ); return FALSE; } TOKEN_ELEVATION tokenEle; DWORD dwRetLen = 0; // Retrieve token elevation information if ( GetTokenInformation( hToken, TokenElevation, &tokenEle, sizeof(tokenEle), &dwRetLen ) ) { if ( dwRetLen == sizeof(tokenEle) ) { bElevated = tokenEle.TokenIsElevated; } } else { strTip.Format( _T("GetTokenInformation failed, GetLastError: %d"), GetLastError() ); AfxMessageBox( strTip ); } CloseHandle( hToken ); return bElevated; }注意,在调用OpenProcess获取进程句柄时,不要传递全权限的参数PROCESS_ALL_ACCESS,传递较低权限的参数PROCESS_QUERY_INFORMATION,避免因为程序的权限不够导致OpenProcess函数执行失败。至于为什么要使用PROCESS_QUERY_INFORMATION参数,可以参见MSDN中说明:
因为获取的进程句柄是给OpenProcessToken函数使用的,所以根据MSDN中的说明,使用PROCESS_QUERY_INFORMATION参数。
相关文章推荐
- 判断当前进程是否以管理员权限运行
- 判断进程是否以管理员权限运行
- 判断当前进程是否以管理员权限运行(AllocateAndInitializeSid后,用CheckTokenMembership与AdministratorsGroup进行比较,和Delphi的那个例子还有点不一样)
- VC 判断进程是否是以管理员权限运行,并且判断是否是用户进程而非服务进程
- 判断是否已经以管理员权限运行
- 判断当前进程是否以管理员程序运行的方法
- 判断当前进程是否"以管理员身份运行"的
- 用户是否是用管理员权限运行本进程
- vc 判断当前用户是否在管理员组以及是否SYSTEM权限运行
- 一个进程是否以管理员权限运行
- 判断程序是否运行在管理员权限下
- 判断当前进程是否"以管理员身份运行"的
- C# WinForm判断程序是否以管理员身份运行,UAC权限的提权与降权
- 修改hosts文件(判断是否为管理员/以管理员权限运行脚本)
- 判断当前进程是否"以管理员身份运行"的
- C# 判断软件是否是管理员权限运行
- 获取提升类型和判断进程是否以管理员身份运行
- C#判断程序是否是管理员权限运行的方法代码示例
- 判断进程是否"以管理员身份运行"
- 获取提升类型和判断进程是否以管理员身份运行