2023年1月25日 星期三

如何把 PowerShell 的代碼寫入 Bat 整合成一個檔案

如何把 PowerShell 的代碼寫入 Bat 整合成一個檔案

因為PowerShell的檔案 ps1 沒辦法直接點擊執行,雖然可以透過改登錄檔的方案實現不過整體麻煩程度太大了,要發佈到其他電腦上執行不太合適

檔案可以儲存成 bat 或 cmd 這兩個附檔名是等價的,從微軟的技術文件可以看到 Windwos98 以前使用 bat 副檔名,而在 WindwosXP 之後因為命令提示字元的版本升級了,為了做出區別才新增了 cmd 的副檔名

不過新系統本身有向下相容,所以即便使用舊檔名也不會有任何影響。對於舊系統 Windwos98 為了避免執行到新版本的代碼,可以使用 cmd 的副檔名做區隔。


整合的關鍵實現原理

說白了其實就是利用臨時環境變數當作通道,由Bat把自身的路徑Path寫入環境變數,然後再由Bat執行Powershell,此時因為環境變數是共通的就能讀取到Bat檔案了

讀取到Bat檔案檔案,再由事先做好的註解來區分哪些是 PwshScript 只執行這一部分就好,這麼一個流程實現的

這邊這個思路是參考 AveYo 的源代碼抽出一部分出來實現 ps1 與 bat 整合的


範例代碼

FileName: RunPwsh.cmd 

檔案請依照第四行後面用UTF8編碼儲存,或是把第四行改成Big5並用Big5編碼儲存


:: 2023-01-25 By:Charlotte.Hong
@echo off

set "0=%~f0"& set "1=%~dp0"& set "2=%*"& set PwshScript=([Io.File]::ReadAllText($env:0,[Text.Encoding]::GetEncoding('UTF-8')) -split '[:]PwshScript')
powershell -nop -exec Bypass -c "(%PwshScript%[1])|iex; Exit $LastExitCode"

echo ExitCode: %errorlevel%
pause
Exit /b %errorlevel%

:PwshScript#:: Script1 # 2023-01-25 By:Charlotte.Hong
#:: --------------------------------------------------------------------------------------------------------------------------------
Write-Host "by PSVersion::" $PSVersionTable.PSVersion
Write-Host "Arguments=" $env:2
Write-Host "Test OK. By:Charlotte.Hong"

:PwshScript#:: End
#:: --------------------------------------------------------------------------------------------------------------------------------


然後直接雙擊執行或從終端機執行即可


參數的獲取方式可以參考上圖的執行方法



Encoding亂碼的問題

上述的範例 PowerShell 會用UTF8編碼讀取Bat檔案,這是為了方便能夠在PwshScript裡面寫入各國語言。

不過這樣做有個很現實的問題,Windwos 預設是用系統語言來讀取Bat檔案的,也就是說在PwshScript之外的代碼,Bat代碼的部分如果輸入非英文就會亂碼。

把它改成Big5的弊端是在 PwshScript 裡就不能輸入日文了,看大家怎麼取捨了。我是鐵了心就是不寫Bat的代碼,所以選擇UTF8顧好 PwshScript 的部分就好。




沒有留言:

張貼留言