在 Windows 10 中,按住 Shift 鍵並右鍵點選資料夾或檔案總管的背景,會在上下文功能表中新增「在此處開啟 PowerShell 視窗」指令。
但是,用於開啟 PowerShell 視窗的命令定義不明確(至少從 W10 版本 ID 1709 開始),因為它錯誤地假設資料夾名稱從不包含嵌入'
字元:
# !! Breaks with folder names such as "a'b"
powershell.exe -noexit -command Set-Location -literalPath '%V'
請參閱下面的修復程序,但請注意,它需要管理權限。
答案1
更新:獨立命令 --- 沒有腳本檔案依賴性。
複製、貼上並在 a 中執行此程式碼電源外殼用於即時「概念驗證」演示的控制台:
$msg = @'
$Args[0] : {0}
$Args[1] : {1}
'@
&{echo ($msg -f $Args[0], $Args[1])} --% I'm an unquoted string with an apostrophe and spaces.
輸出:
PS C:\> $msg = @'
>> $Args[0] : {0}
>> $Args[1] : {1}
>> '@
>> &{echo ($msg -f $Args[0], $Args[1])} --% I'm an unqoted string with an apostroohe and spaces.
$Args[0] : --%
$Args[1] : I'm an unqoted string with an apostroohe and spaces.
PS C:\>
- (有趣的是,它既
--%
是功能性的,也是作為參數捕獲的)
「神奇的子彈」是停止解析令牌: --%
。根據文件:
PowerShell 3.0 中引入的停止解析符號 (--%) 指示 PowerShell 避免將輸入解釋為 PowerShell 指令或表達式。
……
當遇到停止解析符號時,PowerShell 會將行中的剩餘字元視為文字。
雖然旨在與可執行檔的參數一起使用,但它也可以與腳本區塊的參數一起使用,如上面的程式碼所示。
因此,要使用不含引號的路徑執行Set-Location
,語法為:
&{Set-Location -LiteralPath $Args[1]} --% <unquoted path>
因此我們的註冊表命令變為:
powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V
%%
請注意,需要使用雙百分號 ( ) 才能%
在結果指令中產生文字符號。
若要在電腦範圍內修改命令,請直接編輯登錄機碼。相關的鍵是:
HKLM\SOFTWARE\Classes\Directory\Background\Shell\PowerShell\Command
HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
編輯該
(Default)
值,將其變更為:powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V
刪除
Full Control
您為使用者新增的權限。TrustedInstaller
透過NT Service\TrustedInstaller
在您取得所有權的步驟中指定使用者名稱來將所有者變更回。
若要針對每個使用者修改命令,只需建立並編輯登錄項目:
HKCU\Softwar\Classes\Directory\Background\Shell\PowerShell\Command
HKCU\Software\Classes\Directory\Shell\PowerShell\Command
將的值更改(Default)
為:powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V
或只是複製、貼上並執行以下命令:
'Background\','' | ForEach{
$splat = @{
'Path' = ('HKCU:\Software\Classes\Directory\{0}Shell\PowerShell\Command' -f $_)
'Value' = 'powershell.exe -NoExit -Command &{Set-Location -LiteralPath $Args[1]} --%% %V'
}
New-Item @splat -Force
}
原始回覆
對於 5.1 的解決方法,我想不出一個方法電源外殼命令行,但呼叫單行腳本似乎可以解決問題:
(根據 @mklement0 的評論進行程式碼編輯/改進)
### OpenHere.ps1
Set-Location -LiteralPath $Args[0]
### (HKCU|HKLM)\Software\Classes\Direcory[\Background]\Shell\PowerShell\Command
###
###powershell.exe -noexit -File "C:\Path\to\OpenHere.ps1" "%V"
###
- 另存為“OpenHere.ps1”到適當的位置
- 然後您可以修改:
HKLM\SOFTWARE\Classes\Directory\Shell\PowerShell\Command
如果您具有管理員存取權限並且能夠輕鬆處理所有權和權限。
否則,您可以在以下位置建立每個使用者條目:HKCU\Software\Classes\Directory\Shell\PowerShell\Command
註冊表命令行的語法是:
powershell.exe -noexit -File "C:\Path\to\OpenHere.ps1" "%V"
這是上述程式碼的“自安裝”版本,它將在HKCU
(每用戶模式)下建立上下文選單條目。
- 將以下內容儲存為
.ps1
檔案並保存在其所在目錄中。 - 從以下位置執行腳本電源外殼沒有參數的控制台。該程式碼
.ps1
在其建立的命令列中使用檔案的當前 Path\FileName 。
### OpenHere.ps1
If ($Args) { ### Launched from context menu
Set-Location -LiteralPath $Args[0]
} Else { ### Create HKCU registry entries
'Background\','' | ForEach {
$splat = @{
'Path' = ('HKCU:\Software\Classes\Directory\{0}Shell\PowerShell\Command' -f $_)
'Value' = ('powershell.exe -NoExit -File "{0}" "%V"' -f $PSCommandPath)
'Type' = 'ExpandString'
}
New-Item @splat -Force
}
}
### The "(Default)" value is created as a REG_EXPAND_SZ to allow for subsequent
### editing that can include environmental variables
答案2
前言
基斯·米勒的實用回答是一個務實的自動化解決方案 - 唯一需要注意的是它僅適用於使用者等級。
以下答案可能會引起您的興趣全部用戶解決方案和技術背景; Keith 的答案
OpenHere.ps1
同樣可以用於所有使用者的解決方案(自安裝部分除外)。
帽子尖到萊斯·費奇對於他的所有投入。
筆記:
- 這個修復需要管理權限(跑步有海拔)。
打開regedit.exe
和應用以下步驟兩個都以下註冊表項:HKEY_CLASSES_ROOT\Directory\shell\Powershell\command
和
HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command
:
準備:修改權限以便可以修改該值(PowerShell 指令):
手動修改權限的替代方案:
@LesFerch 提到以下第三方實用程式:備擇方案手動權限修改,允許您
regedit.exe
直接以NT SERVICE\TrustedInstaller
使用者身分執行:基斯·米勒的實用回答提到定義使用者級鍵作為替代方案 - 不需要提升,但將解決方案限制為目前用戶。
右鍵單擊
command
子項目並選擇Permissions...
點擊
Advanced
和:- 使該
Administrators
組成為擁有者關鍵的 - 讓
Administrators
團隊完全控制密鑰
- 使該
注意:我不知道這些修改有任何不利影響,但如果您知道任何不利影響,請告訴我們。
但是,為了安全起見,您可以在修改命令後恢復這些修改,如下所述,這需要將TrustedInstaller
安全主體還原為金鑰的擁有者command
;請注意,您必須將其指定為
NT SERVICE\TrustedInstaller
.
現在將
command
鍵的(Default)
值替換為以下內容(請參閱下面有關控制台設定/顏色的註釋):cmd /c set "_dir=%V%" & powershell.exe -NoExit -Command Set-Location -LiteralPath $env:_dir
筆記:
透過呼叫 via
cmd
,您將獲得後者的控制台設置,而不是 Windows PowerShell 的控制台設置,其中特別包括藍色背景。呼喚透過
cmd /c
是個最堅固的和安全的選項:如果的值包含字符,則它
%V
只能在語法上破壞命令,而根據定義,這是不可能的(文件和資料夾名稱不能包含)。set
"
"
但是,如果資料夾名稱包含看起來像
cmd.exe
環境變數引用的內容逐字(例如%OS%
)和引用的變數存在,引用被擴展,導致對該資料夾的變更失敗或 - 假設 - 將不同的資料夾作為目標。cd
該命令不能僅用作呼叫的一部分的原因cmd.exe
是,powershell.exe
從名稱恰好包含[
或]
(例如foo[0]
)的資料夾呼叫時會發生故障。此錯誤已在PowerShell(核心)7+CLI,pwsh.exe
因此您可以簡單地使用:# PowerShell 7+ cmd /c cd /d "%V" & pwsh.exe
其實
pwsh.exe
是新的-WorkingDirectory
參數使能直接的呼叫(這不僅更有效率,而且還避免了控制台設定問題):[1]pwsh.exe -WorkingDirectory "%V\."
打電話時
powershell.exe
直接是一個選項,它總是涉及權衡:如果您的資料夾名稱可能包含文字
'
字符,但從不包含文字`
或$
字符,則可以使用"..."
(可擴展的(插值)字串) 相反,但這帶有以下內容 警告:雖然該命令只是簡單地故障逐字資料夾名稱,例如
foo`bar
或$foo
(或 - 假設 - 目標不同的目錄),這可能會導致不需要的命令執行,透過精心惡意製作的包含$(...)
子表達式的資料夾名稱。powershell.exe -NoExit -Command "Set-Location -LiteralPath \"%V\""
應該可以編寫上述步驟的腳本。
[1]\.
是為了確保根諸如此類的路徑C:\
也得到了妥善處理;否則,PowerShell CLI 會(合理地)將 解釋"C:\"
為C:
跟著一個逃脫了 "
字符,即實際上是逐字 C:"
, 哪個休息。