來源:
https://blog.csdn.net/u011054333/article/details/72567590
https://blog.csdn.net/u011054333/article/details/72568190
https://blog.csdn.net/u011054333/article/details/72798046
一說起 Shell 編程,我們大家想到的應該都是Linux 下的 Shell 編程。其實 Windows 下也可以使用功能強大的 Shell 來編寫程序,這就是今天我要介紹的 Powershell。從名字就可以看出來,Powershell的功能很強大,所以才敢叫Powershell。
如果需要看官方文檔的話,點擊這里。雖然有一些機翻的意味,但是完全可以看。
需要說明一點,Powershell是構建在.NET平臺上的,所有命令傳遞的都是.NET對象。所以為了更好地使用Powershell,最好有一點.NET編程基礎,這樣學習Powershell就會感覺非常輕松和愉快。
安裝Powershell
這里我介紹的是 Powershell 5.0 ,它在 Windows Server 2016 和Windows 10 操作系統(tǒng)中是默認安裝的。如果使用的是比較舊的操作系統(tǒng)例如 Windows 7 或者 Windows 8.1 ,就需要手動安裝 Powershell 5.0 。下載也很簡單,到這里下載 WMF 5.0,它包含了 Powershell 5.0 和一系列工具。
如果要查看當前Powershell版本的話,也很簡單。在Powershell窗口中使用下面的命令即可查看相關信息。
C:\Users\asddf> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.15063.296
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.15063.296
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
啟動Powershell
啟動 Powershell 很簡單,從運行對話框或者開始菜單中搜索powershell 即可。這樣就可以打開 Powershell 命令行窗口了。默認情況下這是一個藍色的窗口。
在64位操作系統(tǒng)下,有兩個版本的 Powershell 。默認情況下,我們使用64位版本就可以了。如果有特殊需求的話,可以選擇啟動帶x86 字樣的32位版本的 Powershell 。
啟動Powershell ISE
在終端中敲命令是一件很麻煩的事情,有沒有什么集成環(huán)境可以讓我們進行交互式學習呢?當然是有的,Windows 附帶了一個交互式環(huán)境,叫做Powershell ISE,可以幫助我們更方便的學習和使用 Powershell。
啟動 Powershell ISE也很簡單,在Windows 10下,直接在開始菜單中輸入 ISE ,就可以打開Powershell ISE了。
命令介紹
首先說明一下,和 Linux Shell 不同,Powershell 的命令基本上都是動詞-名詞 形式的。這樣做的好處是命令作用很容易就可以看出,缺點就是輸入稍微有些麻煩,習慣了Linux 的簡潔的同學可能會不太適應。
Powershell 和Linux Shell 還有一個不同點在于Powershell 是基于 .NET平臺的,它的命令叫做cmdlet 。cmdlet 功能比普通的Linux 命令更強,因為cmdlet 接受的參數(shù)不是字符串,而是 .NET 對象,這使得Powershell 的功能更加強大和靈活。
獲取命令
如果想要獲取當前會話中所有可用的內置命令,可以使用命令Get-Command ,它的別名是gcm 。
PS C:\Users\asddf> Get-Command
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Command 3.0.0.0 Microsoft.PowerShell.Core
.....
如果希望列出指定名稱的命令,可以使用Name 參數(shù)。
PS C:\Users\asddf> Get-Command -Name Get-Command
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Command 3.0.0.0 Microsoft.PowerShell.Core
獲取別名
有些命令比較常用,除了動詞-名詞 版本外,Powershell還提供了和Linux 一樣的別名來簡化輸入。我們可以使用-CommandType Alias 參數(shù)來顯示所有的命令別名。下面列舉了一部分輸出,可以看到,微軟為了照顧Linux用戶,很多命令都縮寫為Linux 命令的形式。
PS C:\Users\asddf> Get-Command -CommandType Alias
CommandType Name Version Source
----------- ---- ------- ------
Alias % -> ForEach-Object
Alias ? -> Where-Object
Alias ac -> Add-Content
Alias blsmba -> 2.0.0.0 SmbShare
Alias cat -> Get-Content
Alias cd -> Set-Location
Alias chdir -> Set-Location
Alias clc -> Clear-Content
Alias clear -> Clear-Host
Alias clhy -> Clear-History
Alias cli -> Clear-Item
Alias clp -> Clear-ItemProperty
Alias cls -> Clear-Host
當然,如果你觀察仔細的話,會發(fā)現(xiàn)命令類型這一欄有Alias 、cmdlet 以及function 三種類型。所以我在前面使用了“內置命令”這個詞。函數(shù)基本上就是最簡單的命令,例如清屏(Clear-Host ),不能接受參數(shù),功能比較基本。cmdlet 則是功能強大的命令,可以接受各類參數(shù),還能復合使用。Alias 則是前兩者的別名,作用是簡化輸入。
獲取動詞/名詞
當然,如果想查找特定動詞/名詞的命令也是可以的。比方說,如果我想查找所有以Get 開頭的命令,可以使用下面的命令。
PS C:\Users\asddf> Get-Command -Verb Get
相應的,如果我想獲取所有名詞是Help 的命令,可以使用下面的命令。
PS C:\Users\asddf> Get-Command -Noun Help
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Help 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Save-Help 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Update-Help 3.0.0.0 Microsoft.PowerShell.Core
上面的命令都只列出了內置命令。如果需要包含包括普通程序在內的所有命令,可以使用通配符。
PS C:\Users\asddf> Get-Command *
獲取幫助
如果要獲取一個命令的幫助,可以使用Get-Help 。如果使用上面介紹的列出別名的命令的話,會發(fā)現(xiàn)這個命令的別名是man ,恰好就是Linux 系統(tǒng)下的獲取幫助的命令。當然它們的功能也很相似。
比方說,我們要查看一下清除屏幕這個命令的幫助,就可以簡單的輸入下面的命令。Powershell 會自動將別名解析為實際命令名稱。所以我們可以看到,cls 實際上是Clear-Host 命令的別名。
PS C:\Users\asddf> man cls
名稱
Clear-Host
摘要
語法
Clear-Host [<CommonParameters>]
說明
相關鏈接
https://go.microsoft.com/fwlink/?LinkID=225747
備注
若要查看示例,請鍵入: "get-help Clear-Host -examples".
有關詳細信息,請鍵入: "get-help Clear-Host -detailed".
若要獲取技術信息,請鍵入: "get-help Clear-Host -full".
有關在線幫助,請鍵入: "get-help Clear-Host -online"
其實從這個命令的幫助信息來看,我們就可以獲得大部分信息。比方說,如果我們要查看這個命令的在線幫助,就可以如同上面的備注所說,在命令上添加-online 參數(shù),這樣就會打開瀏覽器跳轉到這個命令的在線幫助頁上。
值得一提的還有幫助參數(shù)-? 、如果一個命令添加了幫助參數(shù),那么Powershell 不會實際執(zhí)行這個命令,而是顯示它的幫助信息。
服務管理
原來,如果我們使用批處理來管理Windows服務的話,一般情況下用的是sc 這個命令。這個命令的作用有很多,其中一項就是啟動和停止Windows服務。不過在Powershell下有更好用的服務管理命令,功能也更加強大。
首先我們先查看一下有什么管理服務的命令,只需要查詢一下名詞是service 的命令即可。可以看到這些命令涵蓋了從創(chuàng)建服務到管理服務的各個方面,功能很豐富。
PS C:\Users\asddf> Get-Command -Noun service
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Restart-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Resume-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Set-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Start-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Suspend-Service 3.1.0.0 Microsoft.PowerShell.Management
比方說,我們要查詢一下當前計算機安裝了哪些和MySQL相關的服務,就可以用下面的命令。
PS C:\Users\asddf> Get-Service mysql*
Status Name DisplayName
------ ---- -----------
Running MySQL57 MySQL57
然后如果需要停止服務也很簡單,需要注意停止服務的話需要管理員權限,因此Powershell需要在管理員模式下運行。
PS C:\WINDOWS\system32> Stop-Service MySQL57
警告: 正在等待服務“MySQL57 (MySQL57)”停止...
其他命令就不介紹了,配合幫助命令可以很快學習如何使用。
應用實例
最后直接從網上找了個例子來看看Powershell的實際作用。我們可以從中了解到Powershell的強大特性,用它幫助我們方便地管理Windows操作系統(tǒng)。
Office互操作
這里貼一個網絡上的例子,我是從知乎上看到的。運行一下會直接打開Excel并填充數(shù)據(jù),然后畫出占用內存前十的程序的餅狀圖,一氣呵成。我第一次運行的時候簡直驚呆了。
# create new excel instance
$objExcel = New-Object -comobject Excel.Application
$objExcel.Visible = $True
$objWorkbook = $objExcel.Workbooks.Add()
$objWorksheet = $objWorkbook.Worksheets.Item(1)
# write information to the excel file
$i = 0
$first10 = (ps | sort ws -Descending | select -first 10)
$first10 | foreach -Process {$i++; $objWorksheet.Cells.Item($i,1) = $_.name; $objWorksheet.Cells.Item($i,2) = $_.ws}
$otherMem = (ps | measure ws -s).Sum - ($first10 | measure ws -s).Sum
$objWorksheet.Cells.Item(11,1) = "Others"; $objWorksheet.Cells.Item(11,2) = $otherMem
# draw the pie chart
$objCharts = $objWorksheet.ChartObjects()
$objChart = $objCharts.Add(0, 0, 500, 300)
$objChart.Chart.SetSourceData($objWorksheet.range("A1:B11"), 2)
$objChart.Chart.ChartType = 70
$objChart.Chart.ApplyDataLabels(5)
當然其實Powershell能做的事情非常多。微軟自從Powershell出現(xiàn)之后就一直推動Windows和Powershell的互操作。到現(xiàn)在為止大概大部分Windows管理和配置功能都可以使用Powershell來進行。
一開始我也對Powershell不太了解。不過了解了一點之后,我感覺Powershell的功能確實對得起它的名字。我已經決定學習完Powershell之后,將來在所有可以使用Powershell的地方全部使用它,享受命令行管理系統(tǒng)的快感。
這一部分著重于介紹Powershell的程序知識,讓我們能夠編寫功能強大的Powershell腳本,執(zhí)行比較復雜的任務。
變量
變量使用$變量名 創(chuàng)建和引用。舉個例子,Get-Location 命令用于獲取當前工作目錄位置,它的別名是pwd 。那么我們可以使用下面的命令來創(chuàng)建一個變量,存儲當前目錄位置。
C:\Users\asddf> $current=pwd
然后我們訪問$current ,就可以獲取實際值了。
C:\Users\asddf> $current
Path
----
C:\Users\asddf
如果知道這個命令返回的實際是.NET對象的話,我們還可以更進一步,比方說直接訪問這個對象的Path 屬性,獲取值。
C:\Users\asddf> $current.Path
C:\Users\asddf
還有一個命令Get-Member ,別名是gm ,用于獲取對象的屬性。比方說,我們將Get-Location 命令的結果通過管道傳遞給Get-Member 命令,就會顯示下面的輸出。如果不了解.NET的話,可能感覺比較陌生。但是如果你懂得.NET和C#的話,就會像我一樣大喊一聲:“臥槽,還能這樣玩?!”
C:\Users\asddf> Get-Location|Get-Member
TypeName:System.Management.Automation.PathInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Drive Property System.Management.Automation.PSDriveInfo Drive {get;}
Path Property string Path {get;}
Provider Property System.Management.Automation.ProviderInfo Provider {get;}
ProviderPath Property string ProviderPath {get;}
如果我們要獲取對象的所有屬性,使用MemberType 參數(shù)。
C:\Users\asddf> pwd|gm -MemberType Property
我們還可以在變量上調用方法, 比如說將路徑轉換為全小寫。
C:\Users\asddf> $current.Path.ToLower()
c:\users\asddf
最后,如果不再需要一個變量,可以使用Remove-Variable 刪除變量,它的別名是rv 。
C:\Users\asddf> Remove-Variable current
操作符
來看看Powershell中支持的操作符。
數(shù)學運算符
首先,基本的數(shù)學運算符都是支持的。
PS D:\Desktop> $i=5
PS D:\Desktop> $sum=3+4*($i-3)/2
PS D:\Desktop> $sum
7
前置后置自增自減運算符也是支持的。
PS D:\Desktop> $i=0
PS D:\Desktop> $i--
PS D:\Desktop> $i++
PS D:\Desktop> ++$i
PS D:\Desktop> --$i
比較運算符
然后是比較運算符,這些和Linux Shell中很相似,有大于(-gt ),大于等于(-ge ),小于(-lt ),小于等于(-le ),等于(-eq ),不等于(-ne )幾個。
字符串匹配運算符
-like 和-notlike 用于?* 這樣的通配符。
PS D:\Desktop> 'hello' -like '?ello'
True
PS D:\Desktop> 'hello' -notlike '?ello'
False
PS D:\Desktop> 'hello' -like '*o'
True
-match 和-notmatch 用于正則表達式。
PS D:\Desktop> 'aabcc' -match 'a*b?c+'
True
PS D:\Desktop> 'aab' -match 'a*b?c+'
False
包含和替換運算符
-contains 查找序列中是否包含某個元素。
PS D:\Desktop> 'hello','zhang3' -contains 'zhang3'
True
-replace 用于替換字符串中某個部分,當然正則表達式也是支持的。
PS D:\Desktop> 'hello zhang3' -replace 'zhang3','yitian'
hello yitian
分隔和連接運算符
-split 和-join 用于將一個字符串分為幾個子部分,或者將幾個子部分組合為一個字符串。
PS D:\Desktop> 'A B C DE' -split ' '
A
B
C
DE
PS D:\Desktop> 'A','B','C' -join ','
A,B,C
上面這些運算符都是大小寫不敏感的,如果需要大小寫敏感的功能,可以在運算符前面添加c 前綴。
PS D:\Desktop> 'yitian' -match 'Yitian'
True
PS D:\Desktop> 'yitian' -cmatch 'Yitian'
False
邏輯運算符
邏輯運算符有與(-and )、或(-or )、非(-not 或! )以及異或(xor )幾個,并且支持短路計算。
如果需要使用真值和假值字面量,可以使用$true 和$false 。
類型運算符
Powershell 和.NET平臺綁定,所以它是一門強類型的腳本。因此我們可以在腳本中判斷數(shù)據(jù)的類型,只要使用-is 或-isnot 運算符即可,類型需要寫到方括號中。這里的類型可以是所有合適的.NET類型。
PS D:\Desktop> 3.14 -is [Double]
True
PS D:\Desktop> 3.14 -isnot [Float]
True
重定向運算符
這個稍微比較麻煩一點。
首先是> 和>> 運算符,用于將標準輸出流重定向到文件,前者會覆蓋已有文件,后者則是追加到已有文件末尾。
然后我們來說說日志級別,如果有使用過某些語言的日志框架的話,就很好理解了。在這里,2代表錯誤、3代表警告、4代表信息、5代表調試信息。n> 和n>> 運算符就是用于將對應級別的輸出重定向到文件的,這兩者的區(qū)別和前面相同。n>&1 將對應級別的輸出和標準輸出一起重定向到文件。
最后就是*> 和*>> 了,這兩者將所有輸出信息重定向到文件。
需要注意,Powershell使用Unicode編碼來輸出信息。如果你需要使用其他類型的編碼,就不能使用重定向運算符了,而應該使用Out-File 命令。
特殊運算符
& 運算符將它后面的命令設置為后臺運行,當運行的命令需要阻塞當前終端的時候很有用。
.\\ 運算符用于執(zhí)行一個腳本或命令。如果執(zhí)行的是Powershell腳本,那么腳本會在自己的作用域中執(zhí)行,也就是說在當前環(huán)境下無法訪問被執(zhí)行的腳本中的變量。
[] 運算符用于轉換變量的類型,比如說下面的代碼,就將pi 變量轉換為了Float 類型。
[Float]$pi = 3.14
$pi -is [Float]
. 運算符用于調用.NET對象的成員,它也可以用于執(zhí)行腳本。當它用于執(zhí)行腳本的時候,腳本會在當前作用域中執(zhí)行。所以腳本結束之后,我們可以訪問腳本中的元素。
:: 運算符用于調用類中的靜態(tài)成員,例如下面就會調用.NET平臺中DateTime 類的Now 屬性。
PS D:\Desktop> [DateTime]::Now
2017年5月18日 22:45:42
.. 運算符用于創(chuàng)建一個范圍閉區(qū)間,例如下面這樣。
PS D:\Desktop> 1..3
1
2
3
PS D:\Desktop> 3..1
3
2
1
-f 運算符用于格式化數(shù)據(jù),例如下面這樣。格式化方法和C#中的完全相同,所以如果不熟悉的話直接看在C#中如何格式化數(shù)據(jù)就行了。
PS D:\Desktop> 'My name is {0}, I am {1} years old' -f 'yitian',24
My name is yitian, I am 24 years old
$ 運算符可以將字符串內部的變量轉換為實際的值,例如下面這樣。需要注意使用內插操作符的時候,外部字符串需要使用雙引號,否則Powershell會直接輸出字符串內容。
PS D:\Desktop> $name='yitian'
PS D:\Desktop> $age=24
PS D:\Desktop> "My name is $name, I am $age years old."
My name is yitian, I am 24 years old.
@() 運算符用于將一系列值轉換為一個數(shù)組。假如在腳本中有一個函數(shù)可能返回0、1或多個值,就可以使用這個操作符,將一系列值合并為一個數(shù)組,方便后續(xù)處理。
, 逗號運算符如果放置在單個值前面,就會創(chuàng)建一個包含這個值的單元素數(shù)組。
條件判斷
if判斷
Powershell中的條件判斷和一般的編程語言以及Shell編程都很類似,直接看代碼就能理解。
$condition = $true
if ($condition -eq $true) {
Write-Output "condition is $true"
}
elseif ($condition -ne $true ) {
Write-Output "condition is $false"
}
else {
Write-Output "other ocndition"
}
switch判斷
如果需要多重判斷,可以考慮使用switch語句。一個典型的switch如下所示。
$n = 4
switch ($n) {
1 {"n is 1"}
2 {"n is 2"}
3 {"n is 3"}
default {"n is others"}
}
其實細說起來,這個switch的坑還是不少的。例如,switch語句可以接受多個值來測試,在switch語句中還可以編寫多個case相同的語句。這里我就不細說了,想具體了解的話直接看官方文檔 about_Switch吧。
循環(huán)語句
提醒一下,不管是哪種循環(huán)語句,在循環(huán)體內都可以使用break 或continue 中斷/繼續(xù)循環(huán)。
do循環(huán)
首先來看看do-while循環(huán),先執(zhí)行循環(huán)體,然后判斷是否滿足條件,如果滿足條件則繼續(xù)執(zhí)行。
$i = 0
do {
$i++
Write-Output $i
}while ($i -ne 3)
然后是do-until循環(huán),和do-while類似,不過當條件不滿足的時候才會繼續(xù)循環(huán),如果滿足條件則退出循環(huán)。
$i = 0
do {
$i++
Write-Output $i
}until ($i -eq 3)
while循環(huán)
while循環(huán)是先判斷循環(huán)條件,滿足條件時執(zhí)行循環(huán)。
$i = 0
while ($i -lt 3) {
Write-Output $i
$i++
}
for循環(huán)
for循環(huán)可以看做是while循環(huán)的另一種形式,常用于固定次數(shù)的循環(huán)。
for ($i = 0; $i -ne 3; $i++) {
Write-Output $i
}
for-each循環(huán)
for-each循環(huán)用于遍歷一個集合中的所有元素。
$array = @(1, 2, 3, 4)
foreach ($i in $array) {
Write-Output $i
}
值得一提的是,for-each語句用在管道上時,還有以下一種用法。
<command> | foreach {<beginning command_block>}{<middle command_block>}{<ending command_block>}
使用這種方法時,for-each后面可以跟三個語句塊,第一個語句塊是開始語句塊,在循環(huán)前執(zhí)行一次,常用來初始化一些數(shù)據(jù);第三個是結束語句塊,在循環(huán)結束之后執(zhí)行一次,常用于統(tǒng)計一些循環(huán)數(shù)據(jù);第二個就是正常的循環(huán)語句塊,會循環(huán)多次。
函數(shù)
定義函數(shù)
定義函數(shù)使用function 關鍵字。
function hello {
Write-Output 'Hello Powershell'
}
定義好函數(shù)之后,就可以使用函數(shù)名來調用函數(shù)了。
hello
函數(shù)的參數(shù)
函數(shù)當然也可以帶參數(shù)了,參數(shù)列表有兩種寫法:第一種是C風格的,參數(shù)列表寫在函數(shù)名后面,使用小括號分隔開;第二種方式是在方法體中,使用param 關鍵字聲明參數(shù)。這兩種方法是完全等價的,當然我習慣上還是喜歡使用第一種方式。
Powershell是一種強類型的腳本語言,所以可以在參數(shù)列表上添加參數(shù)類型,參數(shù)類型是可選的,不過我還是推薦寫的時候帶上類型,方便閱讀和類型檢查。
function Say-Hello ([string] $name) {
Write-Output "Hello, $name"
}
function Say-Hello2 {
param([string] $name)
Write-Output "Hello, $name"
}
調用帶參數(shù)的函數(shù)時,需要向調用命令那樣,使用-參數(shù)名 來傳遞參數(shù),例如下面這樣。
Say-Hello -name 'yitian'
默認參數(shù)
Powershell支持默認參數(shù),直接用賦值號= 在參數(shù)列表上指定參數(shù)默認值即可。
function Say-Hello3 {
param([string] $name = 'zhang3')
Write-Output "Hello, $name"
}
位置參數(shù)
Powershell也支持位置參數(shù),它會把所有參數(shù)包裝到$args 數(shù)組中,所以我們可以通過這個變量訪問所有位置的參數(shù)。例如下面,將所有參數(shù)合并一個字符串,然后打印出來。
function Say-Hellos {
$names = $args -join ','
Write-Output "Hello, $names"
}
這個函數(shù)調用時候需要指定多個參數(shù),注意不要在多個參數(shù)之間添加括號,否則會變成一個數(shù)組參數(shù),而不是多個參數(shù)。
Say-Hellos 'yitian' 'zhang3' 'li4'
開關參數(shù)
開關參數(shù)沒有類型,作用僅僅是標志是或者否。如果在使用函數(shù)的時候帶上開關參數(shù),那么它就是開的狀態(tài),否則就是關的狀態(tài)。開關參數(shù)需要指定參數(shù)類型為switch 。
function Answer-Hello ([switch] $yes) {
if ($yes) {
Write-Output "Hi"
}
}
然后在調用時就可以看出區(qū)別了。
Answer-Hello -yes
Answer-Hello
函數(shù)返回值
最后來說說函數(shù)返回值。這個其實也很簡單,只要使用return 語句就可以了。
function Add ([double]$a, [double]$b) {
$c = $a + $b
return $c
}
然后我們調用函數(shù),就可以看到結果了。
Add -a 3 -b 5
關于Powershell編程的知識就介紹到這里,其實如果看看官方文檔的話,就知道這里介紹的也僅僅是一部分而已。不過這一部分對于我們日常使用和學習基本上也夠用了。
如果要查看詳細幫助的話,可以運行一下下面的命令,這樣會顯示所有和Powershell相關的幫助文檔。
Get-Help about*
然后,就可以閱讀自己感興趣的部分了。比方說,如果我們想了解用Powershell編寫類,就可以使用下面的命令。如果想在瀏覽器中瀏覽器在線版本,加上-online 參數(shù)即可。
Get-Help about_Classes
參考資料
https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_operators?f=255&MSPPError=-2147217396
http:///powershell/windows-powershell-operators
好像關于Powershell說的已經差不多了,所以最后一篇文章就來使用Powershell寫一些腳本,幫助我們完成一些日常工作。
文件管理
常用命令
先來看看常用的文件管理命令。
Set-Location 命令用于切換工作目錄,它的別名是cd 。
Get-Location 命令用于獲取當前工作目錄,它的別名是pwd 。
Get-ChildItem 命令用于獲取當前目錄下的所有文件。
Get-Item 命令用于獲取給定文件的信息。
還有文件移動、刪除、復制、粘貼、重命名等命令,輸入Get-Command -Noun item 就可以看到這些命令,這里就不做介紹了。
獲取文件信息
獲取文件信息可以利用命令Get-Item 。下面獲取了我電腦上的cmder.exe 可執(zhí)行文件的信息。
λ Get-Item .\Cmder.exe
目錄: D:\devtools\cmder_mini
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2016/12/2 7:15 130560 Cmder.exe
默認只列出這么三個屬性,當然其實文件屬性遠不止這些。我們可以通過管道,將文件信息對象傳遞給命令Select-Object ,讓它幫我們顯示所有屬性。這里只粘貼了一點點內容,其實文件信息很長,大家可以自行嘗試。
λ Get-Item .\Cmder.exe|Select-Object *
PSPath : Microsoft.PowerShell.Core\FileSystem::D:\devtools\cmder_mini\Cmder.exe
PSParentPath : Microsoft.PowerShell.Core\FileSystem::D:\devtools\cmder_mini
過濾文件
用Get-ChildItem 顯示當前當前文件的時候,會顯示所有文件。有時候我們可能僅僅需要搜索或者過濾部分文件。
首先,如果是比較簡單的需求,可以使用?* 通配符來搞定,問號用于匹配任意單個字符,星號用于匹配任意多個字符。比方說,我想要列出所有.md 格式的文件,就可以使用下面的命令。
PS D:\devtools\cmder_mini> Get-ChildItem *.md
目錄: D:\devtools\cmder_mini
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2016/12/2 7:14 73491 CHANGELOG.md
-a---- 2016/12/2 7:14 1784 CONTRIBUTING.md
-a---- 2016/12/2 7:14 10039 README.md
有時候可能需要使用正則表達式來查找文件,不過好像Get-ChildItem 沒有正則表達式查詢的命令行,不過我們可以使用Where-Object 命令來自定義查詢。如果了解C#語言的LINQ的話,應該可以猜到,這個命令對應于LINQ的where 語句。
下面同樣是查找所有.md 格式的文件,不過這次使用了Where-Object 和正則表達式,其中Where-Object 里面的$_ 是形式變量,代表每次迭代的文件。如果了解過C#的LINQ,或者Java 8的流類庫,應該對這種形式會比較熟悉。
Get-ChildItem|Where-Object {$_ -match '\w*.md$'}
如果僅僅為了搜索文件名的話,這種方式好像一點優(yōu)勢都沒有。實際上Where-Object 的功能非常強大。比方說,我現(xiàn)在想查找大于5kb 的所有.md 格式文件,那么就可以這么寫。這里又用到了Powershell的一個方便的特性,文件大小單位,KB GB MB TB 等單位都支持。當然其實并不僅僅可以查詢文件大小屬性,基本上所有文件信息都可以用來查詢。
Get-ChildItem|Where-Object {$_ -match '\w*.md$' -and $_.Length/1kb -gt 5}
最后,Get-ChildItem 不僅可以列出當前文件夾下的所有內容,還可以遞歸查詢所有子文件夾。比方說,我要查找一下迅雷文件夾下所有可執(zhí)行文件,就可以使用下面的命令。如果添加-Depth 參數(shù)的話,還可以指定遞歸深度。
Get-ChildItem -Recurse *.exe
修改hosts
訪問谷歌的一種方式就是更改hosts文件。這里就用Powershell做一個修改hosts的功能。
首先先來介紹一個命令Invoke-WebRequest ,利用它我們可以獲取網頁內容、下載文件甚至是填寫表單。這個命令的別名是iwr 、curl 和wget 。我們就使用它來下載網上的hosts文件。
剩余就沒有什么難度了,無非就是讀寫文件、追加文件、復制和粘貼這種基本操作。最后寫完這個功能發(fā)現(xiàn)有一百多行,就不往這里復制粘貼了。如果有興趣的話,可以直接看我的Github上面的腳本。
進程管理
查看進程
首先我們看看有多少和進程相關的命令,這個很簡單,只要查看一下名詞是Process 的命令即可。
PS C:\WINDOWS\system32> Get-Command -Noun process
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Debug-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Start-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Wait-Process 3.1.0.0 Microsoft.PowerShell.Management
使用這些命令,我們就可以非常方便的管理進程了。比方說,我想查詢現(xiàn)在運行的所有進程,就可以使用下面的命令,這樣就會列出所有運行的進程,就像任務管理器里顯示的那樣。
PS C:\WINDOWS\system32> Get-ProcessGet-Process
上面這個命令會顯示所有進程。如果需要,我們可以按照某個屬性對進程進行排序顯示,這需要使用另外一個命令Sort-Object 。另外,如果只需要顯示前幾個進程,可以使用命令Select-Object 來選擇顯示多少數(shù)據(jù)。比方說,如果我們要查看當前占用CPU前5的chrome進程,就可以使用下面的命令。
Get-Process chrome|Sort-Object cpu -Descending|Select-Object -First 5
利用這幾個命令,我們可以按照任何想要的方式來查詢進程。
管理進程
先來看看MSDN上的一個官方例子。首先先打開三個記事本進程,然后使用名稱獲取這些進程,然后調用進程的Kill() 函數(shù)即可把這些進程全殺掉。中間調用了Count 屬性測試了一下總共獲取到了幾個進程。
PS C:\WINDOWS\system32> notepad;notepad;notepad;
PS C:\WINDOWS\system32> $notepads=Get-Process -Name notepad
PS C:\WINDOWS\system32> $notepads.Count
3
PS C:\WINDOWS\system32> $notepads.Kill()
再學習Powershell編程的時候,我們常常會同時開幾個Powershell窗口。不再使用的時候一個一個關閉它們也是一件麻煩事情,所以官方文檔還為我們介紹了如何關閉除當前窗口外的所有Powershell進程。
每個Powershell進程都有一個變量$PID ,用于標志當前進程的進程號,利用這一點我們就可以實現(xiàn)這個功能。這里的-WhatIf 參數(shù)表示不真正關閉進程,僅列出將要關閉的進程。
PS C:\WINDOWS\system32> Get-Process powershell |Where-Object {$_.Id -ne $PID}|Stop-Process -WhatIf
WhatIf: 正在目標“powershell (2676)”上執(zhí)行操作“Stop-Process”。
如果既想要關閉進程,還想知道關閉了哪些進程,可以使用-PassThru 參數(shù)。
PS C:\WINDOWS\system32> Get-Process powershell |Where-Object {$_.Id -ne $PID}|Stop-Process -PassThru
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
573 30 56884 68992 0.92 2676 1 powershell
輪詢關閉進程
如果在死循環(huán)中不斷查找任務管理器進程,發(fā)現(xiàn)它在運行就把它關閉,就可以做一個小小的“病毒”。代碼很簡單,基本上一下子就能看懂。一開始我沒有加Sleep,然后CPU使用率飚的非常高,加了之后基本上對電腦性能沒有影響了。
$process_name = "taskmgr"
while ($true) {
$processes = Get-Process
if ($processes.Name -contains $process_name) {
Get-Process $process_name|Stop-Process
}
else {
Start-Sleep -Milliseconds 500
}
}
如果把上面代碼中的taskmgr 換成英雄聯(lián)盟的進程名字,我們就可以做一個簡單的“熊孩子防火墻”,防止熊孩子用電腦來玩游戲了。
注冊表操作
讀寫注冊表
讀取注冊表
首先來介紹一下注冊表根的簡寫,例如HKEY_CURRENT_USER 的簡寫就是HKCU ,HKEY_LOCAL_MACHINE 的簡寫就是HKLM 。知道了簡寫,我們就可以將Powershell的工作目錄切換到注冊表內。例如,如果我們想查看HKEY_CURRENT_USER\Control Panel\Desktop\MuiCached 下的值,就可以先把工作目錄切換到這個位置內部。這里需要將對應的注冊表根修改為對應的簡寫加冒號的形式。
PS C:\WINDOWS\system32> Set-Location 'HKCU:\Control Panel\Desktop\MuiCached'
PS HKCU:\Control Panel\Desktop\MuiCached>
切換到了注冊表內部,我們就可以利用Get-Item 命令獲取注冊表的值了。比如說,要獲取這個注冊表鍵的值,就可以直接輸入Get-Item . 了。注意這個點不能省去,它代表當前工作目錄。
PS HKCU:\Control Panel\Desktop\MuiCached> Get-Item .
Hive: HKEY_CURRENT_USER\Control Panel\Desktop
Name Property
---- --------
MuiCached MachinePreferredUILanguages : {zh-CN}
如果要獲取當前注冊表項的屬性值,可以利用Get-ItemProperty 命令。
PS HKCU:\Control Panel\Desktop\MuiCached> Get-ItemProperty . MachinePreferredUILanguages
MachinePreferredUILanguages : {zh-CN}
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Control Panel\Desktop\MuiCached
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Control Panel\Desktop
PSChildName : MuiCached
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry
當然,切換工作目錄這件事情也可以不做。直接利用Get-ItemProperty 命令通過路徑參數(shù)來獲取屬性。
Get-ItemProperty -Path 'HKCU:\Control Panel\Desktop\MuiCached' -Name MachinePreferredUILanguages
編輯注冊表項
下面這個路徑是一個安全的注冊表路徑,在這里修改注冊表不會造成嚴重的系統(tǒng)問題。所以我們把它保存為一個變量。
$path = "HKCU:\Control Panel\Desktop"
如果要新建注冊表項,可以使用New-Item 命令。我們可以使用注冊表編輯器regedit 來驗證項是否創(chuàng)建成功。
New-Item –Path $path –Name HelloKey
如果要修改項的屬性,使用Set-ItemProperty 命令。
Set-ItemProperty -path $path\hellokey -name Fake -Value fuck
最后,如果要刪除項的屬性,使用Remove-ItemProperty 命令。
Remove-ItemProperty -path $path\hellokey -name Fake
如果要刪除整個注冊表項,使用Remove-Item 命令。
Remove-Item -path $path\hellokey -Recurse
獲取當前.NET版本
下面的參考資料中列出了一個MSDN上的文檔,告訴我們如何讀取注冊表的值來判斷當前安裝了.NET Framework的版本,并給出了相應的C#代碼。下面的代碼做的就是將C#代碼改寫成Powershell腳本。
# 判斷系統(tǒng)當前安裝.NET框架版本的腳本
$path = 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'
$not_found_msg = ".net framework 4.5 or later not installed on your system"
function CheckFor45PlusVersion([int] $releaseKey) {
if ($releaseKey -ge 460798) {
return "4.7 or later";
}
if ($releaseKey -ge 394802) {
return "4.6.2";
}
if ($releaseKey -ge 394254) {
return "4.6.1";
}
if ($releaseKey -ge 393295) {
return "4.6";
}
if (($releaseKey -ge 379893)) {
return "4.5.2";
}
if (($releaseKey -ge 378675)) {
return "4.5.1";
}
if (($releaseKey -ge 378389)) {
return "4.5";
}
return $not_found_msg;
}
try {
$key = get-item $path
$releaseKey = Get-ItemPropertyValue $path 'release'
if ($releaseKey -is [int]) {
$releaseKey = [int]$releaseKey
$version = CheckFor45PlusVersion($releaseKey)
Write-Host ".NET framework ${version}"
}
else {
Write-Host $not_found_msg
}
}catch {
Write-Host $not_found_msg
}
Office互操作
操作Excel
雖然Powershell可以通過COM接口和Office程序交互,不過最常用的還是操作Excel,所以我這里只介紹如何控制Excel表。下面最后一個參考資料就是我參考的操作Excel的文章,可能需要梯子才能訪問。需要注意一點,既然是操作Excel,當然首先電腦上需要先安裝Excel才能正常使用。
打開和關閉
首先,我們來創(chuàng)建一個Excel對象,這樣實際上會創(chuàng)建一個Excel應用程序。
$excel = New-Object -ComObject Excel.Application
執(zhí)行了上面的命令,什么事情都沒有發(fā)生。這是因為默認啟動的實例是隱藏的,要顯示Excel的窗口的話,將它設置為可見即可。
$excel.Visible=$true
如果要打開一個現(xiàn)成的工作簿,使用Open 函數(shù)。
$workbook = $excel.Workbooks.Open("XXX.xlsx")
如果要創(chuàng)建一個新的工作簿,使用Add 函數(shù)。
$workbook = $excel.Workbooks.Add()
一個工作簿可以有多個工作表,要選擇某一個工作表,使用Worksheets.Item 屬性,需要注意這里的下標從一開始。
$worksheet = $workbook.Worksheets.Item(1)
對數(shù)據(jù)完成操作之后,需要保存的話,使用SaveAs 函數(shù)。
$workbook.SaveAs("D:\Desktop\hello.xlsx")
操作數(shù)據(jù)
前面只說了打開和關閉操作,下面來看看如何具體讀取和寫入數(shù)據(jù)。首先回到上面那步工作表,因為如果要操作數(shù)據(jù),需要在工作表對象上進行操作。
$worksheet = $workbook.Worksheets.Item(1)
要操作數(shù)據(jù),調用工作表對象的Cells 屬性即可。比方說我要打印九九乘法表,那么就可以用類似下面的代碼來迭代寫入數(shù)據(jù)。
for ($i = 1; $i -le 9; ++$i) {
# 第一行
$worksheet.Cells(1, $i + 1) = $i
# 第一列
$worksheet.Cells($i + 1, 1) = $i
# 它們的乘積
for ($j = 1; $j -le 9; ++$j) {
$worksheet.Cells($i + 1, $j + 1) = $i * $j
}
}
操作之后,Excel表中應該存在如圖所示的數(shù)據(jù)。
類似的,讀取數(shù)據(jù)也很簡單,只要讀取Cells 屬性即可。
for ($i = 1; $i -le 10; ++$i) {
for ($j = 1; $j -le 10; ++$j) {
Write-Host -NoNewline $worksheet.Cells($i, $j).Text "`t"
}
Write-Host
}
上面的代碼獲取了我們剛才寫入Excel的數(shù)據(jù),然后將其轉換為文本并輸出,每個數(shù)據(jù)之間使用制表符\t 分隔,注意Powershell中的轉義字符使用的這個特殊字符。結果應該類似如圖所示。
繪制圖表
Excel很常用的一種操作就是繪制圖表,這里也簡單說說。不過由于這種資料在網上面實在太少,我就算用谷歌搜索英文網頁也搜不出來多少資料,大部分都屬于一點小腳本。所以這里只能隨便說說了。
首先準備一下數(shù)據(jù),我準備了如圖所示的數(shù)據(jù)。
然后來創(chuàng)建一個圖表對象。如果使用交互式環(huán)境Powershell ISE的話,智能提示會顯示這里有AddChart 和AddChart2 兩個方法,不過我看了下文檔,前面那個過時了,所以這里使用帶2的那個版本。
$chart=$worksheet.Shapes.AddChart2().Chart
創(chuàng)建了圖表對象之后,我們?yōu)樗付〝?shù)據(jù)源。
$chart.SetSourceData($worksheet.Range('a1', 'd5'))
這時候如果觀察Excel的話,會發(fā)現(xiàn)已經出現(xiàn)了一個初步的圖形。如果希望改變圖形樣式的話,設置圖標的類型即可。這里將圖表類型保存為一個變量,之后就可以省略長長的類名了。這里推薦使用Powershell ISE,因為自動補全可以顯示所有類型的圖標,只需要修改一下圖表類型并觀察Excel中圖標類型的變化就可以明白類型和圖標的對應關系了。
$chartTypes = [Microsoft.Office.Interop.Excel.XLChartType]
$chart.ChartType = $chartTypes::xlColumnClustered
最后效果如圖所示,我看到人家可以使用方法顯示圖例。但是我使用這個方法卻不知道為什么顯示不了。所以這里只能將就一下了。
最后再來畫個餅狀圖,數(shù)據(jù)還是上面的數(shù)據(jù),不過這次只使用語文那一列的數(shù)據(jù)。基本上和上面的一樣,只有類型那里改成xlPie 。
$chartTypes = [Microsoft.Office.Interop.Excel.XLChartType]
$chart = $worksheet.Shapes.AddChart2().Chart
$chart.SetSourceData($worksheet.Range('a1', 'b5'))
$chart.ChartType = $chartTypes::xlPie
$chart.ApplyDataLabels(5)
最終效果圖如下。
ImportExcel
上面的方法好像只能在安裝Excel的環(huán)境下運行,如果沒有安裝Office,但是也想使用編程功能,可以使用第三方的模塊。這就是這里要介紹的ImportExcel。使用它,我們可以在沒有安裝Excel的情況下編輯Excel文件。
首先需要安裝它,可以利用Powershell的包管理器方便的安裝。
Install-Module ImportExcel -scope CurrentUser
如果想讓所有用戶都可以使用這個模塊,需要安裝到全局位置,不過這需要管理員權限,所以需要在管理員模式的Powershell窗口中運行。
Install-Module ImportExcel
這個模塊如何使用我就不作介紹了,這個項目的README文件上基本列出了所有功能和對應的GIF圖,需要什么功能只要看一看應該就可以使用了。
參考資料
https:///archives/interacting-with-the-registry-in-powershell/
https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.aspx
http://www./2014/03/powershell-read-excel-file-using-com.html
|