VC程序获取管理员权限

一:

编译程序的时候设置一下
在项目属性--链接器--清单文件--UAC执行级别改成requireAdministratorc++

二:

void GainAdminPrivileges(CString strApp, UINT idd)
{
    CString         strCmd;
    strCmd.Format (_T("/adminoption %d"), idd);

    SHELLEXECUTEINFO execinfo;
    memset(&execinfo, 0, sizeof(execinfo));
    execinfo.lpFile         = strApp;
    execinfo.cbSize         = sizeof(execinfo);
    execinfo.lpVerb         = _T("runas");
    execinfo.fMask          = SEE_MASK_NO_CONSOLE;
    execinfo.nShow          = SW_SHOWDEFAULT;
    execinfo.lpParameters   = strCmd;

    ShellExecuteEx(&execinfo);
}

strApp是应用程序的路径idd我传的是1,但好像传几都没问题shell

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;
}

如何获取正确的文件路径

当咱们那些在Windows 7以前设计的应用程序遇到UAC Virtualization问题的时候,咱们须要重新设计咱们的代码,将文件写入到合适的位置。在改善既有代码,使之能够与Windows 7兼容的时候,咱们应该确保如下几点:编程

  ——在运行的时候,应用程序只会将数据保存到每一个用户预先定义的位置或者是%alluserprofile% 中定义的普通用户拥有访问权限的位置。windows

  ——肯定你要写入数据的“已知文件夹”(Knownfolders)。一般,全部用户共用的公共数据文件应该写入到一个全局的公共的位置,这样全部用户均可以访问到。而其它数据则应该写入每一个用户本身的文件夹。api

  1 公共数据文件包括日志文件,配置文件(一般是INI或者XML文件),应用程序状态文件,好比保存的游戏进程等等。函数

  2 而属于每一个用户的文档,则应该保持在文档目录下,或者是用户本身指定的目录。ui

  ——当你肯定合适的文件保存位置后,不要在代码中明文写出(Hard-code)你选择的路径。为了更好地保持兼容性,咱们应该采用下面这些API来得到操做系统“已知文件夹(Knownfolders)”的正确路径。操作系统

  1 C/C++非托管代码: 使用SHGetKnownFolderPath函数,经过指定“已知文件夹”的KNOWNFOLDERID做为参数来得到正确的文件夹路径。.net

  FOLDERID_ProgramData –全部用户均可以访问的应用程序数据适合放置在这个目录下。
  FOLDERID_LocalAppData – 每一个用户单独访问的应用程序数据适合放置在这个目录下。
  FOLDERID_RoamingAppData – 每一个用户单独访问的应用程序数据适合放置在这个目录下。 与上面一个目录不一样的是,放置在这个目录下的文件会随着用户迁移,当一个用户在同一个域中的其余计算机登陆的时候,这些文件会被复制到当前登陆的机器上,就像用户随身携带的公文包同样。

下面这段代码演示了在非托管代码中如何调用shell函数,SHGetKnownFolderPath函数得到正确的文件保存路径(SHGetFolderLocation, SHGetFolderPath, SHGetSpecialFolderLocation, SHGetSpecialFolderPath):设计

#include "shlobj.h"
#include "shlwapi.h"
//…

#define AppFolderName _T("YourApp")
#define DataFileName _T("SomeFile.txt")

// 构造一个数据文件路径
// dataFilePath指向一个长度为MAX_PATH,类型为TCHAR的字符串数值
// hwndDlg是消息对话框的父窗口句柄
// 当有错误发生的时候用于显示错误提示
// includeFileName用于表示是否在路径后面扩展文件名
BOOL MakeDataFilePath(TCHAR *dataFilePath, 
                      HWND hwndDlg, BOOL includeFileName)
{
    // 初始化工做
    memset(dataFilePath, 0, MAX_PATH * sizeof(TCHAR));
    PWSTR pszPath = NULL;

    // SHGetKnownFolderPath函数能够返回一个已知文件见的路径,
    // 例如个人文档(My Documents),桌面(Desktop),
       // 应用程序文件夹(Program Files)等等。 
    // 对于数据文件来讲,FOLDERID_ProgramFiles并非一个合适的位置
    // 使用FOLDERID_ProgramFiles保存全部用户共享的数据文件
    // 使用FOLDERID_LocalAppData保存属于每一个用户本身的文件(non-roaming).
    // 使用FOLDERID_RoamingAppData保存属于每一个用户本身的文件(roaming).
// 对于“随身文件”(Roaming files),
// 当一个用户在一个域中的其余计算机登录的时候,
    // 这些文件会被复制到当前登陆的机器上,就像用户随身携带的公文包同样    

    // 获取文件夹路径
    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;
    }

    // 复制路径到目标变量
    _tcscpy_s(dataFilePath, MAX_PATH, pszPath);
    ::CoTaskMemFree(pszPath);

    //错误的作法: _tcscpy_s(dataFilePath, MAX_PATH, _T("C:\\"));

    // 在路径后面扩展应用程序所在文件夹
    if (!::PathAppend(dataFilePath, AppFolderName))
    {
        // 提示错误
        MessageBox(hwndDlg, _T("PathAppend没法扩展路径"),
            _T("Error"), MB_OK | MB_ICONERROR);
        return FALSE;
    }

    // 是否添加文件名
    if (includeFileName)
    {
        // 在路径后扩展文件名
        if (!::PathAppend(dataFilePath, DataFileName))
        {
            // 提示错误
            MessageBox(hwndDlg, _T("PathAppend没法扩展文件名"),
                _T("Error"), MB_OK | MB_ICONERROR);
            return FALSE;
        }
    }

    return TRUE;
}

2 托管代码: 使用System.Environment.GetFolderPath函数,经过指定咱们想要获取的“已知文件夹”为参数,从而获取相应的文件夹的正确路径。

  Environment.SpecialFolder.CommonApplicationData – 全部用户均可以访问的应用程序数据适合放置在这个目录下。
  Environment.SpecialFolder.LocalApplicationData – 每一个用户单独访问的应用程序数据适合放置在这个目录下。
  Environment.SpecialFolder.ApplicationData – 每一个用户单独访问的应用程序数据适合放置在这个目录下。这是“随身文件夹”。

下面这段代码展现了如何在托管代码中获取正确的文件路径:

internal class FileIO
    {
        private const string AppFolderName = "YourApp";
        private const string DataFileName = "SomeFile.txt";
        private static string _dataFilePath;

        /// <summary>
        /// 构建路径
        /// </summary>
        static FileIO()
        {
            // Environment.GetFolderPath返回一个“已知文件夹”的路径
            // Path.Combine能够合并两个路径成一个合法的路径

            // …
            
            _dataFilePath = Path.Combine(Environment.GetFolderPath(
                  Environment.SpecialFolder.ProgramFiles), AppFolderName);
            //错误的作法:
            //_dataFilePath = Path.Combine(Environment.GetFolderPath(
             Environment.SpecialFolder.CommonApplicationData), AppFolderName);
            
            // 扩展文件名
            _dataFilePath = Path.Combine(_dataFilePath, DataFileName);
        }

         public static void Save(string text)
        {
            // 检查要保存的字符串是否为空
            if (String.IsNullOrEmpty(text))
            {
                MessageBox.Show("字符串为空,没法保持.", "空字符串",
                     MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                // 获取文件保存的路径
                string dirPath = Path.GetDirectoryName(_dataFilePath);
                // 检查文件夹是否存在
                if (!Directory.Exists(dirPath))
                    Directory.CreateDirectory(dirPath); // 建立文件夹
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "文件夹建立失败",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                // 保存字符串到文件
                StreamWriter sw = new StreamWriter(_dataFilePath);
                try
                {
                    sw.Write(text);
                }
                finally
                {
                    // 关闭文件
                    sw.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "文件写入失败",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        // …
   }
}

若是上面的方法都不适合你,你还可使用环境变量,使用getenv()或GetEnvironmentVariable()获取相应的文件夹路径:

  %ALLUSERSPROFILE% – 全部用户均可以访问的应用程序数据适合放置在这个目录下。
  %LOCALAPPDATA% – 每一个用户单独访问的应用程序数据适合放置在这个目录下。 - (Windows Vista 或者Windows 7)
  %APPDATA% – 每一个用户单独访问的应用程序数据适合放置在这个目录下。这是“随身文件夹”。- (Windows Vista 或者Windows 7)

参考:

相关文章
相关标签/搜索