解決pyinstaller在單一檔案時無法正確新增許可權清單問題,(UAC,uac_admin,manifest,asInvoker,python,requireAdministrator)
做了3天的win10的相容性測試,大部分時間都卡許可權獲取這了。
以下廢話很多,想直接找解決方法,請跳至紅字
首先,簡單說下uac,自vista後windows再次加嚴了許可權管理,uac (賬戶控制) ,就是程式對訪問一些敏感資源時的限制,當程式需要訪問限制資源時會彈窗讓使用者選擇。現在系統主要分兩種許可權管理員許可權和標準許可權,當你點選一個程式時只會呼叫標準許可權,這時對windows資料夾,Program資料夾和部分關鍵的登錄檔的修改都會報錯,訪問應該還可以。當你需要安裝驅動或者程式時可以使用右鍵後點選管理員身份執行,那程式在系統幾乎就能暢行無阻了,這樣的確很安全但體驗不好,程式設計師需要提醒使用者右鍵點開以確保程式正常進行,所以有了許可權清單,一個xml格式的檔案,它可以在程式載入前告訴系統需要怎樣的許可權,如果需要管理員許可權,系統會彈窗警告,讓使用者選擇。這個許可權清單在微軟的vs工具集中還是很好實現的,畢竟是本家的東西,但在python中就有問題了。
以下許可權方面的官方說明
https://docs.microsoft.com/en-us/windows/win32/dxtecharts/user-account-control-for-game-developers
------------------------------------------------------------------------------------------------
其實pyinstaller是有許可權清單功能的,但一直都有bug,在生成多檔案時正常,在生成單一exe時無法正確嵌入清單。
多檔案正常是因為許可權清單就放在exe旁邊,檔名和exe一樣,字尾為manifest 那麼系統就可以獲取到。
單檔案時pyinstaller會先解壓將資源丟在臨時目錄裡,清單也在其內,而系統必須先獲得許可權清單,瞭解需要怎樣的許可權才能正確執行程式,否則一律按標準許可權執行,且中途不得更改。
這個bug差不多存在4年了,直到最近19年7月出的最新3.5版,明確表示,該bug修復啦~~
然而並沒有修(小聲說:麻蛋你不說修復,我也不會花這麼長時間去讀文件,換py和pyinstaller的各種版本,總覺得自己操作有誤)
以下pyinstaller版本說明
https://pyinstaller.readthedocs.io/en/stable/CHANGES.html#id1
----------------------------------------------------------------------------------------------
經過在網頁和實驗的海洋裡顛鸞倒鳳了1天之後我決定解決問題還是要去改程式碼的
先說下pycharm除錯怎麼加命令列引數,
選單欄的run>edit configuration...>選擇你要執行的py>parameters 新增就好
注意:如果沒有找到py,請先debug執行下。
在改原始碼時我參照了國外的這位大神
https://stackoverflow.com/questions/13964909/setting-uac-to-requireadministrator-using-pyinstaller-onefile-option-and-manifes
實際上我幾乎就是原版搬過來的
注意:這裡未細測,該程式碼是否會對pyinstaller的其他功能造成影響並不清楚,強烈建議去官網下個3.5版本的pyinstaller對其修改後執行,但請勿安裝。
執行方法:解壓後直接將pyinstaller.py拖進cmd 後面跟引數即可。
在pyinstaller的api.py內搜尋
logger.info("Appending archive to EXE %s", self.name)
在其上部新增
import sys manifest_filename_ = str(sys.argv[1]).split('.py')[0] + ".exe.manifest" if os.path.exists(manifest_filename_): print "Overriding default manifest" tmpnm = tempfile.mktemp() shutil.copy2(exe, tmpnm) os.chmod(tmpnm, 0755) winmanifest.UpdateManifestResourcesFromXMLFile(tmpnm, manifest_filename_, names=[1], languages=[1033]) exe = tmpnm trash.append(tmpnm) # i am too difficult le # Fall back to just append on end of file
使用方法:將manifest檔案和py檔案放在一起,執行 pyinstaller py檔案路徑 -F --uac-admin 即可
maifest的命名規則和其內容:先用pyinstaller對py進行一次多檔案打包,也就是 pyinstaller py檔案路徑 --uac-admin 在資料夾內可以獲取到*.exe.maifest,將其拷貝到py目錄下
再執行單檔案打包。
在win10企業版和win7旗艦版測試均能獲得管理員許可權,但並沒有警告彈窗。。why? 可能是跟UAC的配置有關。sure? 管他呢。。。能用就得了
以下為測試程式碼
import os admin_dir = os.path.join(os.environ.get('SystemRoot','C:\\windows'), 'temp') os.listdir(admin_dir) sys.stdin.readline()
將其打包單一檔案並執行,不報錯即為管理員許可權。
注意:首先登陸的使用者為管理員才能成功獲得管理員許可權。
-------------------------------------------------------------------------
原始碼改的一般,對pyinstaller理解不深,歡迎大家修正,
另附:pyinstaller3.5.rar修改完成版 上傳中