Chapter 1. Welcome to PowerShell
Last updated
Last updated
Managing Windows through objects (透過Object管理Windows)
另一個驅動新Shell模組需求的原因是當Windows得到更多更多的子系統和功能時,使用者不得不去思考在管理系統時會有越來越多的Issue產生.為了幫助使用者解決這種複雜性的增加,這些可被管理的元素被拆解成結構性的structure data object.Management Object的集合在Microsoft內部被稱為Windows Management Surface.
Note: Microsoft不是唯一處理Issue複雜性增加的公司,大多數業界的人也面臨到這樣的問題.這導致了一間叫Distributed Management Task Force(dmtf.org)的公司建立了一個稱為 Common Information Model (CIM)的標準.而 Microsoft原本實踐的標準叫做 Windows Management Instrumentation (WMI).
雖然這個解構的方案解決了整體的複雜性並且在 GUI上運行良好,這使得使用傳統text-base shell envirement變得更加困難.
Windows是一種API驅動的作業系統,與UNIX以及其衍生產品是由文本(或文字)驅動相比.你可以藉由更改configuration設定檔去管理UNIX系統,但是在Windows中你必須透過API,意思是你必須accessing properties 和 using method on the appropriate object.
最後,隨著電腦的效能增加,Windows開始將desktop(桌機?)移到企業數據中心.在企業數據中心中,那邊有相當多的主機(伺服器)需要被管理,而圖形化的典及管理方式並無法擴展.將這些原因綜合起來,使得Microsoft發現不能再忽略command line的重要性.
現在你已經掌握住導致創立Powershell的環境因素,這是來自於能在分散式的object-base操作系統下能讓command-line自動化的需求,讓我們看看解決方案的形式.
1.2 PowerShell example code
我們已經說過PowerShell是用來解決編寫代碼的問題,現在你可能會問"小子!我的code在哪?",現在就讓我們來看範例吧!首先,我們將會看一個Get-ChildItem的範例,這一次,不是顯示目錄列表,而是像其他Shell的環境一樣你會使用輸出導向的方式將它存在文件中
Note:
PowerShell有aliases提供給不同的cmdlet,像是 dir C:\somefile.txt 和 ls C:\somefile.txt都可以使用. 在Interactive usage使用別名(aliases)是一個很好的做法,但不要在腳本中使用它們.我們通常會使用完整的cmdlet名稱,但偶爾會使用別名去節省空間.
再來,做為顯示目錄列表的替代,你將會使用output redirection將它除入一個檔案中就像在其他 shell 環境中一樣, 再下面的例子,你將會得到關於檔案名稱(somefile.txt)和它的主目錄C槽.使用redirection,你將會直接將output輸入到一個新的檔案中,C:\foo.txt,然後使用Get-Content(如果你想要的話你也可以使用別名cat or type)Command line去顯示我們存了什麼,它看起來就長這樣:
正如同你所看到的,command或多或少的照你的預期進行,讓我們來看看你應該更熟悉的其他事情.
Note:
在你的系統中隨便選一個存在的檔案都可以套用在這個範例上,但明顯的,我們的輸出並不會相同.
1.2.1 Navigation and basic operation(導覽以及基本的操作)
使用文件系統的PowerShell Command對於大多數的用戶來說應該是非常熟悉的,你可以使用cd(Set-Location的別名)來瀏覽文件系統,你可以使用copy或是cp(Copy-Item的別名)來複製檔案,使用move或是mv(Move-Item的別名)來搬移檔案,或是使用del或rm(Remove-Item的別名)來刪除檔案.為什麼每個command都有兩個呢?一組名稱對於cmd.exe / DOS用戶來說是熟悉的,另一組對UNIX用戶來說是熟悉的.實際上,它們都是同一個命令的別名,這是為了讓人們能夠輕鬆的使用PowerShell.
Note:
在Linux和macOS上的PowerShell v6 Core中, 為了防止與Linux和MacOS上本機命令的衝突,這些常用的別名已經被刪除了.這些別名只適用在Windows版本的PowerShell v6 Core.
請記住,雖然這些commands非常相似,但他們與其他兩個作業系統中的任一一個都不完全相同 .你可以使用Get-Help指令得到關於這些commands的說明文件.下面這是使用Get-Help查看dir的範例:
PowerShell help system (PowerShell說明系統)
PowerShell說明系統包含了所有command提供在這個系統上的資訊,並且是一個很好的探索方法.
在PowerShell v3或之後的版本,說明文件並不是預設就有安裝的,說明文件變成可以更新的並且你需要自己安裝最新的版本,看看
Get-Help about_Updatable_Help.
你甚至也可以用萬用字元去尋找想要的主題(v2或之後的版本),這是一個簡單的文字輸出,The PowerShell ISE還包涵更豐富關於Windows format的幫助,它讓你可以選擇一個項目然後按F1查看該項目的說明文件.借由使用-Online參數在Get-help後面可以讓你在瀏覽器上面查看說明文件.
使用 -online 是一個很好的方法去查看說明文件,因為線上文件總是時常更新、更正,但是本地的副本並沒有更新這麼快.
1.2.2 Basic expressions and variables (基本的表達式和變數)
除了執行Commands以外,PowerShell還可以評估表達式(expressions),實際上,它是一種計算器.我們來評估一個簡單的表達式:
注意到這邊當你打了一個表達式的時候,結果會被計算並且呈現出來.不必使用任何的print語句來顯示出結果,記住每當一個表達式被評估的時候,最重要的是輸出表達式的結果,並不是捨棄.(?)( It’s important to remember whenever an expression is evaluated, the result of the expression is output, not discarded.) PowerShell支持大部分的算術運算,也包含浮點數運算.
你也可以使用指向運算式將一個表達式的輸出存入檔案中:
變數也能被用來儲存command輸出的結果:
在這個範例中,你提取了由Get-ChildItem所返回的information objects集合中的第二個元素.你可以這樣做是因為你將Get-ChildItem的輸出保存為$files變數中的陣列物件.
Note.
在PowerShell中集合的Index是由0開始不是1,這是我們從.Net繼承來的特性.這也是為什麼$files[1]會提取第二個元素的原因,而不是第一個.
鑑於PowerShell是關於所有的物件,基本的操作運算需要執行許多的數字(?)我們將會在第三及第四章中仔細的介紹( Given PowerShell is all about objects, the basic operators need to work on more than numbers. Chapters 3 and 4 cover these features in detail.)
1.2.3 Processing data (處理資料?)
就像你所看到的,你執行一個command並且得到結果,使用PowerShell的功能對這些結果進行一些基本的操作,然後將結果儲存在文件和變量中.讓我們來看另一個你可以處理這些資料的方法,首先,你將會看到如何排序這些物件以及如何提取這些物件的屬性(properties).然後再來我們會看到使用PowerShell的控制流程(control flow)去寫一個script,使用一些條件以及迴圈去做一些複雜的程序.
sorting object(排序物件)
首先,排序藉由Get-ChildItem所回傳的information object列表,因為你是要排序這些objects,所以你所要使用的command是sort-object.為了方便一點,在這個範例中將會使用簡短的別名,首先查看預設的輸出,顯示出這是按文件名稱來排序的文件
現在你可以看到,檔案按相反的順序排序,現在你可以按造文件名稱以外的內容進行排序,例如:文件長度
Note:在這本書的許多範例中使用別名而不是完整的cmdlet名稱,這是為了簡潔起見,並確認代碼整齊地放在頁面中.
在PowerShell中,當你使用sort-object cmdlet(別名為:sort),你不必告訴他按照數字排序-它就已經知道欄位的類型,你也可以通過屬性名稱而不是欄位的數字來指定排序的Key( it already knows the type of the field, and you can specify the sort key by property name instead of a numeric field offset.),結果就像這樣:
這對你說明了物件的pipeline是如何運作的:
你可以通過名稱來訪問數據元素(data element),而不用使用substring index或是欄位名稱.( You have the ability to access data elements by name instead of using substring indexes or field numbers.)
通過保留元素的原始類型,operations無須提供其他訊息即可正確執行.( By having the original type of the element preserved, operations execute correctly without you having to provide additional information.)
現在讓我們來看看你還可以對Object來做什麼其他的事
從Object中選擇屬性
在本章節中,我們將會介紹對其他物件處理的cmdlet:Select-Object.這個cmdlet允許你選擇輸入到其中的對象的子範圍,並在這些對象上指定屬性的子集合.
假設你想要從檔案列表中得到一個最大的檔案並且將結果存入一個變數中
Note:
你將會注意到第二個prompt(提示) >> 當你複製之前的範例到你的PowerShell Console中,第一行的指令結束在pipe(|)符號,PowerShell interpreter會注意到這個,看到這個指令並還沒完全結束,並提示輸入額外的文字來完成這個command.一但命令完成後,你可以輸入第二個空行將指令發送給interpreter.如果你想要取消這個指令,你可以使用Ctrl+C在任何時間點強制結束,本書中的範例將不會包含>>,是為了讓讀者更方便閱讀.
現在你可能只會想要包含該文件目錄的名稱,你也可以使用Select-Object(別名:alias).與sort-object cmdlet一樣,select-object可以接受-Property的參數(在PowerShell的環境中你將會很常看到這個參數,command在使用參數都是一致的用法):
現在你就有一個只有單一屬性的物件了.
最終的簡化是為了獲得本身的價值,我們將會介紹一個新的cmdlet讓你在pipeline上能隨心所欲的處理任一個物件,ForRach-Object cmdlet執行了pipeline內每一個對象的語句塊.你可以從Oject中獲取任意屬性,然後使用ForEach-Oject指令對該屬性做處理.以下是一個將目錄中所有對象的長度相加的範例:
PowerShell方法的一大優勢就是一但你學習了解決問題的模式,你可以一再使用相同的模式,假設你想要查找列表中檔案最大的三個文件.這個command line可能長的會像這樣:
Note:
由於能夠反覆使用相同的command模式,在這本書中大多數的例子都是故意通用的.這個目的是為了凸顯解決方案的模式,而不是展示一個具體的例子.一但你理解了基本的模式,你可以有效的使用它們去解決大多數的其他問題.
如果你不能把指令打包成腳本,那麼腳本語言有什麼好處呢?PowerShell讓你能夠把你的command放在文字檔中,附檔名為.ps1,然後運行該command.你可以在你的腳本中設定參數,將下面的文字複製到文字檔中並儲存為hello.ps1
Note:
在本機上以預設配置執行腳本之前,你必須更改PowerShell的執行策略准許執行scripts.使用 Get-Help about_execution_policies去看有關執行策略的詳細說明,Windows版本之前的預設方式有所不同,請仔細檢查執行策略設置.
在你第一次執行這個腳本的時候,你可能不會指定任何特定的參數:
你可以再回應的地方看到它使用了預設值.在執行一次,但這次輸入一個特定的參數:
現在這個參數取代了預設值,有時候你可能想在你的code裡面有個子程序.PowerShell通過函數來滿足這個需求.讓我們將hello腳本轉換成一個function.以下是它的樣子
顯示線上版本的說明文件:
將表達式的結果儲存在檔案中是有幫助的;將他們儲存到變數中也是有用的
這個輸出險是關於檔案系統物件(file system onjects)的基本屬性,然後依據檔案名稱排序,現在讓我們改成依據檔案名稱但排序方式改成descending(下降):
在這個例子中,你初使化一個變數$total設定值為0,然後藉由Get-ChildItem指令將它加上每一個檔案的長度,最後顯示total的值(你在你的電腦終將會得到不一樣的total值)
這裡,Get-ChildItem指令檢索File information object的列表,PowerShell會按照降序的方式排列它,然後他會選前三個最大的文件當成結果.
現在讓我們來看另外一個不同的問題,你可能想找系統中前三大工作集大小的程序,這個coomand-line可能長的會像這樣:這時候你執行了Get-Process去取得這台電腦程序的資料,然後按造工作集的大小去排序它而不是使用檔案大小,否則該模式與前面的例子基本上相同,這個命令模是可以反覆應用.
Pipeline是傑出的,但是有時候你需要對你的script做更多的控制流程.PowerShell有大多是編成語言中通常的流程控制語句,這些包含基本的if,switch和迴圈while,for,foreach.下面的例子使用while和if語句:這個例子使用while迴圈去計算一段區間的數字,然後只把奇數印出來.在while迴圈中使用if語句去判斷測試是否這個數字是奇數,如果是的話就把這則訊息印出來, 你也可以用foreach做出一樣的事情,範圍運算子(...),但更簡潔:這個foreach語句迭代了所有Object的集合,範圍運算子是生成一系列數字的一種方法,這兩者結合起來,使循環的數字序列變成非常簡潔的操作.
因為範圍運算子生成一連續的數字,數字就像PowerShell其他的東西一樣都是物件,你可以透過使用pipline去實踐它,然後再使用ForEach-Object(別名:foreach)cmdlet:這些範例只捕捉了PowerShell 流程控制的表面.(你在之後將會看到switch語句),在第五章中我們會藉由更多範例完整的介紹control structures.
注意到關鍵字param被用來定義一個叫做$name的參數.這個參數給了一個預設值'bub',現在你可以使用./hello使用PowerShell執行這個腳本,你需要.\告訴PowerShell從當前的目錄獲得command.