最近寫程式時遇到一個問題,就是當一個程式需要管理員許可權才能正常執行該怎麼辦?
通過查閱多方資料,我總結出來幾個比較實用的辦法(每種辦法實現方法不同,同時功能上也有一些小小的差異)
方法一(批處理指令碼)
@echo off
if exist "%SystemRoot%\SysWOW64" path %path%;%windir%\SysNative;%SystemRoot%\SysWOW64;%~dp0
bcdedit >nul
if '%errorlevel%' NEQ '0' (goto UACPrompt) else (goto UACAdmin)
:UACPrompt
%1 start "" mshta vbscript:createobject("shell.application").shellexecute("""%~0""","::",,"runas",1)(window.close)&exit
exit /B
:UACAdmin
cd /d "%~dp0"
;你的程式碼寫在這裡,你可以在在這裡啟動你的程式
這個批處理指令碼程式碼可以以管理員身份啟動,並且會以檔案所在位置為工作環境。
所以,只要用這個指令碼啟動你的程式即可以管理員身份啟動你的程式。
缺點:
- 會有一個命令提示符視窗一閃而過;
- 程式啟動入口是個批處理檔案。
方法二(manifest)
在 VS 編輯器裡這樣設定專案屬性後再編譯出來的程式就會有個 UAC 盾,以後你的程式只要執行就都會請示管理員許可權。
方法三(動態提權)
所謂動態提權,就是一個沒有管理員許可權的程式程式在他認為合適的時候建立一個有管理員許可權的程式程式,程式碼很簡單:
HINSTANCE ShellExecuteA(
[in, optional] HWND hwnd, // 父視窗的控制程式碼,用於顯示 UI 或錯誤訊息。如果操作未與視窗關聯,則此值可以為NULL。
"runas",
[in] LPCSTR lpFile, // 你的程式路徑
[in, optional] LPCSTR lpParameters, // 需要傳遞的引數
[in, optional] LPCSTR lpDirectory, // 預設(工作)目錄。如果此值為 NULL,則使用當前工作目錄。如果在 lpFile 中提供了相對路徑,則不要對 lpDirectory 使用相對路徑。
[in] INT nShowCmd // 指定應用程式在開啟時如何顯示
);
其中 INT nShowCmd 引數具體可參考 Microsoft Docs - ShowWindow function,
具體函式詳情參考 Microsoft Docs - ShellExecuteA function。
方法四(利用微軟 Windows 的漏洞)
這些方法因為不推薦使用,所以不多介紹了。有 Windows UAC 漏洞,但是微軟會想辦法去修補的,所以這類方法容易失效。
補充資料
基本概念:
1。程式的許可權是繼承的,也就是說,有管理員許可權的程式建立的程式也有管理員許可權,沒有管理員許可權的程式建立程式就沒有管理員許可權(但高許可權程式建立程式必須是高許可權不是絕對的)
2。Windows Shell程式explorer本身沒有管理員許可權,如果explorer有管理員許可權,大家可以想一下,那麼它建立的程式都有管理員許可權,那UAC不就形同虛設了嗎
3。沒有許可權的程式不能建立有許可權的程式!是的,你沒有聽錯,就是不能,這是Windows作業系統規定的。但你可能會問“那麼如何提權?你不是說連explorer都沒有許可權嗎?”,答案是:Windows系統中有一個開機自啟的AppInfo服務,它直接以系統許可權執行,在一個管理員使用者登入時,系統會保留一份當前使用者的高許可權令牌並傳給AppInfo服務,提權的過程本身就是一個程式通過程式通訊把要提權的程式傳給AppInfo服務,AppInfo服務會執行一個UI程式,UI程式會接收使用者響應,如果使用者同意這次提權,AppInfo服務就使用高許可權令牌在當前使用者會話的互動視窗站的當前桌面建立管理員許可權的程式,建立時將程式的父程式替換為請求提權的程式。這樣我們看起來就好像是“沒許可權程式建立有許可權程式”了,其實高許可權程式不是它建立的。
參考文件
讓bat批處理以管理員許可權執行的實現方法
[Win32] UAC使用者賬戶控制(提權+降權)
Microsoft 技術文件
宣告
本文作者:SeaYJ
轉載請註明出處:https://www.cnblogs.com/SeaYJ/p/15778337.html