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)

參考:

相關文章
相關標籤/搜索