VC程序在win7系统上运行,自动获取管理员权限

    技术2022-05-18  12

    在win7 上运行程序,经常需要管理员权限,如何让自己编写的程序启动的时候获取管理员权限呢?方法如下:

     

    1: 在VS2010中,可以参考《VS2010与Win7共舞:UAC与数据重定向》这篇文章,为了方便,这里复制过来:

     

    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

     禁用UAC Virtualization

      凡事都没有绝对。如果因为一些特殊的要求(众所周知,客户的要求千奇百怪,无奇不有),我们一定要向“Program Files”目录写入数据,这时该怎么办呢?面对这种极其特殊的情况,我们可以在应用程序的Manifest禁用UAC Virtualization,取消其对数据写操作的重定向。在项目属性中,我们设置启用UAC(Enable User Account Control),并且在UAC Execution Level中设置请求管理员权限。这样,应用程序在启动的时候,就会向用户请求管理员权限,当应用程序获得管理员执行权限后,当然可以向任意目录写入数据,UAC Virtualization也就不会起作用了。

      图2  通过Manifest禁用UAC Virtualization

      对于64位应用程序,本身是不具备UAC Virtualization机制的,所以根本不存在禁用的问题。当我们在64位应用程序中尝试向“Program Files”等敏感目录写入数据时,就会遇到一个“拒绝访问”的错误:

    <!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> // 测试文件夹是否存在 BOOL IsDirectoryExists(TCHAR * dirName) {     WIN32_FILE_ATTRIBUTE_DATA dataDirAttrData;      if ( ! ::GetFileAttributesEx(dirName, GetFileExInfoStandard, & dataDirAttrData))     {         DWORD lastError = ::GetLastError();          if (lastError == ERROR_PATH_NOT_FOUND || lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_NOT_READY)              return FALSE;     }      return (dataDirAttrData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; } // …      // 获取文件夹路径      // if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramData,      //            0, NULL, &pszPath)))      // 错误的做法:      if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFiles,          0 , NULL, & pszPath)))     {          // 提示错误         MessageBox(hwndDlg, _T( " SHGetKnownFolderPath无法获取文件路径 " ),             _T( " Error " ), MB_OK | MB_ICONERROR);          return FALSE;     } // …        // 检查文件夹是否存在      if (::IsDirectoryExists(dataFilePath))     {          // 如果文件夹不存在,则创建文件夹          if ( ! ::CreateDirectory(dataFilePath, NULL))         {             DWORD dwErrorCode = ::GetLastError();             LPCWSTR lpBuffer;              // 获取错误信息             FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER   |                    FORMAT_MESSAGE_IGNORE_INSERTS   |                  FORMAT_MESSAGE_FROM_SYSTEM,                  NULL,                  dwErrorCode, //   错误代码                  LANG_NEUTRAL,                  (LPTSTR) & lpBuffer,                  0 ,                  NULL );                           // 显示错误对话框             MessageBox(hwndDlg, lpBuffer, _T( " 创建文件夹错误 " ), MB_OK | MB_ICONERROR);             LocalFree((HLOCAL)lpBuffer);                           return FALSE;         }     }

      当这段代码执行到创建文件夹的时候,会遇到一个“拒绝访问”错误:

      图3  创建文件夹的“拒绝访问”错误

      为了避免这个错误,同样的,我们可以通过在项目属性中设置,使得Manifest中嵌入UAC相关的信息,在应用程序启动的时候请求管理员权限,就像我们在运行其他大多数需要管理器权限的应用程序一样。当应用程序获得管理员权限后,这个错误就不存在了。但是这里必须要指出,这种做法是不太安全的,能够避免尽量避免。

    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

     

    按照上述文章,VS2010编写的程序可以运行时获取管理员权限;

     

    但是如果是VS2010以前的程序呢?

    方法1:当然是移植到VS2010上了;

     

    方法2:(这才是要说的):

    (1)按照《VS2010与Win7共舞:UAC与数据重定向》上述方法,随便写一个VS2010工程,编译,在这个工程的Debug目录下会有两个文件:   *.exe.embed.manifest 和 *.exe.intermediate.manifest ;

    (2)随便复制一个 .manifest 文件到你现在的工程目录的资源文件夹(res)下,然后在工程的资源中Import这个文件;

    (3)资源文件夹设置为“24”,资源ID设置为“1”;

     

    现在ok了,你编译的程序,可以获取管理员权限了。

     

    用一下这个函数就可以启动其他程序以管理员权限,当然可以自己启动自己

    BOOL ElevateCurrentProcess(CString sCmdLine)

    {    TCHAR szPath[MAX_PATH] = {0};    if (::GetModuleFileName(NULL, szPath, MAX_PATH))     {      // Launch itself as administrator.      SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };      sei.lpVerb = _T("runas");      sei.lpFile = szPath;      sei.lpParameters = (LPCTSTR)sCmdLine;      //     sei.hwnd = hWnd;      sei.nShow = SW_SHOWNORMAL;            if (!ShellExecuteEx(&sei))       {        DWORD dwStatus = GetLastError();        if (dwStatus == ERROR_CANCELLED)         {          // The user refused to allow privileges elevation.          return FALSE;         }        else          if (dwStatus == ERROR_FILE_NOT_FOUND)           {            // The file defined by lpFile was not found and            // an error message popped up.            return FALSE;           }                    return FALSE;                  }          return TRUE;     }    return FALSE;   }

     


    最新回复(0)