判断进程是否以管理员权限运行(***)
来源:互联网 发布:数据报送管理办法 编辑:程序博客网 时间:2024/06/06 15:36
有时我们需要判断进程是否以管理员权限运行,比如在运行安装包时需要安装包进程以管理员权限运行,因为安装包将执行写注册表、注册组件等需要管理员权限的操作。如果没有申请到管理员权限,这些需要管理员权限的操作都会执行失败,则会导致安装失败。以QQ7.1安装包为例,如果当前以标准用户登录到系统中,并且UAC关闭,双击运行时将申请不到管理员权限,QQ会弹出如下的提示框:
我们的TL安装程序可以参考QQ的做法,避免出现没有管理员权限导致安装失败的问题,即如果没有申请到管理员权限,则直接弹出如上类似的提示。要弹出提示,则要判断当前安装程序的进程是否以管理员权限运行。那应该如何判断呢?
一、判断函数的实现
经查阅相关资料得知,调用GetTokenInformation函数,获取TOKEN_ELEVATION结构体信息,通过结构体中的TokenIsElevated字段就能判断出来,相关的代码如下:
BOOL IsRunasAdmin() {BOOL bElevated = FALSE; HANDLE hToken = NULL; // Get current process tokenif ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )return FALSE;TOKEN_ELEVATION tokenEle;DWORD dwRetLen = 0; // Retrieve token elevation informationif ( 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)
(3)登录的是标准用户(非管理员)
输入管理员密码后,才能正常的启动程序。
2、UAC关闭
UAC关闭,应该只是关闭了UAC提示。此种情况设置了requireAdministrator属性的程序和没有设置requireAdministrator属性的程序都要嫁衣说明。
(1)登录的是超级管理员Administrator或者管理员(普通管理员)
当然还有很多示例可以拿过来加以验证。
(2)登录的是标准用户
由上可知,程序是申请不到管理员权限的,程序是可以启动的,但是所有执行需要管理员权限的操作都会返回失败。这就是QQ在申请不到管理员权限时弹出无法安装的提示的原因所在了。
三、IsRunasAdmin函数的说明
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; // 目标进程的进程idHANDLE 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参数。
- 判断进程是否以管理员权限运行(***)
- 判断当前进程是否以管理员权限运行
- 判断进程是否以管理员权限运行
- 判断是否已经以管理员权限运行
- mfc之判断是否以管理员权限运行
- 判断进程是否"以管理员身份运行"
- VC 判断进程是否是以管理员权限运行,并且判断是否是用户进程而非服务进程
- C# 判断软件是否是管理员权限运行
- 判断当前进程是否"以管理员身份运行"的
- 判断当前进程是否"以管理员身份运行"的
- 判断当前进程是否"以管理员身份运行"的
- 判断进程是否运行
- 使程序以管理员权限运行(C++)
- bat 以管理员权限运行
- 以管理员权限运行
- 2.1 Windows核心编程-进程UAC下以管理员权限运行
- 用户是否是用管理员权限运行本进程
- bat判断进程是否运行
- 超级采样 Supersampling 方式汇总
- CSDN
- Linux元素集合—原子变量
- 错误代码调试成功后。。。
- 1.c
- 判断进程是否以管理员权限运行(***)
- 黑马程序员 JAVA基础学习笔记
- Android开发之Handler消息传递机制
- 深入理解Java:注解(Annotation)自定义注解入门
- 2864:分跑道
- Office 2010 中打开多个Excel文件只能在同一窗口中显示的问题
- jQuery ajax 传数据到后台,后台返回时success函数不执行问题
- char | string | NSString 之间的转换
- Ubuntu访问window下的磁盘分区出现“Error mounting /dev/sda5 at/media”错误