衝出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