1. 程式人生 > >解決pyinstaller在單一檔案時無法正確新增許可權清單問題,(UAC,uac_admin,manifest,asInvoker,python,requireAdministrator)

解決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修改完成版 上傳中