[問題] 安裝 Console 應用程式
準確來說是把程式目錄新增至環境變數 PATH 之中,
方便在終端機中使用檔名或 basename 呼叫程式並執行。
但當程式越來越多後 PATH 就會變得越來越臃腫。
為了保持 PATH 簡潔,需要統一使用同一個目錄,我嘗試了以下方法。
方法 1. 在同一目錄下放置所有程式的子目錄、檔案
這是最簡單粗暴的方法
但,由於所有程式的子目錄與檔案都混在一起,
可能遇到檔案衝突,且管理上也很不方便。
方法 2. 在同一目錄建立目標程式的符號連結
PowerShell:
--------
New-Item -ItemType SymbolicLink -Path program1.exe -Target "C:\My Programs\pro
gram1\program1.exe"
--------
符號連結的好處是簡單且方便管理。
但通過符號連結執行程式會因為找不到依賴的檔案 (例如 dll 檔) 而無法正常執行,
所以只適合用於單 exe 檔的程式。
或者,要為所有項目也建立符號連結。
但這可能會與其他程式的同名子目錄或檔案的符號連結衝突。
方法 3. 在同一目錄下建立執行目標程式的 bat 檔案
program1.bat:
--------
@echo off
"C:\My Programs\program1\program1.exe" %*
exit /b %ERRORLEVEL%
--------
bat 檔的好處是可以使用 set 命令預先設定必要的臨時環境參數。
但使用 bat 檔會遇到一個棘手的問題。
由於 bat 的 args 需要按照 cmd 的方式跳脫字元,
這導致我必須重寫現有 powershell 腳本裡的受影響的程式的執行命令。
或者必須在 bat 內就跳脫所有特殊字元,
但 cmd 貧弱的字串處理能力,還有一堆例外狀況,想到就讓人怯步…
以上三種方法無論是哪一種都有缺點
搞了半天還是乖乖往 PATH 內新增每個程式的目錄比較實際...
有沒有人知道更加漂亮的解決方式?
--
Sent from PTTopia
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.231.152.70 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/Windows/M.1714045005.A.193.html
推
04/25 19:51,
7月前
, 1F
04/25 19:51, 1F
→
04/25 20:00,
7月前
, 2F
04/25 20:00, 2F
→
04/25 20:18,
7月前
, 3F
04/25 20:18, 3F
python 腳本的問題就是在 powershell 或 cmd 無法只使用 basename 呼叫並執行
PS> .\program # 執行名為 program 的可執行檔,例如 program.bat
PS> python .\program.py # 執行 python 腳本 program.py
這會導致我要需要重寫我所有的 powershell 腳本
推
04/26 14:06,
6月前
, 4F
04/26 14:06, 4F
→
04/26 14:07,
6月前
, 5F
04/26 14:07, 5F
微軟自己的 winget 安裝 Console 程式就是在同一資料夾為所有 exe 檔建立符號連結
遺失依賴檔案的問題在 GitHub 上也是個開啟中的 Issue
→
04/26 14:10,
6月前
, 6F
04/26 14:10, 6F
→
04/26 14:11,
6月前
, 7F
04/26 14:11, 7F
→
04/26 14:11,
6月前
, 8F
04/26 14:11, 8F
這個方法稍微嘗試一下,目前還沒發現什麼問題
推
04/26 14:18,
6月前
, 9F
04/26 14:18, 9F
推
04/26 14:21,
6月前
, 10F
04/26 14:21, 10F
推
04/26 15:58,
6月前
, 11F
04/26 15:58, 11F
→
04/26 15:59,
6月前
, 12F
04/26 15:59, 12F
推
04/26 16:01,
6月前
, 13F
04/26 16:01, 13F
問題不於如何執行目標程式,而是如何跳脫 args 中的所有特殊字元
例如在 powershell 用 ffmpeg 轉換影片格式
原始 ffmpeg.exe
PS> .\ffmepg -i input.mp4 ^outpu.mkv # 實際輸出檔案名稱為 "^outpu.mkv"
ffmpeg.bat
PS> .\ffmpeg -i input.mp4 ^outpu.mkv # 實際輸出檔案名稱為 "outpu.mkv"
※ 編輯: falcon (118.231.152.70 臺灣), 04/26/2024 21:07:30
→
04/26 21:25,
6月前
, 14F
04/26 21:25, 14F
→
04/26 21:37,
6月前
, 15F
04/26 21:37, 15F
→
04/26 21:46,
6月前
, 16F
04/26 21:46, 16F
→
04/26 22:23,
6月前
, 17F
04/26 22:23, 17F
→
04/26 22:24,
6月前
, 18F
04/26 22:24, 18F
推
04/26 23:09,
6月前
, 19F
04/26 23:09, 19F
→
04/26 23:09,
6月前
, 20F
04/26 23:09, 20F
→
04/26 23:09,
6月前
, 21F
04/26 23:09, 21F
→
04/26 23:09,
6月前
, 22F
04/26 23:09, 22F
推
04/26 23:37,
6月前
, 23F
04/26 23:37, 23F
→
04/26 23:37,
6月前
, 24F
04/26 23:37, 24F
→
04/26 23:38,
6月前
, 25F
04/26 23:38, 25F
推
04/27 00:22,
6月前
, 26F
04/27 00:22, 26F
推
04/27 00:32,
6月前
, 27F
04/27 00:32, 27F
→
04/27 00:35,
6月前
, 28F
04/27 00:35, 28F
我發現搞錯一點了
還以為有名的參數一定要在 param() 內先宣告
不知道沒有宣告的都會被丟到 $args
那就奇怪了...
微軟的 winget 安裝 console 程式怎麼怎麼不用 .ps1 檔取代 links 目錄下的符號連結
這樣就不會因為程式找不到依賴檔案而無法正常執行了
推
04/27 00:38,
6月前
, 29F
04/27 00:38, 29F
→
04/27 00:40,
6月前
, 30F
04/27 00:40, 30F
※ 編輯: falcon (118.231.152.70 臺灣), 04/27/2024 00:59:44
→
04/27 01:03,
6月前
, 31F
04/27 01:03, 31F
→
04/27 01:03,
6月前
, 32F
04/27 01:03, 32F
推
04/27 02:17,
6月前
, 33F
04/27 02:17, 33F
→
04/27 02:17,
6月前
, 34F
04/27 02:17, 34F
→
04/27 02:17,
6月前
, 35F
04/27 02:17, 35F
對了 順便問題下
遇到 Linux 移植過來的程式,那些 share 的檔案要放哪裡?
通常是 config 或 preset 檔案
在 linux 中,我記得預設目錄位置是
/usr/local/share/<program name>
使用時只要給程式檔名或 basename 就可以了
但在 Windows 下如果不把工作目錄切過去
好像就只能使用絕對路徑了?
※ 編輯: falcon (118.231.152.70 臺灣), 04/27/2024 03:27:27
推
04/27 18:31,
6月前
, 36F
04/27 18:31, 36F
→
04/27 18:37,
6月前
, 37F
04/27 18:37, 37F
試過許多路徑與環境變數都沒用
看起來有些程式並沒有為 Windows 設定程式資料目錄
只能在 .ps1 檔內自動修改目標參數的值了
param ([Alias('pre')][string]$preset)
$programArgs = $args
if (-not !$preset) {
Push-Location 'C:\My Programs\program1\presets'
$absConfigPath =
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($preset)
Pop-Location
$programArgs += @('-pre', """$($absConfigPath)""")
}
& "C:\My Programs\program1\bin\program1.exe" $programArgs
exit $lastExitCode
※ 編輯: falcon (118.231.152.70 臺灣), 04/28/2024 15:15:11
→
04/29 11:54,
6月前
, 38F
04/29 11:54, 38F
→
04/29 11:54,
6月前
, 39F
04/29 11:54, 39F
→
04/29 11:55,
6月前
, 40F
04/29 11:55, 40F
以 % 字元為例,在 cmd 必須 %% 來代表一個 % 常值字元
powershell 或 bash 中
ffmpeg -i input.mkv frame-%d.png
cmd 中
ffmpeg -i input.mkv frame-%%d.png
其他特殊字元若要表示為常值則是要在前面加上 ^ 字元
還有一些奇奇怪怪的例外除理方式...
關於 powershell 腳本
目前已發現的問題是在就發現就是使用了 param() 後
一旦傳入了未在 param() 中宣告的參數並不會被存入 $args 變數中
而是會發生錯誤
「參數無法處理,因為 '???' 參數名稱不明確......」
※ 編輯: falcon (39.10.17.37 臺灣), 04/29/2024 22:56:27
→
04/29 23:31,
6月前
, 41F
04/29 23:31, 41F
→
04/29 23:31,
6月前
, 42F
04/29 23:31, 42F
→
04/29 23:31,
6月前
, 43F
04/29 23:31, 43F
→
04/29 23:31,
6月前
, 44F
04/29 23:31, 44F
→
04/30 09:56,
6月前
, 45F
04/30 09:56, 45F
→
04/30 09:57,
6月前
, 46F
04/30 09:57, 46F
→
04/30 10:02,
6月前
, 47F
04/30 10:02, 47F
→
04/30 10:16,
6月前
, 48F
04/30 10:16, 48F
→
04/30 13:38,
6月前
, 49F
04/30 13:38, 49F
→
04/30 13:38,
6月前
, 50F
04/30 13:38, 50F
→
04/30 13:38,
6月前
, 51F
04/30 13:38, 51F
→
04/30 13:40,
6月前
, 52F
04/30 13:40, 52F
→
04/30 13:44,
6月前
, 53F
04/30 13:44, 53F
→
04/30 16:32,
6月前
, 54F
04/30 16:32, 54F
例如這個例子執行時會發生錯誤
ffmpeg.exe -i input.mkv frame-%d.png
只會得到第一個畫面的圖片 frame-d.png
與輸出路徑格式錯誤訊息
必須讓程式收到 args 長下面這個樣子
ffmpeg.exe -i input.mkv frame-%%d.png
因為 % 在 cmd 中有特殊意義
例如 %~d1 為 bat 將 arg1 路徑擴展為磁碟機代號
→
04/30 16:33,
6月前
, 55F
04/30 16:33, 55F
→
04/30 16:34,
6月前
, 56F
04/30 16:34, 56F
*[32m※ 編輯: falcon (39.10.17.37 臺灣), 05/01/2024 11:50:37*[m
→
05/01 13:40,
6月前
, 57F
05/01 13:40, 57F
→
05/01 13:41,
6月前
, 58F
05/01 13:41, 58F
→
05/01 13:41,
6月前
, 59F
05/01 13:41, 59F
→
05/01 13:45,
6月前
, 60F
05/01 13:45, 60F
→
05/01 13:49,
6月前
, 61F
05/01 13:49, 61F
→
05/01 14:12,
6月前
, 62F
05/01 14:12, 62F
我理解你所說的,我之前也是這樣做
但我再嘗試了一次,沒有發生錯誤
也找不到重現問題的關鍵點在哪裡......
還是自動新增程式目錄到 PATH 比較省事...
$programDirPaths = $env:PATHEXT -split ';' | % {"*$($_)"} |
Get-ChildItem -Include $_ -Recurse |
% {$_.DirectoryName} | Sort-Object -Unique
$newEnvPathVal = (([Environment]::GetEnvironmentVariable(
"Path", "Machine") -split ';') + $programDirPaths) -join ';'
[Environment]::SetEnvironmentVariable("Path", $newEnvPathVal, "Machine")
※ 編輯: falcon (39.10.17.37 臺灣), 05/01/2024 21:30:08
→
05/01 21:47,
6月前
, 63F
05/01 21:47, 63F
推
05/02 07:59,
6月前
, 64F
05/02 07:59, 64F
Windows 近期熱門文章
PTT數位生活區 即時熱門文章