日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PowerShell runspace 的创建,使用和查错

發布時間:2025/5/22 编程问答 61 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PowerShell runspace 的创建,使用和查错 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天拜讀了The Scripting Guy關于runspace的幾篇大作,溫故而知新,一些忽略的地方更為清楚。

https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/26/beginning-use-of-powershell-runspaces-part-1/


runspace這兩年在PowerShell使用的頻率越來越高,由于他的高效率,基本上很多時候已經取代了傳統的Job后臺操作。不管是多線程實現,或者是后臺操作,亦或是***腳本,runspace 的性能可以是job的幾十倍以上。


現在由淺入深的看幾個例子,到底是怎么實現的。


例1 同步操作一個PowerShell實例


創建一個PowerShell的實例,然后添加一段代碼,然后invoke執行。


$PowerShell?=?[powershell]::Create() [void]$PowerShell.AddScript({Get-DateStart-Sleep?-Seconds?10 }) $PowerShell.Invoke()


注意幾點:

  • ?PowerShell不僅僅是一個腳本語言,我們可以通過這個類System.Management.Automation.PowerShell所提供的方法來創建實例,添加腳本和參數。

    Powershell 作為平臺的使用方法參考https://blogs.msdn.microsoft.com/powershell/2013/10/01/paap-windows-powershell-as-a-platform-part-1/


  • ?我使用了[void]的目的是避免輸出太多亂起八糟的信息(比如當前runspace的信息等等)來污染我的輸出結果?


  • ?我在這個腳本里面添加了一條等待10秒的命令,當我們執行invoke命令的時候,會看見屏幕上卡了10秒以后,才返回當前的時間。 這種同步的操作在執行多線程和后臺操作的時候應該避免,后面我們會說如何實現異步操作。



可以看見執行invoke之后直接返回了一個結果,事實上,這個和我直接在控制臺輸入Get-Date的效果一樣,這樣的腳本并不適合在后臺操作。


例2,異步操作Runspace和PowerShell實例。


$Runspace?=?[runspacefactory]::CreateRunspace() $PowerShell?=[powershell]::Create() $PowerShell.runspace?=?$Runspace $Runspace.Open() [void]$PowerShell.AddScript({Get-DateStart-Sleep?-Seconds?10 }) $AsyncObject?=?$PowerShell.BeginInvoke()


這一次,我們創建一個runspace的對象,然后把它綁定到一個PowerShell的實例中,運行這個runspace,然后和上面一樣,給這個PowerShell的實例添加腳本。請注意,一個很重要的改進是這里使用了BeginInvoke()方法,這個會返回一個異步的對象。異步和同步的區別在于,同步會死等在某個環節,直到輸出結果,而異步會自動切換出來,定期的檢查結果,等操作結束之后,再切換回去獲取結果。


一個簡單有趣的C#例子老王洗澡很生動了對比了同步和異步操作

http://www.cnblogs.com/lxblog/archive/2012/12/11/2813893.html


回到之前的腳本,我們來看看BeginInvoke返回的異步對象是什么樣。因為我設置了要等10秒鐘,所以可以看見他的IsComleted屬性是False


10秒鐘以后再查看,就已經變成True,這表示操作已經結束。


現在我們調用EndInvoke這個異步對象切換回去獲取結果


$Data?=?$PowerShell.EndInvoke($AsyncObject) $Data


成功獲取結果


最后別忘記關掉這個實例。

$PowerShell.Dispose()


例3 給PowerShell的平臺傳遞參數


$name?=?'James' $title?=?'Manager' $PowerShell?=[powershell]::Create() [void]$PowerShell.AddScript({Param?($Param1,?$Param2)[pscustomobject]@{Param1?=?$Param1Param2?=?$Param2} }).AddArgument($name).AddArgument($title) #Invoke?the?command $PowerShell.Invoke() $PowerShell.Dispose()

比如我定義了2個變量,我可以通過AddArgument來傳遞到腳本塊里,當然腳本塊里面也得定義對應的參數,然后按順序傳入變量。


例4 ?如果參數過多,我可以通過定義hash表和 addParameters來傳遞參數,這樣顯得更為簡潔。

$ParamList?=?@{param1?=?'Kevin'Param2?=?'receptionist' } $PowerShell?=?[powershell]::Create() [void]$PowerShell.AddScript({Param?($Param1,?$Param2)[pscustomobject]@{name?=?$Param1title?=?$Param2} }).AddParameters($ParamList) #Invoke?the?command $PowerShell.Invoke() $PowerShell.Dispose()



例5 ?整合上面的知識點,來個完整的例子,例如使用 runspace pool來實現多線程的Ping


這個是我之前寫過的一個例子。http://beanxyz.blog.51cto.com/5570417/1760880


$Throttle?=?20?#threads#腳本塊,對指定的計算機發送一個ICMP包測試,結果保存在一個對象里面,接收一個計算機名字的參數$ScriptBlock?=?{Param?([string]$Computer)$a=test-connection?-ComputerName?$Computer?-Count?1?$RunResult?=?New-Object?PSObject?-Property?@{IPv4Adress=$a.ipv4address.IPAddressToStringComputerName=$Computer}Return?$RunResult }#創建一個資源池,指定多少個runspace可以同時執行,這里表示最低1個,最多20個$RunspacePool?=?[RunspaceFactory]::CreateRunspacePool(1,?$Throttle) $RunspacePool.Open() $Jobs?=?@()#獲取Windows?2012服務器的信息,對每一個服務器單獨創建一個Powershell實例,每一個實例都異步的執行PING的操作,并把異步對象保存在Result里面 #最后把所有的結果都保存在一個Jobs的對象中。 #注意這里綁定的是RunspacePool,而不是單個的Runspace(get-adcomputer?-filter?{operatingsystem?-like?"*2012*"}).name?|?%?{#Start-Sleep?-Seconds?1$Job?=?[powershell]::Create().AddScript($ScriptBlock).AddArgument($_)$Job.RunspacePool?=?$RunspacePool$Jobs?+=?New-Object?PSObject?-Property?@{Server?=?$_Pipe?=?$JobResult?=?$Job.BeginInvoke()} }#循環輸出等待的信息....?直到所有的job都完成?Write-Host?"Waiting.."?-NoNewline Do?{Write-Host?"."?-NoNewlineStart-Sleep?-Seconds?1 }?While?(?$Jobs.Result.IsCompleted?-contains?$false) Write-Host?"All?jobs?completed!"#解鎖,輸出異步操作的結果? $Results?=?@() ForEach?($Job?in?$Jobs) {???$Results?+=?$Job.Pipe.EndInvoke($Job.Result) }$Results



例6, 最后看看來怎么debug runspace。 PowerShell 5 以后提供了一個命令 Debug-Runspace可以像普通的debug一樣來跟蹤當前執行的命令或者腳本。


先直接創建一個runspace,可以看見他的狀態是available

$rs=[runspacefactory]::CreateRunspace() $rs.name="MyRunSpace" $rs.open() get-runspace

把這個runspace綁定到一個powershell的實例,綁定某個腳本,異步執行


$ps=[powershell]::create() $ps.runspace=$rs $ps.addscript('C:\users\yli\documents\github\Powershell\Restart-WSUSComputers.ps1')?>?$null $async=$ps.BeginInvoke() get-runspace


可以看見他的狀態變成了busy


這個時候我們來debug一下

Debug-Runspace?Myrunspace


他自動就切換到我的腳本頁面了,按F10就會一行行的自動跟蹤執行下去了





如果需要終止debug,在控制臺輸入 detach 就可以了



參考資料


1.?https://blogs.msdn.microsoft.com/powershell/2015/09/08/powershell-runspace-debugging-part-1/

2.?https://blogs.msdn.microsoft.com/powershell/2013/10/01/paap-windows-powershell-as-a-platform-part-1/

3.?http://www.cnblogs.com/lxblog/archive/2012/12/11/2813893.html

4.?https://blogs.technet.microsoft.com/heyscriptingguy/2015/11/26/beginning-use-of-powershell-runspaces-part-1/


總結

以上是生活随笔為你收集整理的PowerShell runspace 的创建,使用和查错的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。