PowerShell中運行CMD命令的技巧總結(jié)(解決名稱沖突和特殊字符等問題)
引言
我從老舊的 CMD.EXE 命令行換到優(yōu)秀的 POWSERSHELL.EXE 已經(jīng)有一段時間啦。您可能知道新的 Windows PowerShell 可以運行任何舊命令。不過有些舊命令的名稱或語法可能會產(chǎn)生問題。但這都不是事兒。
麻煩 1:名稱沖突
PowerShell 的 cmdlet 別名和舊命令的名稱有沖突是個常見的問題。比如說您喜歡的服務(wù)控制命令 SC.EXE。SC.EXE 非常靈活!我能理解您為什么喜歡它(不要為用 NET.EXE 管理服務(wù)找借口)。如果您想查看 SMB Server 服務(wù)的狀態(tài),可以在 CMD.EXE 里這樣用:
C:\>SC QUERY LANMANSERVER
SERVICE_NAME: LANMANSERVER
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
如果您在 PowerShell 中嘗試同樣的事,會得到:
PS C:\> SC QUERY LANMANSERVER
Set-Content : Access to the path 'C:\QUERY' is denied.
At line:1 char:1
+ SC QUERY LANMANSERVER
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\QUERY:String) [Set-Content], UnauthorizedAccessException
+ FullyQualifiedErrorId : GetContentWriterUnauthorizedAccessError,Microsoft.PowerShell.Commands.SetContentCommand
因為 SC 是 Set-Content 的別名。它優(yōu)先于 SC.EXE 文件。
方案 1A:使用 .EXE 擴展名
為了克服這個問題,您可以簡單地將 .EXE 擴展名包含進舊命令。這消除了歧義并使相同的命令在 CMD.EXE 和 PowerShell 里都能用。還可以清楚告訴使用您腳本的人這里用的是舊 .EXE 命令而非 PowerShell 別名。
SERVICE_NAME: LANMANSERVER
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
方案 1B:使用 CMD /C
另一個辦法是把您的命令用引號括起讓 CMD.EXE 來運行。但這樣做沒啥效率,僅僅為了執(zhí)行您的命令就得運行一個 CMD.EXE 實例。
SERVICE_NAME: LANMANSERVER
TYPE : 20 WIN32_SHARE_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
方案 1C:用等效的 PowerShell
很多情況下,可以用 PowerShell cmdlet 來代替您的舊命令。
例如這里您就可以直接使用 Get-Service:
PS C:\> Get-Service LANMANSERVER | FL
Name : LANMANSERVER
DisplayName : Server
Status : Running
DependentServices : {Browser}
ServicesDependedOn : {SamSS, Srv}
CanPauseAndContinue : True
CanShutdown : False
CanStop : True
ServiceType : Win32ShareProcess
麻煩 2:PowerShell 的特殊字符
有時舊命令的參數(shù)使用的字符在 PowerShell 里有特殊意義。
比如您想讓某個目錄被所有用戶完全控制。在 CMD.EXE 里您可以這樣做:
C:\>ICACLS.EXE C:\TEST /GRANT USERS:(F)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files
在 CMD.EXE 做這些沒問題,但如果你在 PowerShell 運行就會報錯:
PS C:\> ICACLS.EXE C:\TEST /GRANT USERS:(F)
The term 'F' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:34
+ ICACLS.EXE C:\TEST /GRANT USERS:(F)
+ ~
+ CategoryInfo : ObjectNotFound: (F:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundExceptionn
試圖給名字以 $ 結(jié)尾的電腦對象授權(quán)時也會引起一個類似的錯誤。
PS C:\> ICACLS.EXE C:\TEST /GRANT COMPUTERNAME$:(F)
At line:1 char:39
+ ICACLS.EXE C:\TEST /GRANT COMPUTERNAME$:(F)
+ ~~
Invalid variable reference. '$' was not followed by a valid variable name character. Consider using ${} to delimit the
name.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidVariableReference
這個問題是因為括號和美元符在 PowerShell 中都有特殊意義。例如大括號之類常用字符也會引發(fā)相似的沖突。也有幾種不同的方案來解決這個問題。
方案 2A:使用 CMD /C
和第一個問題一樣,你可以引號括起您的命令交給 CMD.EXE 來處理。先不考慮效率,PowerShell 不會去解析引號里的字符串,這樣就能正常工作。
PS C:\> CMD.EXE /C "ICACLS.EXE C:\TEST /GRANT USERS:(F)"
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files
方案 2B:使用 PowerShell 的轉(zhuǎn)義字符
對于這個方案,您必須先知道使用的字符哪些對 PowerShell 有特殊意義。然后在它們每一個前面加上個反引號(`),它就是 PowerShell 的轉(zhuǎn)義字符。這個方案的主要問題是你必須知道哪些字符需要轉(zhuǎn)義,這讓讀寫您的腳本更困難。
我們的例子里,你需要處理 ( 和 ) 這兩個字符:
PS C:\> ICACLS.EXE C:\TEST /GRANT USERS:`(F`)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files
方案 2C:使用 PowerShell v3 的新語法“–%”
在 PowerShell v3 中有另一種選擇來解決這個問題。您只需在命令行的任意位置添加 –% 序列(兩個短劃線和一個百分號)PowerShell 就不會再去解析剩下的部分。
我們的例子里,您可以這樣用:
PS C:\> ICACLS.EXE --% C:\TEST /GRANT USERS:(F)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files
也可以這樣用:
PS C:\> ICACLS.EXE C:\TEST --% /GRANT USERS:(F)
processed file: C:\TEST
Successfully processed 1 files; Failed processing 0 files
方案 2D:使用等效的 PowerShell
使用等效的 PowerShell 也是種選擇。ICACLS.EXE 可以用 Set-ACL 代替??梢詮倪@篇博客中找到更多的 Set-ACL 例子。
混搭
這里展示如何讓您安全地享受 PowerShell 結(jié)合您的舊命令帶來的靈活性。您可能會學(xué)到幾個技巧并以全新的方式開始新老結(jié)合。
例如您能用靈活的 Get-Service 通配符代替 SC.EXE 里晦澀選項:
或者您可以使用 PowerShell 的 Get-Item(別名 Dir)過濾文件子集傳遞給 ICACLS.EXE 來處理:
您甚至可以循環(huán)遍歷幾個數(shù)并結(jié)合好用的 FSUTIL.EXE 來創(chuàng)建一批大小不同的文件用于測試項目:
尾聲
事到如今,您可能已經(jīng)確信 Windows PowerShell 是管理員的好朋友啦。然而您可能因為有些舊命令帶著古怪的名字或參數(shù)而不能使用 POWERSHELL.EXE。我非常鼓勵您使用這些技巧來徹底停用 CMD.EXE 并永久遷移到 PowerShell 來作為您主要的 shell。
文章出處:http://www.pstips.net/using-windows-powershell-to-run-old-command-line-tools-and-their-weirdest-parameters.html
相關(guān)文章
Windows Powershell Where-Object 條件過濾
本篇會對條件判斷進行實際應(yīng)用。在管道中可以通過條件判斷過濾管道結(jié)果,Where-Object會對集合逐個過濾,將符合條件的結(jié)果保留。2014-10-10Powershell檢查網(wǎng)站響應(yīng)并計算執(zhí)行時間例子
這篇文章主要介紹了Powershell檢查網(wǎng)站響應(yīng)并計算執(zhí)行時間例子,本文直接給出實現(xiàn)代碼,需要的朋友可以參考下2015-03-03PowerShell 獲取系統(tǒng)信息的函數(shù)
如果你要得到本地或遠程的使用配置信息,又不想浪費太多的解決時間。可以在Powershell中使用systeminfo.exe提取數(shù)據(jù)2014-03-03PowerShell獲取系統(tǒng)環(huán)境變量的方法
這篇文章主要介紹了PowerShell獲取系統(tǒng)環(huán)境變量的方法,本文講解了列出所有的環(huán)境變量的方法和獲取環(huán)境變量的值的方法,需要的朋友可以參考下2014-08-08PowerShell入門教程之高效使用PowerShell交互式運行環(huán)境的幾個小技巧
這篇文章主要介紹了PowerShell入門教程之高效使用PowerShell交互式運行環(huán)境的幾個小技巧,本文也可以說是使用PowerShell的一些好習(xí)慣,需要的朋友可以參考下2014-10-10PowerShell腳本實現(xiàn)創(chuàng)建桌面快捷方式的方法
這篇文章主要介紹了PowerShell腳本實現(xiàn)創(chuàng)建桌面快捷方式的方法,本文通過調(diào)用WScript腳本組件實現(xiàn),需要的朋友可以參考下2014-08-08Powershell Profiles配置文件的存放位置介紹
這篇文章主要介紹了Powershell Profiles配置文件的存放位置介紹,Profiles文件存放的位置不同,它的作用域也會不同,需要的朋友可以參考下2014-08-08