閱讀139 返回首頁    go 阿裏雲 go 技術社區[雲棲]


衝出UAC-解決Win UAC問題的編程經驗

    感想關注 ,轉載引用請注明 https://blog.csdn.net/leonwei/article/details/8905703 

 

   最近一直在搞頁遊版的端遊移植,裏麵用到了很多進程啟動進程的情況,這種情況在XP以前的係統上是很常見的編程形式,也從來不會出現問題,但是搬到Win7係統上就不行,在很多用戶的Win7係統中,進程A去啟動進程B(如果直接使用CreateProcess)會創建失敗,後來發現這是因為受到了UAC的控製,將解決這類問題的經驗總結於此。

1.什麼是UAC

UAC全稱User Access Control,是Win Vista係統開始引入的一種安全機製,它在操作係統中定義了多種用戶訪問的安全級別(可在用戶賬戶中修改,默認為中),

不同的安全級別對於程序的行為是有不同限定的:

從不通知:這個跟XP一樣,沒有限定任何程序行為,是最低的

僅當程序嚐試更改計算機時通知:當你的程序會觸發對計算機的修改,更簡單的說就是你發生了寫磁盤操作,就會彈出通知詢問用戶(這是默認的)

始終通知:無論是自己還是程序修改計算機都會觸發詢問

 例如當我們在win7下打開某個程序時可能觸發這樣的畫麵

這個小盾牌我們經常看見,這就是觸發了UAC的詢問了

 

2.UAC會給編程帶來哪些問題

UAC在vista上他是一個飽受詬病的東西,因為在它降低了用戶使用程序軟件的連貫性,經常的這種彈窗很煩,而且它能帶來的安全保護又有些雞肋,所以很多用戶去控製麵板裏關了它,但是微軟在Win7之後的版本仍然保留甚至加強了這個東西,甚至在Win8版本中用戶想關它都要費點麻煩。

他對於我們的編程上更是帶來一些問題,但是既然我們還在用Windows,而UAC就是Windows的一部分,我們就要Do the Microsoft Way 了。

在編程上通常有下列問題(在開啟uac的情況下):

1.任何更改係統或者寫磁盤的操作都會失敗(例如fopen這些都會失敗)

2.對其他進程的調用會失敗(例如createprocess)

 

3.解決方案

 3.1 首先對於寫磁盤失敗這些問題,是因為你的程序啟動默認都是采用低權限啟動的,突破UAC你就要使用高權限啟動程序,行話叫elevate(提升)。一個程序啟動後是沒有辦法任何辦法elavate的,一個程序是不是被elevate隻有在啟動的那一時刻決定,查閱了一下MSDN,上麵有張圖如下,就是UAC起作用與elevate的整個過程。記住elevate隻有在啟動時可以發生,一旦它已經運行了,沒有任何辦法提升他的權限。

所以對待這樣的程序,在win7下我們要顯示的聲明他們需要elevate,而如何顯示聲明,就是把這個信息寫入exe的清單文件(,manifest),在vs下麵,清單文件一般我們讓他默認生成,而如果是想讓在win7下獲得elevate,可以建立一個新的manifest文件,內容如下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
<ms_asmv2:security>
<ms_asmv3:requestedPrivileges xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</ms_asmv3:requestedPrivileges>
</ms_asmv2:security>
</ms_asmv2:trustInfo>
</assembly>
其中的level="requireAdministrator就標誌著這個程序的執行需要elevate,在vs裏附加以上清單文件,再編譯鏈接,就會發現新生成的exe文件帶有一個盾牌,如圖,這標誌著這個程序的啟動需要以管理員權限啟動,它可能會修改係統。

當這個exe雙擊啟動時,會觸發UAC,而在得到用戶的詢問允許後,你的程序就自然獲得了高權限,就可以寫磁盤了。(相反,沒有這個盾牌,啟動後不觸發UAC,自動進入較低權限,你程序的行為可能就會被限製)

 

3.2還有一種情況是對process的調用,如你在A程序中想創建一個進程B,如果進程A的權限較低,而B的權限較高(即A有盾牌,B沒有盾牌),那麼B是回創建失敗的,怎麼辦,一種是像前麵那樣把A加個盾牌,另一種就是采用ShellExecuteEx啟動進程。

ShellExecuteEx是唯一一個微軟允許觸發UAC的進程啟動函數,如下麵代碼

SHELLEXECUTEINFO shExInfo = {0};
 shExInfo.cbSize = sizeof(shExInfo);
 shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
 shExInfo.hwnd = 0;
 shExInfo.lpVerb = _T("open");                // Operation to perform
 shExInfo.lpFile = enginePath;       // Application to start   
 shExInfo.lpParameters = szBuf;                  // Additional parameters
 shExInfo.lpDirectory = workingPath;
 shExInfo.nShow = SW_SHOW;
 shExInfo.hInstApp = 0; 

ShellExecuteEx(&shExInfo);
 

使用ShellExecuteEx啟動中,lpVerb可以指定為Open、edit等等,這個函數不僅可以啟動進程,還可以打開文件,這個函數會自動觸發UAC的詢問。

在Win7下使用Createprocess,如果發現權限不足,會直接失敗,而ShellExecuteEx則是一個好的解決方法。

 

最後更新:2017-04-03 18:51:50

  上一篇:go Android的ListPreference手動綁定數據
  下一篇:go linux下如何寫RTC驅動