- PowerShell 管道
- 管道輸出
- 控制管道輸出的格式設置
- Format-List
- Format-Table
- Format-Wide
- 管道選擇、排序和度量對象
- 排序和分組
- Sort-Object
- Format 的 GroupBy分組
- 度量管道中的對象
- Select-Object
- Unique去重
- Property
- 自定義屬性並設置表達式與格式
- 計算
- 排序和分組
- 從管道中篩選對象
- 比較運算符
- 基本篩選器語法
- 高級篩選器語法
- 組合多個條件
- True 或 False 的屬性篩選使用技巧
- 高級篩選不受簡單篩選限制
- 優化篩選器性能
- 枚舉
- 枚舉管道對象語法
- 寫入到文件
- 轉換為其他形式的數據表示形式
- Csv
- XML
- Json
- HTML
- 其他輸出選項
- 轉換為其他形式的數據表示形式
- 傳遞管道對象
- ByValue 傳遞數據
- ByPropertyName 傳遞數據
- 展開屬性值
- 深入瞭解Powershell腳本
- 開發生命週期與安全強化
- PowerShellGet 模塊
- 執行策略
- 以數字方式對腳本進行簽名
- 進階語法
- ForEach 循環
- If 構造
- Switch 構造
- For 構造
- 其他循環構造
- Do..While
- Do..Until
- While
- Break 和 Continue
- 導入數據
- Get-Content
- Import-Csv
- Import-Clixml
- ConvertFrom-Json
- Invoke-RestMethod
- 接受用户輸入
- Read-Host
- Credential憑證使用
- Get-Credential
- Export-Clixml
- 腳本故障排除與錯誤處理
- 輸出命令的層次與用途
- 腳本中使用斷點
- 根據行進行斷點
- 根據命令進行斷點
- 根據特定變量進行斷點
- 錯誤操作
- $ErrorActionPreference
- -ErrorAction
- $ErrorActionPreference
- 函數與模塊
- 變量範圍
-
- Set-Variable指定作用域
- 類似指針修改
- return
-
- 創建模塊
- 變量範圍
- 開發生命週期與安全強化
PowerShell 管道
管道輸出
PowerShell 命令不會生成文本作為輸出,而是會生成對象,對象是描述內存中數據結構的通用詞。
運行 Get-Service 命令時,它會返回服務對象的集合,每個對象都包含 Name、DisplayName 和 Status 等名稱的屬性。
控制管道輸出的格式設置
格式設置 cmdlet 為:
- Format-List
- Format-Table
- Format-Wide
- Format-Custom
Format-Custom cmdlet 需要創建定義格式的自定義 XML 配置文件。 該 cmdlet 不經常使用。
Format-List
Format-List cmdlet 將命令的輸出格式化為一個簡單的屬性列表,其中每個屬性顯示在一個新行上。
如果將輸出傳遞給 Format-List 的命令返回多個對象,則會為每個對象顯示單獨屬性列表。
當命令返回大量很難以表格格式查看的屬性時,列表格式尤其有用。
Format-List cmdlet 的別名是 fl。
Format-Table
Format-Table cmdlet 將輸出格式化為表格,其中每一行表示一個對象,每一列表示一個屬性。
這個輸出的效果和默認的沒啥效果,多了一個就是你可以選擇參數來進行定義你輸出的效果,下面介紹參數↓↓↓
可使用多種參數修改此格式,例如:
-
-AutoSize。 此參數可根據數據的寬度來調整列的大小和數量。 在 Windows PowerShell 5.0 及更高版本中,-AutoSize 默認設置為 true。 在更低版本的 Windows PowerShell 中,默認值可能會截斷表中的數據。
-
-HideTableHeaders。 此參數會從輸出中移除表標頭。
-
-Wrap。 此參數會使超出列寬的文本換行到下一行。
Format-Table cmdlet 的別名是 ft。
Format-Wide
Format-Wide cmdlet 的輸出是單個列表中分多列顯示的單個屬性。
這個其實只需要知道:使用 -Property 參數,指定一個屬性去進行多個列展示,不用單個列展示這麼難看
下面展示的就是服務的所有名字,但是我們是用3列進行展示
Get-Service | fw -Property Name -Column 3
管道選擇、排序和度量對象
排序和分組
Sort-Object
Sort-Object 命令接受一個或多個屬性名作為排序依據, 默認情況下,命令按升序排序
Get-Service | Sort-Object –Property Name –Descending
Get-Service | Sort Name –Desc
Get-Service | Sort Status,Name
默認情況下,字符串屬性的排序不考慮大小寫。
(但是Sort-Object 也有參數去支持指定區分大小寫的排序、特定區域性的排序規則和其他選項)
Format 的 GroupBy分組
Format-List、Format-Table 和 Format-Wide 格式設置 cmdlet 具有接受屬性名的 -GroupBy 參數。 通過使用 -GroupBy 參數,可以按指定屬性對輸出進行分組。
注意:這裏説的是Format的幾個格式設置的分組,所以要用格式cmdlet然後再使用這個GroupBy參數
Get-Service | Sort-Object Status,Name | fw -GroupBy Status
-GroupBy 參數的運行方式與 Group-Object 命令類似。 Group-Object 命令接受管道輸入,讓你可以更好地控制對象分組。 Group-Object 具有別名 group。
度量管道中的對象
Measure-Object 默認情況下,該命令會對集合中的對象數進行計數,並生成包含計數的測量對象。
使用 Measure-Object 的 -Property 參數可指定單個屬性,該屬性必須包含數值。 隨後,可以添加 -Sum、-Average、-Minimum 和 -Maximum 參數,以計算指定屬性的這些聚合值。
(通常可注意到 -Sum、-Average、-Minimum 和 -Maximum 參數被截斷為 -Sum、-Ave、-Min 和 -Max)
以下命令計算文件夾中的文件數,並顯示文件大小的最小、最大和平均值:
(Recurse遞歸讀取)
Get-ChildItem -File -Recurse | Measure -Property Length -Sum -Average -Minimum -Max
效果如下圖:
Select-Object
Select-Object 命令具有別名 Select。
這個命令比較簡單,用法如下:
用Property指定要選擇的對象即可,多個就用逗號隔開
Get-Process | Select-Object -Property 列名1,列名2
- 選擇最少虛擬內存使用量排名前 10 的進程
Get-Process | Sort-Object –Property VM | Select-Object –First 10
- 選擇最後 10 個正在運行的服務並按名稱排序
Get-Service | Sort-Object –Property Name | Select-Object –Last 10
- 選擇 CPU 用量最少的五個進程,並跳過使用最少 CPU 的那一個進程
Get-Process | Sort-Object –Property CPU –Descending | Select-Object –First 5 –Skip 1
Unique去重
只需要在指定對象後添加多一個-Unique參數即可
- 顯示某個用户在每個部門中的用户信息
Get-ADUser -Filter * -Property Department | Sort-Object -Property Department | Select-Object Department -Unique
Property
沒啥好説的,就是select-object 的 參數Property 指定顯示的進程屬性即可
- 顯示一個表,其中包含本地計算機上運行的所有進程的名稱、進程 ID、虛擬內存大小、分頁內存大小和 CPU 使用率:
Get-Process | Select-Object –Property Name,ID,VM,PM,CPU | Format-Table
- -Property 參數適用於 -First 或 -Last 參數。 以下命令返回具有最大 CPU 使用率的 10 個進程的名稱和 CPU 使用率:
Get-Process | Sort-Object –Property CPU –Descending | Select-Object –Property Name,CPU –First 10
自定義屬性並設置表達式與格式
- 定義屬性的名字:
- label、l、name 或 n:這指定計算屬性的標籤或名稱。 由於小寫字母 l 在某些字體中類似於數字 1,因此請嘗試使用 name、n 或 label。
- 設置屬性計算的式子:
- expression 或 e:這將指定設置計算屬性值的表達式。
Get-Process |
Select-Object Name,ID,@{n='VirtualMemory';e={$PSItem.VM}},@{n='PagedMemory';e={$PSItem.PM}}
$PSItem 是由 Windows PowerShell 創建的特殊變量。 它表示通過管道傳輸到 Select-Object 命令中的任何對象。 在上一個示例中,這是一個 Process 對象。 $PSItem 之後的句點允許訪問對象的單個成員。 在此示例中,一個計算屬性使用 VM 屬性,另一個使用 PM 屬性。
當我們輸入正常的Get-Process 並獲取他的所有屬性的時候你會看到VM這個屬性,所以我們$PSItem.VM是能夠獲取到的
檢查一下是否有VM
Get-Process | Get-Member | Select-Object -Property Name | Format-Wide -Column 5
下圖可以看到確實有VM屬性
- 為什麼用@{}
解釋:還記不記得之前創建空數組是用@(),這裏是創建hash表,所以用@{},n是屬性名,對應鍵,e是計算式子相當於值,所以説我們還能知道在自定義的時候不能定義同一個名字的屬性
計算
你可能想要修改前面的命令以顯示內存值(以兆字節 (MB) 為單位)。 PowerShell 將縮寫 KB、MB、GB、TB 和 PB 分別表示千字節、兆字節、千兆字節、兆兆字節和拍字節。 因此,可以按如下所示修改命令:
($PSItem是接收傳過來的對象,$_也是一樣的, 用的比較多的是$_,所以説我們可以在Get-Process出來的對象中一個個用$PSItem去取你想要的屬性或者激活方法)
Get-Process |
Select-Object Name,
ID,
@{n='VirtualMemory(MB)';e={$PSItem.VM / 1MB}},
@{n='PagedMemory(MB)';e={$PSItem.PM / 1MB}}
生成的值有幾個小數位,這在視覺上是不理想的。
若要改進輸出,請進行以下更改:
Get-Process |
Select-Object Name,
ID,
@{n='VirtualMemory(MB)';e={'{0:N2}' –f ($PSItem.VM / 1MB) -as [Double] }},
@{n='PagedMemory(MB)';e={'{0:N2}' –f ($PSItem.PM / 1MB) -as [Double] }}
上一個示例中的語法可能看起來令人困惑,因為它包含許多標點符號。 從基本表達式開始:
'{0:N2}' –f ($PSItem.VM / 1MB)
上一個表達式將 VM 屬性除以 1 MB,然後將結果格式化為最多兩個小數位的數字。 然後將該表達式放入哈希表中:
該哈希表創建名為 VirtualMemory(MB) 的自定義屬性。
@{n='VirtualMemory(MB)';e={'{0:N2}' –f ($PSItem.VM / 1MB) }}
從管道中篩選對象
比較運算符
| 操作 | DESCRIPTION |
|---|---|
| -eq | 等於 |
| -ne | 不等於 |
| -gt | 大於 |
| -lt | 小於 |
| -le | 小於或等於 |
| -ge | 大於或等於 |
在powershell中默認是不區分大小寫,但是在比較的時候難免希望對大小寫的區分
所以我們可以在操作中添加一個前綴c作為比較區分大小寫的標誌
-ceq
-cne
不僅僅上述的運算符,其他也都可以加c
當然還有like也可以用來區分大小寫去匹配,因為-like 運算符類似於 -eq
-clike
其他更高級的運算符存包括:
- -in 和 -contains 運算符,用於測試集合中是否存在對象。
- -as 運算符,用於測試對象是否為指定類型。
- 將字符串與正則表達式進行比較的 -match 和 -cmatch 運算符。
- 還包含許多運算符來反轉比較的邏輯,例如 -notlike 和 -notin。
簡單案例:
PS C:\> 100 -gt 10
True
PS C:\> 'hello' -eq 'HELLO'
True
PS C:\> 'hello' -ceq 'HELLO'
False
基本篩選器語法
Where-Object 命令及其別名 Where
- 僅顯示正在運行的服務的列表
Get-Service | Where Status –eq Running
基本語法的限制
只能對單個比較使用基本語法。 例如,無法顯示已停止且具有“自動”啓動模式的服務列表,因為需要兩個比較。
不能將基本語法用於複雜表達式。 例如,服務對象的 Name 屬性由一串字符組成。 PowerShell 使用 System.String 對象包含該串字符,而 System.String 對象具有 Length 屬性。 以下命令不適用於基本篩選語法:
Get-Service | Where Name.Length –gt 5
目的是顯示名稱超過五個字符的所有服務。 但是,此命令永遠不會生成輸出。 一旦超過基本語法的能力,必須改用高級篩選語法。
高級篩選器語法
高級語法使用篩選器腳本
使用 -FilterScript 參數傳遞該腳本塊
對於通過管道傳遞到命令的每個對象,篩選器腳本都會運行一次。 當篩選器腳本返回 True 時,該對象將作為輸出傳遞到管道中,當篩選器腳本返回 False 時,將從管道中刪除該對象。
以下兩個命令具有相同的功能。 第一個命令使用基本語法,第二個命令使用高級語法執行相同的操作:
Get-Service | Where Status –eq Running
Get-Service | Where-Object –FilterScript { $PSItem.Status –eq 'Running' }
-FilterScript 參數是位置參數,大多數用户會省略它。 大多數用户還會使用 Where 別名或 ? 別名,此名稱長度更短。
推薦使用 $_ 變量而不是 $PSItem,因為在 Windows PowerShell 1.0 和 Windows PowerShell 2.0 中只允許使用 $_。
以下命令執行與前兩個命令相同的任務:
Get-Service | Where {$PSItem.Status –eq 'Running'}
Get-Service | ? {$_.Status –eq 'Running'}
組合多個條件
高級語法允許通過使用 -and 和 -or 布爾值或邏輯運算符來組合多個條件。 下面是一個示例:
Get-EventLog –LogName Security –Newest 100 |
Where { $PSItem.EventID –eq 4672 –and $PSItem.EntryType –eq 'SuccessAudit' }
邏輯運算符的任意一側都必須是一個完整的比較式子,下面給幾個錯誤示範,請不要犯錯:
Get-Process | Where { $PSItem.CPU –gt 30 –and VM –lt 10000 }
Get-Service | Where { $PSItem.Status –eq 'Running' –or 'Starting' }
True 或 False 的屬性篩選使用技巧
Get-Process 生成的對象具有名為“Responding”的屬性,此屬性包含 True 或 False。
獲取正在響應的進程的列表,可以使用以下命令之一:
Get-Process | Where { $PSItem.Responding –eq $True }
Get-Process | Where { $PSItem.Responding }
在第一個命令中,特殊 shell 變量 $True 用於表示布爾值 True。 第二個命令未包含任何比較,但它是有效的,因為 Responding 屬性已包含 True 或 False
這類似於反向邏輯,僅列出未響應的進程:
Get-Process | Where { -not $PSItem.Responding }
在前面的示例中,-not 邏輯運算符將 True 更改為 False,並將 False 更改為 True。 因此,如果進程未響應,則其 Responding 屬性為 False。 -not 運算符將結果更改為 True,這會使進程被傳遞到管道中,幷包含在命令的最終輸出中。
高級篩選不受簡單篩選限制
現在再去根據字符長度來篩選就沒問題了
Get-Service | Where {$PSItem.Name.Length –gt 8}
優化篩選器性能
説是優化,但其實都是靠編寫腳本自己的功底
Get-隨便 對於下面兩個示例,你認為哪一個速度更快?
Get-隨便 | Sort-Object –Property Letter | Where-Object –FilterScript { $PSItem.Color –eq 'Red' }
Get-隨便 | Where-Object –FilterScript { $PSItem.Color –eq 'Red' } | Sort-Object –Property Letter
第二個命令速度更快,因為他先是移除了不要的再進行排序,這加速了排序,但是如果你排序了再移除就表示你排序排了沒用的東西,然後還要移除,那就慢了。
再比如下面這個查找文件,一看就知道是第二個塊了,內置的直接使用更快
Get-ChildItem | Where { -not $PSItem.PSIsContainer }
Get-ChildItem -File
枚舉
這裏的枚舉是説powershell取出來的對象在管道中每一個都傳遞給下一個cmdlet去操作。
比如:停止計算機上每個正在運行的記事本進程,則可以運行以下兩個命令之一
Get-Process –Name Notepad | Stop-Process
Stop-Process –Name Notepad
比如Get-Process 篩選了名字為Notepad的,那就可能會出現很多個進程,那給到管道後面的Stop-Process來説,他就是在枚舉每一個Notepad進程然後執行停止進程操作
枚舉管道對象語法
這裏官網分了基本語法和高級語法,但其實枚舉管道都支持
基本和高級的區分就是:基本的不用腳本,高級的用腳本塊
查看下ForEach-Object的幫助文檔:
可以看到有兩個參數,一個是接腳本塊的,一看就是高級用法
基本用法應該就是下面的-MemberName指定屬性或方法名的了
基本語法:
兩個常見別名: ForEach 和 %。 與 Where-Object 一樣, ForEach-Object 具有基本語法和高級語法。
下面三個都一樣,原理都是將Get-ChildItem取出來的對象 ([System.IO.FileInfo])進行For枚舉出來然後參數-MemberName就是取屬性或者方法,那我們給的Encrypt就是一個方法(加密),所以我們就相當於給當前遍歷的對象執行了該方法,以此類推每一個對象都會執行一次。
Get-ChildItem –Path C:\Encrypted\ -File | ForEach-Object -MemberName Encrypt
# 使用了別名和忽略了參數
Get-ChildItem –Path C:\Encrypted\ -File | ForEach Encrypt
# 使用了別名和忽略了參數
Get-ChildItem –Path C:\Encrypted\ -File | % Encrypt
你可以特地去查看下是否有該方法:
Get-ChildItem | Get-Member -Name Encry*
高級語法:就是使用腳本塊
使用高級語法加密一組文件
Get-ChildItem –Path C:\ToEncrypt\ -File | ForEach-Object –Process { $PSItem.Encrypt() }
範圍運算符是兩個句點 (..),中間沒有空格,range 運算符生成從 1 到 3 的整數對象,這 3 個對象通過管道傳遞給 ForEach-Object,迫使腳本塊運行 3 次
1..3 | ForEach-Object { Get-Random }
寫入到文件
Out-File就相當於cmd裏面的文本重定向運算符 > 和 >>,這些運算符可作為 Out-File 的別名,管道末尾的大於號 (>) 將輸出定向到文件,從而覆蓋內容,兩個連續的大於號 (>>) 將輸出定向到文件,從而將輸出附加到文件中已有的任何文本。
例如:
下面這個雖然説輸出到csv文件,但其實就是文本格式輸入進去,沒有csv格式
Get-Service |
Sort-Object –Property Status, Name |
Select-Object –Property DisplayName,Status |
Out-File –FilePath ServiceList.csv
轉換為其他形式的數據表示形式
PowerShell 使用兩個不同的謂詞進行轉換: ConvertTo 和 Export
Csv
使用 ConvertTo 的命令(如 ConvertTo-Csv )接受來自管道的對象作為輸入,並將轉換後的數據作為輸出生成到管道
切記:這個是將對象轉換成了csv格式,但是你直接輸入進文件可能會存在各種問題,比如ConvertTo-Csv 生成的 CSV 包含類型信息行(如 #TYPE System.ServiceProcess.ServiceController),這不是標準 CSV 的一部分,可能會干擾某些應用程序的解析,這就需要Export-Csv解決
Get-Service | ConvertTo-Csv | Out-File Services.csv
使用 Export(如 Export-Csv)的命令執行兩項作:它會轉換數據,然後將數據寫入外部存儲,例如磁盤上的文件
Get-Service | Export-Csv Services.csv
XML
ConvertTo-Clixml 和 Export-Clixml
Json
ConvertTo-Json 命令創建 JSON 格式的數據,必須使用 Out-File 或文本重定向運算符之一將 JSON 數據發送到文件
HTML
ConvertTo-Html 命令支持此功能,必須使用 Out-File 或其別名之一來定向輸出。
ConvertTo-Html 創建編碼為 HTML 的簡單列表或表,您可以通過各種參數以有限的方式控制HTML格式,例如:
- ‑Head。 指定 HTML 頭 節的內容。
- —標題。 設置 HTML 標題 標記的值。
- -PreContent。 定義應在表或列表輸出之前顯示的任何內容。
- -PostContent。 定義應在表或列表輸出之後顯示的任何內容。
其他輸出選項
Out-* 命令的核心功能、常見參數和典型使用場景:
| Cmdlet | 核心功能 | 常用參數 | 典型應用場景 |
|---|---|---|---|
Out-Host |
將輸出發送到主機(控制枱)進行顯示 | -Paging (強制分頁顯示) |
逐頁查看長輸出,避免滾動過快錯過信息 |
Out-Printer |
將輸出發送到打印機進行打印 | -Name (指定打印機名稱) |
打印命令結果、報告或配置清單 |
Out-GridView |
在交互式表格窗口中顯示輸出,支持排序、篩選和複製 | -Title (設置窗口標題) |
可視化數據分析、快速篩選和分享信息,但無法直接保存 |
Out-Host:控制枱輸出管理
Out-Host是 PowerShell 默認的輸出方式,即直接將結果呈現在控制枱。它的特殊之處在於你可以通過-Paging參數手動控制輸出分頁-Paging參數:強制對輸出進行分頁,顯示一頁後暫停,按空格鍵查看下一頁,按 Q 鍵退出- 與
more命令的關係:在 PowerShell 中,more是一個內置函數,它本質上是Out-Host -Paging的別名,兩者功能相同
逐頁查看系統進程列表
Get-Process | Out-Host -Paging
# 也可以使用更簡潔的more
Get-Process | more
Out-Printer:打印輸出
Out-Printer允許你將命令的輸出直接發送到打印機。- 默認行為:不使用參數時,輸出會發送到默認打印機
-Name參數:指定目標打印機的名稱,打印機名稱需與系統中安裝的打印機名稱匹配(可通過Get-Printercmdlet 查看所有可用打印機)
打印當前運行的進程列表到默認打印機
Get-Process | Out-Printer
將系統服務狀態發送到特定打印機(假設打印機名為 "HP-LaserJet"):
Get-Service | Out-Printer -Name "HP-LaserJet"
打印到虛擬打印機(如生成PDF):如果你安裝了 Microsoft Print to PDF 這類虛擬打印機,也可以使用 -Name 參數指定它來生成PDF文件。
Get-Service | Where-Object {$_.Status -eq 'Running'} | Out-Printer -Name "Microsoft Print to PDF"
Out-GridView:交互式表格輸出
Out-GridView(通常簡稱 OGV)是一個非常強大的工具,它會在一個新窗口中以交互式表格的形式顯示輸出。你可以:- 點擊列名進行排序(升序/降序)。
- 使用頂部的篩選框對任何列進行篩選(支持包含、不包含等條件)。
- 選中行並複製(Ctrl+C),然後粘貼到 Excel 或其他應用程序中。
- 多選(Ctrl+點擊 或 Shift+點擊)。
重要限制:正如你所讀到的,無法直接從 GridView 窗口保存數據。你需要先通過複製粘貼,或在命令行中就使用Export-Csv等命令保存數據。
可視化並篩選系統服務:
# 查看所有服務
Get-Service | Out-GridView
# 僅查看正在運行的服務,並自定義窗口標題
Get-Service | Where-Object Status -eq 'Running' | Out-GridView -Title "當前運行的服務"
# 結合篩選器:找出所有正在運行且名稱中包含 "windows" 的服務
Get-Service | Where-Object { $_.Status -eq 'Running' -and $_.Name -like '*windows*' } | Out-GridView
在彈出的窗口中,你可以進一步點擊“狀態”列排序,或在“名稱”列篩選器輸入更多關鍵字。
分析進程資源佔用:
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 | Out-GridView -Title "CPU佔用最高的10個進程"
自定義列順序:如果你使用 Select-Object 選擇並排序了屬性,Out-GridView 會遵循這個順序顯示列
Get-Service | Select-Object Name, Status, DisplayName, StartType | Out-GridView
傳遞管道對象
管道傳遞數據可以有兩種方式:ByValue 和 ByPropertyName
它們最根本的區別在於匹配的依據:
- ByValue:依據管道對象的整體類型進行匹配。
- ByPropertyName:依據管道對象的屬性名稱進行匹配。
例如運行:Get-Help Stop-Process -Full
必須看輸入支持哪種類型:那我們只能輸入下面的這幾種了
那既然我們要傳數據給Stop-Process的話那我們就需要知道左邊的那個輸出符不符合這裏面的輸入,下面詳細講一下這個!
ByValue 傳遞數據
直接將String類型傳給Get-Service
'BITS','WinRM' | Get-Service
是否成功前可以看下Get-Service接受哪些類型的管道輸入
Get-Help Get-Service -Full
包含string那就可以傳入了
但是這種就不行:
Get-LocalUser | Stop-Process
首先我們看下Stop-Process的接受類型
Get-Help Stop-Process -Full
接着再看Get-LocalUser的輸出是否符合Stop-Process的輸入類型
Get-Help Get-LocalUser -Full
下圖可以看到明顯不符合,輸出的是Object,傳到Stop-Process的時候就肯定報錯了
如何解決?那就交給ByPropertyName,指定輸出一個屬性內容即可
ByPropertyName 傳遞數據
這裏感覺沒啥好説的,就是在ByValue不成立的時候,我們就需要特別指定某個屬性給到下一個要執行的命令,但是前提是左邊和右邊的屬性名字要相同,否則在匹配的時候就不知道該屬性給哪個。
(有一個特殊情況就是希望將左邊的A屬性值傳遞給右邊的B屬性,兩個名字不一樣的時候就需要重命名)
重命名方式,這種就比較特殊
Get-Process有一個參數-ComputerName,它支持通過 ByPropertyName 接收輸入。- 但
Get-ADComputer返回的計算機對象有一個叫Name的屬性,沒有叫ComputerName的屬性。 - 因此,
Name屬性無法自動傳遞給-ComputerName參數
這樣就需要重命名了:
Get-ADComputer -Filter * | Select-Object @{Name='ComputerName'; Expression={$_.Name}} | Get-Process
若是説在 ByPropertyName 的時候,兩邊的屬性名相同那就會自動匹配去執行操作了(這種就不詳細説了)
展開屬性值
先看一個動作:
Get-Process –ComputerName (Get-LocalUser –Filter *)
這個是想要將Get-LocalUser給到Get-Process的ComputerName參數
先看Get-Process的ComputerName接受什麼輸入
Get-Help Get-Process -Full
可以看到只接受string類型,那我們直接將整個Get-LocalUser東西穿進去肯定不行
再看看這樣行不行
回答:看似可以,其實也不行
Get-Process –ComputerName (Get-LocalUser –Filter * | Select-Object –Property Name)
我們要看這個–Property Name輸出的到底是不是string
$(Get-LocalUser | Select-Object –Property Name -First 1).GetType()
查看後發現還是不是string,那這時候就需要用到展開屬性的操作了
其實就是改了個參數名:
將Property改為ExpandProperty,下面這樣就可以了
$(Get-LocalUser | Select-Object –ExpandProperty Name -First 1).GetType()
為什麼可以,我們直接看下取出來的Name是不是string即可
複習提問:
在命令行接口將對象從一個命令傳遞到管道中的另一個命令時,Windows PowerShell 總是優先嚐試使用哪種技術?
ByValue
深入瞭解Powershell腳本
開發生命週期與安全強化
PowerShellGet 模塊
| Cmdlet | 説明 |
|---|---|
| Find-Module | 使用此 cmdlet 在 PowerShell 庫中搜索 Windows PowerShell 模塊。 最簡單的用法是根據模塊名進行搜索,但也可以根據命令名、版本、DscResource 和 RoleCapability 進行搜索。 |
| Find-Script | 使用此 cmdlet 在 PowerShell 庫中搜索 Windows PowerShell 腳本。 最簡單的用法是根據腳本名進行搜索,但也可以根據版本進行搜索。 |
| PowerShell 庫需要使用傳輸層安全性 (TLS) 1.2 來幫助保護通信。 默認情況下,Windows 10 和 Windows Server 2016 不支持在 Windows PowerShell 中使用 TLS 1.2。 因此,需要啓用 TLS 1.2 才能下載 PowerShell 庫內容。 |
若要為當前 PowerShell 提示啓用 TLS 1.2,請運行以下命令:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
若要在計算機上永久解決此問題,需要創建註冊表項。 可以運行以下兩個命令來創建必要的密鑰:
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319'-Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
執行策略
確保當前配置,可以使用:Get-ExecutionPolicy
執行策略的選項包括:
- Restricted:不允許運行任何腳本。
- AllSigned:僅當腳本經過數字簽名後才能運行。
- RemoteSigned:下載的腳本只有在經過數字簽名後才能運行。
- Unrestricted:可以運行所有腳本,但在運行下載但未簽名的腳本時會顯示確認提示。
- Bypass:運行所有腳本且不顯示提示。
以數字方式對腳本進行簽名
使用現有的代碼簽名證書(如果你有)
如果你已經從公共證書頒發機構(CA)或企業的內部CA獲取並安裝了代碼簽名證書,可以用以下命令查找:
# 在當前用户的證書存儲中查找所有可用於代碼簽名的證書
$certs = Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert
# 如果你確定只有一個,可以直接賦值
$cert = Get-ChildItem -Path "Cert:\CurrentUser\My" -CodeSigningCert
Cert:\CurrentUser\My是 PowerShell 證書驅動器(PSDrive)中的一個路徑,指向當前用户的“個人”證書存儲區域。-CodeSigningCert參數是Get-ChildItem在證書驅動器中專用的,用於篩選出具有“代碼簽名”用途的證書。
創建自簽名證書(用於測試和學習)
在生產環境中,你需要一個受信任的CA頒發的證書。但在測試和學習時,可以快速創建一個自簽名證書
# 以管理員身份運行 PowerShell 執行以下命令
$certParams = @{
Type = 'CodeSigningCert'
Subject = 'CN=PowerShell Scripting Test' # 證書主題,CN是通用名
KeyUsage = 'DigitalSignature' # 密鑰用法:數字簽名
KeyExportPolicy = 'Exportable' # 密鑰可導出,方便備份和轉移
CertStoreLocation = 'Cert:\CurrentUser\My' # 證書存儲位置
HashAlgorithm = 'sha256' # 哈希算法
# FriendlyName 是可選的,便於在證書管理中識別
FriendlyName = 'My PowerShell Test Signing Certificate'
}
$cert = New-SelfSignedCertificate @certParams
重要提示:自簽名證書僅用於測試。因為它不是由受信任的根證書頒發機構頒發的,所以其他計算機默認不會信任它。
(你自己創建的,你自己使用的時候就導入即可,不用設置密碼啥的,因為是你自己創建你自己用,除非你導出的時候就要設置密碼,因為你導出肯定是要給其他計算機使用)
從證書文件導入
如果你有 .pfx 或 .p12 格式的證書文件(通常包含私鑰),可以使用 Get-PfxCertificate cmdlet 來加載它:
# 會彈窗提示輸入密碼
$cert = Get-PfxCertificate -FilePath "C:\Path\To\Your\CodeSigningCert.pfx"
# 或者使用SecureString自動輸入密碼(注意密碼安全)
$securePassword = ConvertTo-SecureString -String "YourCertificatePassword" -Force -AsPlainText
$cert = Get-PfxCertificate -FilePath "C:\Path\To\Your\CodeSigningCert.pfx" -Password $securePassword
加載的時候需要密碼,這需要在證書持有者導出證書的時候設置的那個密碼,然而這個pdx或者p12文件是用來簽名的,不是用來驗證的,用來驗證的那個是cert,這也是為啥要輸入密碼的原因了,這個證書是拿來公章簽名的。
拿到證書對象($cert)後,就可以用它來簽名腳本了。官網的例子是基礎,但強烈建議添加時間戳服務器參數。
# 基礎簽名(官網示例)
Set-AuthenticodeSignature -FilePath "C:\Scripts\MyScript.ps1" -Certificate $cert
# 推薦的簽名方式(添加時間戳)
$signParams = @{
FilePath = "C:\Scripts\MyScript.ps1" # 要簽名的腳本路徑
Certificate = $cert # 之前獲取的證書對象
HashAlgorithm = 'Sha256' # 哈希算法,建議使用Sha256
# 添加時間戳至關重要!即使證書過期,時間戳也能證明簽名時證書是有效的。
TimestampServer = 'http://timestamp.digicert.com'
# -IncludeChain 參數可選,默認是 'NotRoot'(包含除根CA以外的所有證書)
# -Force 參數可選,如果腳本已有簽名,強制替換
}
Set-AuthenticodeSignature @signParams
簽名完成後,務必檢查一下:
Get-AuthenticodeSignature -FilePath "C:\Scripts\MyScript.ps1"
查看輸出中的 Status 屬性:
Valid:簽名有效且受信任。UnknownError:簽名無效或證書不受信任(常見於自簽名證書)。NotSigned:腳本未簽名。
讓系統信任你的簽名
!!!!!記住這裏是驗證,不是用來簽名,前面説的都是pxf和p12證書,這裏講的是cer文件!!!!!!!!
對於自簽名證書,由於它不是公共CA頒發的,你需要將你的自簽名證書**導入到“受信任的根證書頒發機構”或“受信任的發佈者”存儲區。否則,在其他計算機上運行時會顯示 UnknownError。
- 將你的證書導出為
.cer文件(只包含公鑰)。 - 在需要運行此腳本的計算機上,將這個
.cer文件導入到“受信任的根證書頒發機構”或“受信任的發佈者”(對於代碼簽名證書,通常是“受信任的發佈者”)。
你可以使用 PowerShell 自動化導入信任證書的過程
$certPath = "C:\Path\To\Exported\Certificate.cer"
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine")
$store.Open("ReadWrite")
$store.Add((New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath)))
$store.Close()
進階語法
ForEach 循環
在某些情況下,可能需要使用 ForEach-Object cmdlet 來處理管道中的數據。 將數據存儲在數組中時,ForEach 構造支持處理數組中的每個項。
powershell ForEach ($user in $users) { Set-ADUser $user -Department "Marketing" }
在 PowerShell 7 中,已將 -Parallel 參數添加到 ForEach-Object cmdlet。 這樣,管道就可以同時處理多個對象。 相較於標準 ForEach 循環,同時處理多個對象所提供的性能更佳。 如果使用的是 PowerShell 7,應考慮這一點。 以下示例説明了如何將 ForEach-Object 與 -Parallel 參數配合使用。
$users | ForEach-Object -Parallel { Set-ADUser $user -Department "Marketing" }
默認情況下,-Parallel 參數支持一次處理五個項,可以使用 -ThrottleLimit 參數將其修改為更大或更小的值。
If 構造
舉例子:如果可用磁盤空間不足,則可以使用 If 語句顯示警告
If ($freeSpace -le 5GB) {
Write-Host "Free disk space is less than 5 GB"
} ElseIf ($freeSpace -le 10GB) {
Write-Host "Free disk space is less than 10 GB"
} Else {
Write-Host "Free disk space is more than 10 GB"
}
同時也學到大小是可以直接使用MB、GB等單位直接比較
Switch 構造
Switch ($choice) {
1 { Write-Host "You selected menu item 1" }
2 { Write-Host "You selected menu item 2" }
3 { Write-Host "You selected menu item 3" }
Default { Write-Host "You did not select a valid option" }
}
可以使用 -wildcard 參數,以與 -like 運算符相同的語法來執行模式匹配。 或者,可以使用 -regex 參數通過正則表達式執行匹配。
Switch -WildCard ($ip) {
"10.*" { Write-Host "This computer is on the internal network" }
"10.1.*" { Write-Host "This computer is in London" }
"10.2.*" { Write-Host "This computer is in Vancouver" }
Default { Write-Host "This computer is not on the internal network" }
}
For 構造
For($i=1; $i -le 10; $i++) {
Write-Host "Creating User $i"
}
處理對象數組時,最好使用 ForEach 構造,因為在處理之前不需要計算數組中的項數。
其他循環構造
Do..While
Do..While 構造運行腳本塊,直到指定條件為false
此構造保證腳本塊至少運行一次
Do {
Write-Host "Script block to process"
} While ($answer -eq "go")
Do..Until
Do..Until 構造運行腳本塊,直到指定條件為 true
此構造保證腳本塊至少運行一次
Do {
Write-Host "Script block to process"
} Until ($answer -eq "stop")
While
While 構造運行腳本塊,直到指定條件為 false
雖然它類似於 Do..While 構造,但它不能保證腳本塊的運行
While ($answer -eq "go") {
Write-Host "Script block to process"
}
Break 和 Continue
使用 Continue 可阻止修改要修改的用户列表中的管理員用户帳户:
ForEach ($user in $users) {
If ($user.Name -eq "Administrator") {Continue}
Write-Host "Modify user object"
}
Break 用於在最大帳户數已修改時結束循環:
ForEach ($user in $users) {
$number++
Write-Host "Modify User object $number"
If ($number -ge $max) {Break}
}
導入數據
Get-Content
直接讀取文件內容進來
$computers = Get-Content C:\Scripts\computers.txt
可在 Get-Content 的路徑中使用通配符,以便一次獲得多個文件的數據
可使用 -Include 和 -Exclude 參數修改所選文件
Get-Content -Path "C:\Scripts\*" -Include "*.txt","*.log"
可以使用 -TotalCount 和 -Tail 參數限制使用 Get-Content 檢索的數據量
- -TotalCount 參數指定應從文件開頭檢索多少行
- -Tail 參數指定從文件末尾檢索多少行
例如:
Get-Content C:\Scripts\computers.txt -TotalCount 10
Import-Csv
$users = Import-Csv C:\Scripts\Users.csv
輸出示例:
First,Last,UserID,Department
Amelie,Garner,AGarner,Sales
Evan,Norman,ENorman,Sales
Siu,Robben,SRobben,Sales
當我們存進一個變量後,也可以通過變量訪問某個數據
$users[2].UserID
Import-Csv 默認分隔符是逗號,有的文件不是以逗號進行分割的話你也可以使用Import-Csv,只要格式相同分隔符不同也可以用這個,前提是你要自己加參數去修改分隔符:
比如説分隔符是分號
Import-Csv -Path .\1.csv -Header h1,h2,h3 -Delimiter ';'
Import-Clixml
$users = Import-Clixml C:\Scripts\Users.xml
使用 -First 和 -Skip 參數來限制 Import-Clixml 檢索的數據
- -First 參數指定僅從 XML 文件的開頭檢索指定數量的對象
- -Skip 參數指定從 XML 文件開頭忽略指定數量的對象,並檢索所有剩餘的對象。
ConvertFrom-Json
$users = Get-Content C:\Scripts\Users.json | ConvertFrom-Json
Invoke-RestMethod
Invoke-RestMethod 能夠處理JSON、 XML、RSS 源和 ATOM 源。
$users = Invoke-RestMethod "https://hr.adatum.com/api/staff"
接受用户輸入
Read-Host
這種會在How many das後加上冒號然後提示用户輸入:
$answer = Read-Host "How many days"
下面這種會先打印How many days? ,-NoNewline就是不換行,然後也是等待用户輸入
這種就沒有冒號
Write-Host "How many days? " -NoNewline
$answer = Read-Host
-MaskInput 或 -AsSecureString 參數在提示符處屏蔽輸入用户,這種偏向於輸入密碼的時候不會直接顯示在終端上
$answer = Read-Host "How many days" -AsSecureString
具體使用哪個看情況了,我的電腦使用AsSecureString才行
Credential憑證使用
Get-Credential
它的核心作用就是安全地彈窗收集用户憑據(用户名和密碼),並將其封裝在一個 PSCredential 對象中,供其他需要憑據的 cmdlet 使用。
基礎用法:
這會彈出一個標準對話框,讓你輸入用户名和密碼。
$cred = Get-Credential
高級用法(自定義提示和用户名):
-Message:讓提示更清晰,指導用户輸入什麼憑據。-UserName:預填用户名字段,用户只需要輸入密碼即可。$env:COMPUTERNAME是環境變量,代表本機計算機名,這在工作組環境下至關重要。
# 自定義提示信息並預填用户名
$cred = Get-Credential -Message "請輸入本地管理員權限憑據" -UserName "$env:COMPUTERNAME\Administrator"
遠程管理另一台工作組計算機
假設你想從計算機 CLIENT-A 遠程管理計算機 CLIENT-B
# 在 CLIENT-A 上運行
# 1. 獲取 CLIENT-B 的本地管理員憑據
$cred = Get-Credential -Message "請輸入CLIENT-B的本地管理員憑據" -UserName "CLIENT-B\Administrator"
# 2. 建立遠程會話 (PSRemoting)
$session = New-PSSession -ComputerName "CLIENT-B" -Credential $cred
# 3. 在遠程會話中執行命令(例如:檢查磁盤空間)
Invoke-Command -Session $session -ScriptBlock { Get-Volume }
# 4. 關閉會話
Remove-PSSession $session
本地腳本臨時提權
你用自己的標準用户賬户登錄,但腳本中的某些操作(如修改系統設置)需要管理員權限。
# 檢查當前用户權限,如果不是管理員則請求憑據
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Warning "此操作需要管理員權限。"
$adminCred = Get-Credential -Message "請提供本地管理員密碼以繼續" -UserName "$env:COMPUTERNAME\Administrator"
# 使用 Start-Process 以管理員身份啓動一個新進程來運行命令
$scriptBlock = {
# 這裏放需要提權的命令,例如安裝Windows功能
Enable-WindowsOptionalFeature -Online -FeatureName "Microsoft-Hyper-V" -All
}
Start-Process "pwsh" -ArgumentList "-Command", $scriptBlock -Credential $adminCred -Wait -NoNewWindow
} else {
# 如果已經是管理員,直接執行命令
Enable-WindowsOptionalFeature -Online -FeatureName "Microsoft-Hyper-V" -All
}
訪問受保護的網絡共享
掛載一個需要特定用户名和密碼才能訪問的局域網共享文件夾。
$netCred = Get-Credential -Message "請輸入訪問共享\\FileServer\Data$的憑據" -UserName "FileServer\SomeUser"
# 將憑據映射到驅動器號
New-PSDrive -Name "Z" -PSProvider "FileSystem" -Root "\\FileServer\Data$" -Credential $netCred -Persist
# 現在可以像訪問本地磁盤一樣訪問 Z:\
Get-ChildItem Z:\
# 使用完畢後斷開
Remove-PSDrive -Name "Z"
Export-Clixml
首次保存憑據(在一台電腦上):
# 彈窗輸入一次憑據
$cred = Get-Credential -Message "輸入要保存的憑據" -UserName "MyPC\Admin"
# 將加密後的憑據保存到文件(只能由你在本機解密)
$cred | Export-Clixml -Path "C:\Users\$env:USERNAME\Documents\secureCred.xml"
後續腳本中自動使用保存的憑據:
# 無需彈窗,直接讀取加密文件獲取憑據對象
$savedCred = Import-Clixml -Path "C:\Users\$env:USERNAME\Documents\secureCred.xml"
# 使用憑據執行需要權限的操作,例如重啓遠程計算機
Restart-Computer -ComputerName "192.168.1.100" -Credential $savedCred -Force
腳本故障排除與錯誤處理
錯誤發生時,它們將存儲在 $Error 數組中。 最近的錯誤始終在索引零處。 新錯誤生成時,會插入到 $Error[0] 處,其他錯誤的索引將增加一。 每當需要查看以前的錯誤消息時,查看 $Error 中的錯誤會很有幫助。 例如,如果清除屏幕,則可以通過 $Error 查看最近的錯誤消息。
輸出命令的層次與用途
PowerShell 的輸出命令不是一個簡單的“打印”功能,而是一個完整的信息流系統。理解不同命令的定位是關鍵。
| 命令 | 用途 | 輸出位置 | 是否受 *Preference 變量影響 |
適用場景 |
|---|---|---|---|---|
Write-Host |
直接與用户交互 | 控制枱 (主機) | 否 | 顯示進度、美觀的標題、即時提示。謹慎使用。 |
Write-Output |
將對象放入輸出管道 | 管道 / 控制枱 | 否 | 腳本的主要輸出結果。通常隱式使用(如 "Hello")。 |
Write-Verbose |
輸出詳細信息 | 控制枱 ( verbose流) | 是 | 調試、記錄腳本執行的詳細步驟。 |
Write-Debug |
輸出調試信息 | 控制枱 (debug流) | 是 | 更深入的調試,可在運行時暫停腳本。 |
Write-Warning |
輸出警告信息 | 控制枱 (warning流) | 是 | 提示用户潛在的問題,但腳本會繼續執行。 |
Write-Error |
輸出錯誤信息 | 控制枱 (error流) | 是 | 報告錯誤,但不終止腳本執行。 |
Throw |
拋出終止錯誤 | 控制枱 (error流) | - | 報告嚴重錯誤,並立即終止當前函數/腳本。 |
Write-Verbose 和 Write-Debug:真正的調試利器
這兩個命令的強大之處在於它們的可控性。默認情況下它們是靜默的,只在需要時通過參數開啓。
示例腳本 (Test-Service.ps1):
[CmdletBinding()] # 啓用高級功能,支持 -Verbose 和 -Debug 參數
param (
[Parameter(Mandatory=$true)]
[string]$ServiceName
)
Write-Verbose "腳本開始執行,傳入的服務名參數為: $ServiceName"
# 檢查服務是否存在
$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
Write-Debug "Get-Service 查詢結果: $($service | Out-String)"
if (-not $service) {
Write-Error "錯誤: 找不到名為 '$ServiceName' 的服務。"
exit 1
}
Write-Verbose "服務狀態: $($service.Status)"
if ($service.Status -ne 'Running') {
Write-Warning "服務 '$ServiceName' 當前未運行。"
# 嘗試啓動服務
try {
Start-Service -Name $ServiceName
Write-Host "服務已成功啓動。" -ForegroundColor Green
}
catch {
Throw "啓動服務失敗: $($_.Exception.Message)"
}
} else {
Write-Output "服務 '$ServiceName' 正在運行。"
}
Write-Verbose "腳本執行完畢。"
如何使用這個腳本:
- 默認運行(只看到基本輸出):
.\Test-Service -ServiceName "WinRM"
# 輸出: 服務 'WinRM' 正在運行。
- 查看詳細信息(使用
-Verbose):
.\Test-Service -ServiceName "WinRM" -Verbose
# 輸出:
# 詳細: 腳本開始執行,傳入的服務名參數為: WinRM
# 詳細: 服務狀態: Running
# 服務 'WinRM' 正在運行。
# 詳細: 腳本執行完畢。
- 進行深度調試(使用
-Debug):
.\Test-Service -ServiceName "SomeService" -Debug
運行後會首先顯示 Write-Debug 的信息,並暫停,提示你:
調試: Get-Service 查詢結果:
(這裏會顯示Get-Service返回的詳細對象信息)
繼續執行?
[Y] 是(Y) [A] 全是(A) [N] 否(N) [L] 全否(L) [S] 暫停(S) [?] 幫助 (默認值為“Y”):
按 `Y` 繼續執行每一步,按 `A` 讓它自動執行完所有調試步驟。這讓你可以一步步觀察腳本的執行流程。
使用 $VerbosePreference 和 $DebugPreference 進行全局控制
在當前會話中開啓所有Verbose輸出:
$VerbosePreference = "Continue" # 默認是 "SilentlyContinue"
.\Test-Service -ServiceName "WinRM"
# 現在即使不加 -Verbose,也會輸出Verbose信息
在腳本開頭強制開啓調試(常用於日誌記錄):
[CmdletBinding()]
param()
# 在腳本內部設置,強制記錄詳細信息到日誌文件
$VerbosePreference = "Continue"
Write-Verbose "$(Get-Date): 腳本啓動..."
# ... 腳本邏輯 ...
腳本中使用斷點
根據行進行斷點
可使用 Set-PSBreakPoint cmdlet 設置斷點
可以基於腳本行、正在使用的特定命令或正在使用的特定變量來設置斷點
以下示例描述如何在腳本的特定行處設置斷點:
Set-PSBreakPoint -Script "MyScript.ps1" -Line 23
根據命令進行斷點
Set-PSBreakPoint -Command "Set-ADUser" -Script "MyScript.ps1"
基於命令設置斷點時,可以包含通配符。 例如,可以使用值 *-ADUser 為 Get-ADUser、Set-ADUser、New-ADUser 和 Remove-ADUser 觸發斷點。
根據特定變量進行斷點
Set-PSBreakPoint -Variable "computer" -Script "MyScript.ps1" -Mode ReadWrite
可以使用變量的 -Mode 參數來確定是否要在讀取和/或寫入變量值時中斷。 有效值為 Read、Write 和 ReadWrite。
以上是終端中運行腳本的時候設置的斷點,其實我們可以用:
- Powershell ISE 圖形化工具進行根據行去斷點
- VScode 中也能夠進行更多高級的斷點方式
錯誤操作
$ErrorActionPreference
內置全局變量。 當命令生成非終止錯誤時,命令會檢查此變量來決定該執行的操作
變量可具有下面 4 個可能值之一:
- Continue 是默認值,它告知命令顯示錯誤消息並繼續運行。
- SilentlyContinue 告知命令不顯示錯誤消息,但要繼續運行。
- Inquire 告知命令顯示提示,詢問用户要做什麼。
- Stop 告知命令將錯誤視為終止錯誤並停止運行。
若要設置 $ErrorActionPreference 變量,請使用以下語法:
$ErrorActionPreference = 'Inquire'
-ErrorAction
所有 Windows PowerShell 命令都有 –ErrorAction 參數。 此參數具有別名 –EA
當你使用他的時候,會覆蓋$ErrorActionPreference但可以設置一樣的類型,該參數僅針對當前使用的cmdlet
函數與模塊
有參函數:
Function Get-SecurityEvent {
Param (
[string]$ComputerName
) #end Param
Get-EventLog -LogName Security -ComputerName $ComputerName -Newest 10
}
無參函數就很簡單了,不寫接受參數的變量即可
函數調用如下:
Get-SecurityEvent -ComputerName LON-DC1
變量範圍
使用範圍修飾符 (Scope Modifiers) 指定目標作用域
這是修改其他作用域中變量的關鍵方法。通過在變量名前加修飾符來指定目標作用域
| 修飾符 | 作用 | 語法示例 | 説明 |
|---|---|---|---|
$global: |
修改全局作用域中的變量。 | $global:MyVariable = "新值" |
在任何地方(函數、腳本)都能訪問和修改這個全局變量。慎用,容易造成污染。 |
$script: |
修改腳本作用域中的變量。 | $script:MyVariable = "新值" |
在當前腳本文件的任何函數內部修改在腳本頂層定義的變量。這是最常用、最安全的方式。 |
$using: |
在遠程命令或腳本塊中引用當前局部作用域的變量。 | Invoke-Command { ... -Name $using:LocalVar } |
用於將本地變量的值傳遞到遠程會話或新腳本塊中,而不是在遠程會話中修改它。 |
$private: |
在當前作用域創建變量,且該變量不會傳遞到更高級的作用域。 | $private:TempVar = "值" |
用於限制變量範圍,確保其不會影響父作用域。較少用。 |
示例:
假設您在腳本頂層定義了 $configPath,現在需要在一個函數裏修改它:
Set-Variable指定作用域
Set-Variable -Name "MyVariable" -Value "新的值" -Scope <ScopeName>
-Scope 參數值:
'Global': 修改全局作用域。'Script': 修改腳本作用域。'Local': 修改當前局部作用域(默認值)。'Private': 修改為私有作用域。
絕大多數情況下,您應該使用 $script: 修飾符
這是在函數內修改腳本級變量的最標準、最可讀且副作用最小的方式。
類似指針修改
使用[ref]去拿到真實的那個變量在函數裏面去修改,而不是説每次修改的都是函數內部接受到的值,他會直接影響到函數外部那個傳進來的變量的值
function Modify-ByReference {
param (
[ref]$RefValue
)
$RefValue.Value = "在函數內部被修改了" # 注意:是修改 .Value 屬性
}
$OriginalVariable = "原始值"
Modify-ByReference -RefValue ([ref]$OriginalVariable)
Write-Host $OriginalVariable # 輸出:在函數內部被修改了
但是我們是避免這樣去修改變量的,要改的話最好是通過return返回值,然後在函數外部去改變某個變量
return
好像沒啥好説的,就是return值
function xxx{
xxx
return($var) # return "xxx" return $var
}
$ch = xxx()
創建模塊
你必須創建與該文件同名的子文件夾,並將文件放在該子文件夾中
例如,如果你有一個名為 AdatumFunctions.psm1 的模塊,
則將其放置在 C:\Program Files\WindowsPowerShell\Modules\AdatumFunctions 中。