PowerShell、私の経隓のダンプ

はじめに


この蚘事は、PowerShellの基本に既に粟通し、stackexchangeでいく぀かのスクリプトを実行し、おそらく日垞の䜜業を容易にするためのさたざたなスニペットを含む独自のテキストファむルを持っおいる人を察象ずしおいたす。 これを曞く目的は、゚ントロピヌを枛らし、䌚瀟で䜿甚されおいるPowerShellコヌドの可読性ず保守性を高め、その結果、それを䜿甚する管理者の生産性を高めるこずです。


kdpv


以前の仕事の堎所では、タスクの詳现ず䞖界の䞍完党さのために、PowerShellで䜜業するスキルを倧いに掻気づけたした。 䜜業の倉曎埌、この皮の負荷は劇的に枛少し、指の角を曲がったずころにあるものはすべお、新しい技術で新しい問題を解決する経隓の䞋でたすたす深く沈み始めたした。 このこずから、この蚘事はそれ自䜓が宣蚀しおいるこずだけを䞻匵しおおり、私の意芋では、このツヌルの知り合いが始たったばかりの玄7幎前に自分にずっお圹立぀トピックのリストを明らかにしおいたす。


PowerShellがオブゞェクト指向シェルである理由、これから埗られるボヌナス、およびなぜそれが必芁なのかを理解しおいない堎合、嫌悪感の叫びにもかかわらず、この環境の本質をすばやく玹介する良い本をお勧めしたす-Andrey Vladimirovich Popov、Introduction to Windows PowerShell 。 はい、それは叀いバヌゞョンのPSに぀いおです、はい、蚀語はいく぀かの拡匵ず改善を獲埗したしたが、この環境の開発の初期段階を説明するずき、それは基本的なこずだけを無意識に匷調するので、この本は良いです。 環境が倧きくなりすぎた構文糖は、抂念がどのように機胜するかを理解するこずなく、すぐにそれを知芚したす。 この本を読むず、文字通り数晩の倕べになり、読んだ埌に戻っおきたす。


ポポフ


本は著者のりェブサむトでも入手できたすが、この䜿甚がどのようにラむセンスされおいるかはわかりたせん https : //andpop.ru/courses/winscript/books/posh_popov.pdf


スタむルガむド


スタむルガむドに埓っおスクリプトを蚭蚈するこずは、その適甚のすべおの堎合においお良い習慣であり、2぀の意芋はほずんどあり埗たせん。 いく぀かの゚コシステムはネむティブチュヌニングのレベルでこれを凊理しおおり、Pythonコミュニティではpep8、Golangではgo fmtが明らかになりたす。 これらは非垞に貎重な時間節玄ツヌルであり、残念ながら、暙準のPowerShellパッケヌゞには存圚しないため、問題を頭に移したす。 珟圚、統䞀されたコヌドフォヌマットの問題を解決する唯䞀の方法は、スタむルガむドを満たすコヌドを繰り返し蚘述するこずで反射神経を開発するこずです実際、いいえ。


Microsoftによっお公匏に承認され、詳现に説明されおいないためのスタむルガむドは、PowerShell v3の時代にコミュニティで誕生し、それ以来githubのオヌプンフォヌムで開発されおいたす PowerShellPracticeAndStyle 。 これは、PowerShell iseで「保存」ボタンを䜿甚したこずがある人にずっお泚目すべきリポゞトリです。


スクむヌズを行おうずするず、おそらく次の点になりたす。



コメントベヌスのヘルプ


以䞋は、ヘルプスクリプトを取埗する方法の䟋です。 スクリプトは、画像を四角にし、サむズを倉曎したす。ナヌザヌのアバタヌを䜜成するタスクがあるず思いたすおそらくexifデヌタに埓った回転を陀く。 .EXAMPLEセクションに䜿甚䟋がありたす。詊しおください。 PowerShellは、他のドットネット蚀語ず同様に、共通蚀語ランタむムによっお実行されるため、ドットネットラむブラリのすべおの機胜を䜿甚できたす。


 <# .SYNOPSIS Resize-Image resizes an image file .DESCRIPTION This function uses the native .NET API to crop a square and resize an image file .PARAMETER InputFile Specify the path to the image .PARAMETER OutputFile Specify the path to the resized image .PARAMETER SquareHeight Define the size of the side of the square of the cropped image. .PARAMETER Quality Jpeg compression ratio .EXAMPLE Resize the image to a specific size: .\Resize-Image.ps1 -InputFile "C:\userpic.jpg" -OutputFile "C:\userpic-400.jpg"-SquareHeight 400 #> # requires -version 3 [CmdletBinding()] Param( [Parameter( Mandatory )] [string]$InputFile, [Parameter( Mandatory )] [string]$OutputFile, [Parameter( Mandatory )] [int32]$SquareHeight, [ValidateRange( 1, 100 )] [int]$Quality = 85 ) # Add System.Drawing assembly Add-Type -AssemblyName System.Drawing # Open image file $Image = [System.Drawing.Image]::FromFile( $InputFile ) # Calculate the offset for centering the image $SquareSide = if ( $Image.Height -lt $Image.Width ) { $Image.Height $Offset = 0 } else { $Image.Width $Offset = ( $Image.Height - $Image.Width ) / 2 } # Create empty square canvas for the new image $SquareImage = New-Object System.Drawing.Bitmap( $SquareSide, $SquareSide ) $SquareImage.SetResolution( $Image.HorizontalResolution, $Image.VerticalResolution ) # Draw new image on the empty canvas $Canvas = [System.Drawing.Graphics]::FromImage( $SquareImage ) $Canvas.DrawImage( $Image, 0, -$Offset ) # Resize image $ResultImage = New-Object System.Drawing.Bitmap( $SquareHeight, $SquareHeight ) $Canvas = [System.Drawing.Graphics]::FromImage( $ResultImage ) $Canvas.DrawImage( $SquareImage, 0, 0, $SquareHeight, $SquareHeight ) $ImageCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object MimeType -eq 'image/jpeg' # https://msdn.microsoft.com/ru-ru/library/hwkztaft(v=vs.110).aspx $EncoderQuality = [System.Drawing.Imaging.Encoder]::Quality $EncoderParameters = New-Object System.Drawing.Imaging.EncoderParameters( 1 ) $EncoderParameters.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter( $EncoderQuality, $Quality ) # Save the image $ResultImage.Save( $OutputFile, $ImageCodecInfo, $EncoderParameters ) 

䞊蚘のスクリプトは耇数行のコメント<# ... #>で始たり、このコメントが最初に来お特定のキヌワヌドが含たれおいる堎合、PowerShellはスクリプトのヘルプを自動的に䜜成したす。 この皮のヘルプは文字通り呌ばれたす- コメントに基づくヘルプ 


助けお


さらに、スクリプトが呌び出されるず、PowerShellコン゜ヌルであれコヌド゚ディタヌであれ、パラメヌタヌのツヌルチップが機胜したす。


むンンラむンヘルプ


もう䞀床、私は圌女が無芖されるべきではないずいう事実に泚意を匕きたす。 あなたがそこに䜕を曞くべきかわからない堎合は、䜕かを曞いお、クヌラヌに行き、戻ったずきに、曞かれたもので䜕を倉曎する必芁があるかを確実に理解するでしょう。 動䜜したす。 すべおのキヌワヌドを熱狂的に入力しないでください.SYNOPIS自己文曞化するように蚭蚈されおおり、パラメヌタヌに意味のあるフルネヌムを付けた堎合、 .SYNOPISセクションの短い文ず1぀の䟋で十分です。


厳栌モヌド


PowerShellは、他の倚くのスクリプト蚀語ず同様に、動的型付けを備えおいたす。 このタむプのタむピングには倚くの支持者がいたすシンプルだが匷力な高レベルのロゞックを曞くこずは数分で完了したすが、決定が千行に達するず、このアプロヌチの脆匱性に必ず遭遇したす。


垞に芁玠のセットを受け取る堎所に配列を圢成したテスト段階で型を自動的に出力するず、1぀の芁玠を取埗し、次の条件で芁玠の数をチェックする代わりに、文字の数たたは別の属性を取埗したすアむテムのタむプ。 スクリプトのロゞックが壊れ、ランタむムはすべおが正垞であるず芋せかけたす。


ストリクトモヌドを蚭定するず、この皮の問題を回避できたすが、倉数の初期化や明瀺的なキャストなど、もう少しコヌドを远加する必芁がありたす。


このモヌドはSet-StrictMode -Version Latestコマンドレットによっお有効になりたすが、「厳栌さ」には他のオプションがありたすが、私の遞択は埌者を䜿甚するこずです。


以䞋の䟋では、strictモヌドは存圚しないプロパティぞの呌び出しをキャッチしたす。 フォルダヌ内には芁玠が1぀しかないため、実行の結果ずしおの$Input倉数の型はFileInfoになり、察応する芁玠の予想される配列ではありたせん。


厳しい


このような問題を回避するには、コマンドレットの結果を明瀺的に配列にキャストする必芁がありたす。


 $Items = @( Get-ChildItem C:\Users\snd3r\Nextcloud ) 

垞に厳栌モヌドを蚭定するこずをルヌルにしおください。これにより、スクリプトの実行による予期しない結果を回避できたす。


゚ラヌ凊理


ErrorActionPreference


他の人のスクリプト、たずえばgithubを調べるず、゚ラヌ凊理メカニズムを完党に無芖するか、゚ラヌが発生した堎合に継続操䜜のサむレントモヌドを明瀺的にアクティブにするこずがよくありたす。 ゚ラヌ凊理の問題は、䞀般に、特にスクリプトでプログラミングするのが最も簡単ではありたせんが、間違いなく無芖するに倀するものではありたせん。 デフォルトでは、゚ラヌが発生した堎合のPowerShellぱラヌを衚瀺しお動䜜し続けたす抂念を少し簡略化したしたが、このトピックに関するgitブックぞのリンクです。 これは、ドメむンで広く䜿甚されおいるプログラムの曎新プログラムをすべおのマシンに緊急に配垃する必芁がある堎合に䟿利です。すべおのsccm展開ポむントに広がるか、ナヌザヌが䜿甚する別の方法で広がるたで埅぀必芁はありたせん。 マシンの1぀がオフになっおいる堎合、プロセスを䞭断しお再起動するのは䞍快です。これは事実です。


䞀方、情報システムの耇数の郚分の耇数のデヌタファむルで構成されるシステムの耇雑なバックアップを䜜成する堎合、バックアップの䞀貫性ず、必芁なすべおのデヌタセットが゚ラヌなしでコピヌされたこずを確認する必芁がありたす。


゚ラヌが発生した堎合のコマンドレットの動䜜を倉曎するには、グロヌバル倉数$ErrorActionPreferenceがあり、次の倀のリストがありたす Stop、Inquire、Continue、Suspend、SilentContinue 。


スクリプトの数たたはその耇雑さが頭のスタックに保存されなくなった堎合は、垞にStop倀を䜿甚するこずをお勧めしたす。予期せぬ状況では、スクリプトが動䜜を停止し、fireを「静かに」䞭断せず、実行が「正垞に」終了するこずを確認するこずをお勧めしたす。


䜕か問題が発生した堎合にスクリプトを停止するこずに加えお、その䜿甚には別の前提条件がありたす-䟋倖的な状況を凊理したす。 これにはtry/catchコンストラクトがありたすが、゚ラヌにより実行が停止した堎合にのみ機胜したす。 スクリプト党䜓のレベルで停止を有効にする必芁はありたせんErrorActionは、パラメヌタヌを䜿甚しおコマンドレットレベルで蚭定するこずErrorActionできたす。


 Get-ChildItem 'C:\System Volume Information\' -ErrorAction 'Stop' 

実際、この可胜性は2぀の論理的な戊略を定矩したす。すべおの゚ラヌを「デフォルトで」解決し、゚ラヌを凊理する重芁な堎所にのみErrorActionを蚭定したす。 グロヌバル倉数の倀を蚭定しお、スクリプト党䜓のレベルで有効にするか、重芁でない操䜜で-ErrorAction 'Continue'を蚭定したす。 私は垞に2番目のオプションを遞択したす。急いであなたに課すこずはありたせん。この問題を理解し、この䟿利なツヌルを䜿甚するのは1回だけにするこずをお勧めしたす


詊し/キャッチ


゚ラヌハンドラヌでは、䟋倖の皮類ごずに䞀臎させ、実行のスレッドで操䜜したり、たずえば、もう少し情報を远加したりできたす。 try/catch/throw/trap挔算子を䜿甚するず、スクリプト実行のフロヌ党䜓を構築できたすが、実行を䌎うこのような方法は「goto-noodle」カテゎリの極端なアンチパタヌンず芋なされるだけではないため、これを明確に回避する必芁がありたす。たた、パフォヌマンスが倧幅に䜎䞋したす。


 #requires -version 3 $ErrorActionPreference = 'Stop' #   ,    , #          $Logger = Get-Logger "$PSScriptRoot\Log.txt" #    trap { $Logger.AddErrorRecord( $_ ) exit 1 } #    $count = 1; while ( $true ) { try { #   $StorageServers = @( Get-ADGroupMember -Identity StorageServers | Select-Object -Expand Name ) } catch [System.Management.Automation.CommandNotFoundException] { #      ,         throw " Get-ADGroupMember ,    Active Directory module for PowerShell; $( $_.Exception.Message )" } catch [System.TimeoutException] { #             if ( $count -le 3 ) { $count++; Start-Sleep -S 10; continue } #             throw "     -   ,   $count ; $( $_.Exception.Message )" } #         break } 

trap挔算子はグロヌバル゚ラヌトラップであるこずに泚意しおください。 䞋䜍レベルで凊理されおいないすべおのものをキャッチするか、状況を個別に修正できないために䟋倖ハンドラヌからスロヌされたす。


䞊蚘の䟋倖のオブゞェクト指向のアプロヌチに加えお、PowerShellは、゚ラヌフロヌ、リタヌンコヌド、゚ラヌ环積倉数など、他の「クラシック」シェルず互換性のあるより銎染みのある抂念も提䟛したす。 これは確かに䟿利で、時には争われないこずもありたすが、党䜓ずしおこのトピックの範囲を超えおいたす。 幞いなこずに、このテヌマに関するgithubの良い本がありたす。


ロガヌのコヌドは、システムにPowerShell 5ロガヌクラスをより䟿利に蚘述するこずができるがあるずいう確信がない堎合に䜿甚したす。詊しおみおください。そのシンプルさず簡朔さから、圹に立぀こずがありたす。远加のメ゜ッドを簡単に远加できたす。 


 #   " ",   PowerShell v3 function Get-Logger { [CmdletBinding()] param ( [Parameter( Mandatory = $true )] [string] $LogPath, [string] $TimeFormat = 'yyyy-MM-dd HH:mm:ss' ) $LogsDir = [System.IO.Path]::GetDirectoryName( $LogPath ) New-Item $LogsDir -ItemType Directory -Force | Out-Null New-Item $LogPath -ItemType File -Force | Out-Null $Logger = [PSCustomObject]@{ LogPath = $LogPath TimeFormat = $TimeFormat } Add-Member -InputObject $Logger -MemberType ScriptMethod AddErrorRecord -Value { param( [Parameter( Mandatory = $true )] [string]$String ) "$( Get-Date -Format 'yyyy-MM-dd HH:mm:ss' ) [Error] $String" | Out-File $this.LogPath -Append } return $Logger } 

私はこの考えを繰り返したす-゚ラヌ凊理を無芖しないでください。 これは長期的にあなたの時間ず神経を節玄したす。
䜕があっおもスクリプトを実行するずは思わないでください。 良い-itを壊さずに萜ちる時です。


ツヌル


PowerShellを䜿甚するためのツヌルの改善を開始するには、間違いなくコン゜ヌル゚ミュレヌタヌを䜿甚する必芁がありたす。 代わりのスズメバチの支持者から、Windowsのコン゜ヌルが悪いこず、これはたったくコン゜ヌルではなく、dosなどであるずよく耳にしたした。 この䞻題に関する䞻匵を適切に定匏化するこずはできたせんでしたが、誰かが成功した堎合、実際にはすべおの問題を解決できるこずが刀明したした。 端末ずハブのりィンドりには新しいコン゜ヌルに関する情報がすでにありたしたが、 すべおがそこにありたす。


最初のステップはConemuたたはそのCmderアセンブリをむンストヌルするこずです。これは特に重芁ではありたせん。ずにかく蚭定を怜蚎する䟡倀があるからです。 私は通垞、gitaや他のバむナリを䜿甚せずに、最小限の構成でcmderを遞択したす。数幎の間、玔粋なConemuの構成を調敎したした。 これは本圓にりィンドり甚の最高のタヌミナル゚ミュレヌタで、画面を分割tmux /スクリヌンが奜きな人向け、タブを䜜成、地震スタむルのコン゜ヌルモヌドを有効にできたす。


コネム


cmder


モゞュヌルを配眮するこずをお勧めする次のステップ oh-my-posh 、 posh-git 、およびPSReadLine 。 最初の2぀は、珟圚のセッション、最埌に実行されたコマンドのステヌタス、特暩むンゞケヌタヌ、および珟圚の堎所のgitリポゞトリのステヌタスに関する情報を远加するこずにより、promをより快適にしたす。 PSReadLineは、入力されたコマンドの履歎CRTL + Rの怜玢や、CRTL + Spaceのコマンドレットの䟿利なヒントなどを远加しお、プロンプトを倧幅に向䞊させたす。


readline


そしお、はい、CTRL + Lでコン゜ヌルをクリアでき、 clsを忘れるこずができたす。


ビゞュアルスタゞオコヌド


゚ディタヌ。 PowerShellに぀いお私が蚀える最悪のこずは、玔粋にPowerShell ISEです。3぀のパネルを持぀最初のバヌゞョンを芋た人は、この経隓を忘れるこずはほずんどありたせん。 タヌミナルの異なる゚ンコヌディング、自動むンデント、自動クロヌズブラケット、コヌドの曞匏蚭定、生成されたアンチパタヌンのセットなど、基本的な゚ディタヌ機胜の欠劂これはISEに぀いおです。


䜿甚しないでください。PowerShell拡匵機胜を備えたVisual Studio Codeを䜿甚しおください-必芁のないものはすべおありたすもちろん、合理的な制限内です。 たた、6番目のバヌゞョンPowerShell Core 6.0より前のPoweShellでは、スクリプトの゚ンコヌドがUTF8 BOMであるこずを忘れないでください。そうしないずロシア語が壊れたす。


vscode


プラグむンは、構文の匷調衚瀺、ツヌルのヒント、およびスクリプトのデバッグ機胜に加えお、コミュニティで確立された慣習に埓うのに圹立぀リンタヌをむンストヌルしたす。たずえば、ワンクリックで電球䞊でショヌトカットを展開したす。 実際、これは独立しおむンストヌルできる通垞のモゞュヌルです。たずえば、パむプラむン眲名スクリプトに远加できたす PSScriptAnalyzer


PSScriptAnalyzer


拡匵機胜の蚭定でコヌドの曞匏蚭定パラメヌタヌを蚭定できたす。すべおの蚭定゚ディタヌず拡匵機胜の䞡方に察しお、怜玢がありたす File - Preferences - Settings 


Otbs


新しいconptyコン゜ヌルを取埗するには、蚭定でフラグを蚭定する必芁がありたす 。おそらく、このアドバむスは関係ないでしょう。


VS Codeのすべおのアクションは、Ctrl + Shift + Pで呌び出されるコントロヌルセンタヌから実行できるこずを芚えおおく䟡倀がありたす。 チャットから挿入されたコヌドをフォヌマットし 、行をアルファベット順に䞊べ替え、むンデントをスペヌスからタブに倉曎するなど、これはすべおコントロヌルセンタヌにありたす。


たずえば、党画面衚瀺をオンにしお゚ディタヌを䞭倮に配眮したす。


レむアりト


゜ヌス管理 Git、SVN


倚くの堎合、Windowsシステム管理者はバヌゞョン管理システムの競合解決に恐怖心を抱いおいたす。これはおそらく、このセットの代衚者がgitを䜿甚する堎合、この皮の問題が発生しないこずが倚いためです。 vscodeを䜿甚するず、競合の解決は、コヌドの残りの郚分たたは眮き換える必芁のある郚分での文字通りのマりスクリックに限定されたす。


䜵合する


303行ず304行の間のこれらの碑文はクリック可胜です。競合が発生した堎合にドキュメントに衚瀺されるすべおをクリックし、倉曎をコミットしおサヌバヌに倉曎を送信する䟡倀がありたす。 U-利䟿性。


バヌゞョン管理システムの操䜜方法ず、vscode dockで曞かれた写真を䜿甚する方法に぀いおは、そこを簡単に確認しおください。


スニペット


スニペットは、コヌドの蚘述を高速化できる䞀皮のマクロ/テンプレヌトです。 間違いなく必芋です。


オブゞェクトの迅速な䜜成


カスタムオブゞェクト


コメントベヌスのヘルプの魚


助けお


コマンドレットが倚数のパラメヌタヌを枡す必芁がある堎合は、 splattingを䜿甚するのが理にかなっおいたす 。
これが圌のスニペットです。


飛び散る


Ctrl + Alt + Jで䜿甚可胜なすべおのスニペットを衚瀺したす。


スニペット


その埌、呚囲の環境を改善し続けたいず思っおいたが、 wasp-lists nirazuに぀いお聞いたこずがない堎合は、ここにいたす 。 たた、PowerShellスクリプトを䜜成するずきに䟿利な独自の拡匵機胜セットがある堎合は、コメントにそのリストが衚瀺されおうれしいです。


性胜


パフォヌマンスのトピックは、䞀芋するず思えるほど単玔ではありたせん。 䞀方で、時期尚早な最適化により、コヌドの可読性ず保守性が倧幅に䜎䞋し、スクリプト実行時間が300ミリ秒節玄されたす。通垞の実行時間は10分であり、この堎合の䜿甚は間違いなく砎壊的です。 䞀方、コヌドの可読性ず操䜜の速床の䞡方を向䞊させるいく぀かの非垞に単玔なトリックがあり、これらは継続的に䜿甚するのに非垞に適切です。 以䞋にそれらのいく぀かに぀いお説明したすが、パフォヌマンスがあなたにずっおすべおであり、メンテナンス䞭のサヌビスのダりンタむムの厳しい時間制限のために読みやすさが途䞭である堎合は、 専門の文献を参照するこずをお勧めしたす。


パむプラむンずforeach


生産性を高める最も簡単で垞に機胜する方法は、パむプの䜿甚を避けるこずです。 型の安党性ずPowerShellのための䜜業の利䟿性により、芁玠をパむプに枡すず、各芁玠がオブゞェクトにラップされたす。 ドットネット蚀語では、この動䜜はボクシングず呌ばれたす。 ボクシングは良いです、それはセキュリティを保蚌したすが、それはそれ自身の䟡栌を持っおいたす、それは時々支払う意味がありたせん。


最初のステップは、 Foreach-Objectすべおのアプリケヌションを削陀し、foreachステヌトメントに眮き換えるこずにより、生産性を向䞊させ、読みやすさを向䞊させるこずです。 foreachはForeach-Object゚むリアスであるため、これらは実際には2぀の異なる゚ンティティであるずいう事実に混乱する可胜性がありたす-実際には、䞻な違いはforeachはパむプラむンから倀を受け入れず、同時に最倧3倍の速床で動䜜するこずです。


問題を想像しおください。たずえば、倧きなログを凊理しおその掟生物を䜜成する必芁がありたす。たずえば、その䞭の䞀連の゚ントリを遞択しお別の圢匏にする必芁がありたす。


 Get-Content D:\temp\SomeHeavy.log | Select-String '328117' 

䞊蚘の䟋では、タスクの最初の段階-必芁なレコヌドの遞択が最もわかりやすい方法で合栌したした。これは認知の容易さず衚珟力に優れおいたす。同時に、生産性を倧幅に䜎䞋させる堎所、぀たりパむプラむンが含たれおいたす。たたは、パむプラむン自䜓が原因ではなく、コマンドレットの動䜜であるず蚀われたすGet-Content。パむプラむンでデヌタを転送するには、ファむルを1行ず぀読み取り、ログの各行をベヌスタむプからstringオブゞェクトにラップし、サむズを倧幅に増やし、キャッシュ内のデヌタの局所性を枛らし、本圓に必芁な䜜業を行いたせん。これを回避するには簡単です。このデヌタを䞀床に完党に読み取る必芁があるこずをパラメヌタヌで瀺す必芁がありたす。


When reading from and writing to binary files, use the AsByteStream parameter and a value of 0 for the ReadCount parameter. A ReadCount value of 0 reads the entire file in a single read operation. The default ReadCount value, 1, reads one byte in each read operation and converts each byte into a separate object, which causes errors when you use the Set-Content cmdlet to write the bytes to a file unless you use AsByteStream

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content

 Get-Content D:\temp\SomeHeavy.log -ReadCount 0 | Select-String '328117' 

:


リヌドカりント


, . Select-String — . , Select-String . , Select-String , , :


 foreach ( $line in ( Get-Content D:\temp\SomeHeavy.log -ReadCount 0 )) { if ( $line -match '328117' ) { $line } } 

30 , - 30%, , , , - , ( ;-). , . , -match ; — . , — — - , .


— - , " " :


 foreach ( $line in ( Get-Content D:\temp\SomeHeavy.log -ReadCount 0 )) { if ( $line -match '328117' ) { "$( Get-Date -UFormat '%d.%m.%Y %H:%M:%S') $line" | Out-File D:\temp\Result.log -Append } } 

Measure-Command :


 Hours : 2 Minutes : 20 Seconds : 9 Milliseconds : 101 

. , , , . , PowerShell , , — . , , — StringBuilder . , , . , .


 $StringBuilder = New-Object System.Text.StringBuilder foreach ( $line in ( Get-Content D:\temp\SomeHeavy.log -ReadCount 0 )) { if ( $line -match '328117' ) { $null = $StringBuilder.AppendLine( "$( Get-Date -UFormat '%d.%m.%Y %H:%M:%S') $line" ) } } Out-File -InputObject $StringBuilder.ToString() -FilePath D:\temp\Result.log -Append -Encoding UTF8 

5 , :


 Hours : 0 Minutes : 5 Seconds : 37 Milliseconds : 150 

Out-File -InputObject , , . — . — Get-Help -Full , Accept pipeline input? true (ByValue) :


 -InputObject <psobject> Required? false Position? Named Accept pipeline input? true (ByValue) Parameter set name (All) Aliases None Dynamic? false 

PowerShell :


taskmgr


StringBuilder :


stringbuilder alloc


, , 3 3. dotnet- — StreamReader .


 $StringBuilder = New-Object System.Text.StringBuilder $StreamReader = New-Object System.IO.StreamReader 'D:\temp\SomeHeavy.log' while ( $line = $StreamReader.ReadLine()) { if ( $line -match '328117' ) { $null = $StringBuilder.AppendLine( "$( Get-Date -UFormat '%d.%m.%Y %H:%M:%S') $line" ) } } $StreamReader.Dispose() Out-File -InputObject $StringBuilder.ToString() -FilePath C:\temp\Result.log -Append -Encoding UTF8 

 Hours : 0 Minutes : 5 Seconds : 33 Milliseconds : 657 

, . , , , , 2. , :


ストリヌムリヌダヌ


— "", — StringBuilder — "" . , ( 100) . — 90% ( , ):


 $BufferSize = 104857600 $StringBuilder = New-Object System.Text.StringBuilder $BufferSize $StreamReader = New-Object System.IO.StreamReader 'C:\temp\SomeHeavy.log' while ( $line = $StreamReader.ReadLine()) { if ( $line -match '1443' ) { #      if ( $StringBuilder.Length -gt ( $BufferSize - ( $BufferSize * 0.1 ))) { Out-File -InputObject $StringBuilder.ToString() -FilePath C:\temp\Result.log -Append -Encoding UTF8 $StringBuilder.Clear() } $null = $StringBuilder.AppendLine( "$( Get-Date -UFormat '%d.%m.%Y %H:%M:%S') $line" ) } } Out-File -InputObject $StringBuilder.ToString() -FilePath C:\temp\Result.log -Append -Encoding UTF8 $StreamReader.Dispose() 

 Hours : 0 Minutes : 5 Seconds : 53 Milliseconds : 417 

1 :


ダンプ付きストリヌムリヌダヌ


, . , , StreamWriter , , ;-) , , .


- — , . , — . Select-String Out-File , OutOfMemoryException , — .



, PowerShell , — , : PowerShell — , .


, StringBuilder dir — ( ). :


 $CurrentPath = ( Get-Location ).Path + '\' $StringBuilder = New-Object System.Text.StringBuilder foreach ( $Line in ( &cmd /c dir /b /s /ad )) { $null = $StringBuilder.AppendLine( $Line.Replace( $CurrentPath, '.' )) } $StringBuilder.ToString() 

 Hours : 0 Minutes : 0 Seconds : 3 Milliseconds : 9 

 $StringBuilder = New-Object System.Text.StringBuilder foreach ( $Line in ( Get-ChildItem -File -Recurse | Resolve-Path -Relative )) { $null = $StringBuilder.AppendLine( $Line ) } $StringBuilder.ToString() 

 Hours : 0 Minutes : 0 Seconds : 16 Milliseconds : 337 

$null — . , — Out-Null ; , ( $null ) , .


 # : $null = $StringBuilder.AppendLine( $Line ) # : $StringBuilder.AppendLine( $Line ) | Out-Null 

, , . Compare-Object , , , . robocopy.exe, ( PowerShell 5), :


 class Robocopy { [String]$RobocopyPath Robocopy () { $this.RobocopyPath = Join-Path $env:SystemRoot 'System32\Robocopy.exe' if ( -not ( Test-Path $this.RobocopyPath -PathType Leaf )) { throw '    ' } } [void]CopyFile ( [String]$SourceFile, [String]$DestinationFolder ) { $this.CopyFile( $SourceFile, $DestinationFolder, $false ) } [void]CopyFile ( [String]$SourceFile, [String]$DestinationFolder, [bool]$Archive ) { $FileName = [IO.Path]::GetFileName( $SourceFile ) $FolderName = [IO.Path]::GetDirectoryName( $SourceFile ) $Arguments = @( '/R:0', '/NP', '/NC', '/NS', '/NJH', '/NJS', '/NDL' ) if ( $Archive ) { $Arguments += $( '/A+:a' ) } $ErrorFlag = $false &$this.RobocopyPath $FolderName $DestinationFolder $FileName $Arguments | Foreach-Object { if ( $ErrorFlag ) { $ErrorFlag = $false throw "$_ $ErrorString" } else { if ( $_ -match '(?<=\(0x[\da-f]{8}\))(?<text>(.+$))' ) { $ErrorFlag = $true $ErrorString = $matches.text } else { $Logger.AddRecord( $_.Trim()) } } } if ( $LASTEXITCODE -eq 8 ) { throw 'Some files or directories could not be copied' } if ( $LASTEXITCODE -eq 16 ) { throw 'Robocopy did not copy any files. Check the command line parameters and verify that Robocopy has enough rights to write to the destination folder.' } } [void]SyncFolders ( [String]$SourceFolder, [String]$DestinationFolder ) { $this.SyncFolders( $SourceFolder, $DestinationFolder, '*.*', '', $false ) } [void]SyncFolders ( [String]$SourceFolder, [String]$DestinationFolder, [Bool]$Archive ) { $this.SyncFolders( $SourceFolder, $DestinationFolder, '*.*', '', $Archive ) } [void]SyncFolders ( [String]$SourceFolder, [String]$DestinationFolder, [String]$Include ) { $this.SyncFolders( $SourceFolder, $DestinationFolder, $Include, '', $false ) } [void]SyncFolders ( [String]$SourceFolder, [String]$DestinationFolder, [String]$Include, [Bool]$Archive ) { $this.SyncFolders( $SourceFolder, $DestinationFolder, $Include, '', $Archive ) } [void]SyncFolders ( [String]$SourceFolder, [String]$DestinationFolder, [String]$Include, [String]$Exclude ) { $this.SyncFolders( $SourceFolder, $DestinationFolder, $Include, $Exclude, $false ) } [void]SyncFolders ( [String]$SourceFolder, [String]$DestinationFolder, [String]$Include, [String]$Exclude, [Bool]$Archive ) { $Arguments = @( '/MIR', '/R:0', '/NP', '/NC', '/NS', '/NJH', '/NJS', '/NDL' ) if ( $Exclude ) { $Arguments += $( '/XF' ) $Arguments += $Exclude.Split(' ') } if ( $Archive ) { $Arguments += $( '/A+:a' ) } $ErrorFlag = $false &$this.RobocopyPath $SourceFolder $DestinationFolder $Include $Arguments | Foreach-Object { if ( $ErrorFlag ) { $ErrorFlag = $false throw "$_ $ErrorString" } else { if ( $_ -match '(?<=\(0x[\da-f]{8}\))(?<text>(.+$))' ) { $ErrorFlag = $true $ErrorString = $matches.text } else { $Logger.AddRecord( $_.Trim()) } } } if ( $LASTEXITCODE -eq 8 ) { throw 'Some files or directories could not be copied' } if ( $LASTEXITCODE -eq 16 ) { throw 'Robocopy did not copy any files. Check the command line parameters and verify that Robocopy has enough rights to write to the destination folder.' } } } 

, ( ), — .


, : Foreach-Object !? , : foreach , Foreach-Object — , , , , . .


, :


 $Robocopy = New-Object Robocopy #    $Robocopy.CopyFile( $Source, $Dest ) #   $Robocopy.SyncFolders( $SourceDir, $DestDir ) #    .xml     $Robocopy.SyncFolders( $SourceDir, $DestDir , '*.xml', $true ) #     *.zip *.tmp *.log     $Robocopy.SyncFolders( $SourceDir, $DestDir, '*.*', '*.zip *.tmp *.log', $true ) 


— , , ; , , , :



: - , .


Jobs


, , , , , , . . , IO, .


ssd

これは、新しくむンストヌルされたHyper-VのWindows Server 2019からssdぞの最初のブヌトが行われる方法です仮想マシンのhddぞの移行によっお決定されたした。


2019ssd


PowerShell ( Get-Command *-Job ), .


, , , :


 $Job = Start-Job -ScriptBlock { Write-Output 'Good night' Start-Sleep -S 10 Write-Output 'Good morning' } $Job | Wait-Job | Receive-Job Remove-Job $Job 

, — , . .


, :


仕事
https://xaegr.wordpress.com/2011/07/12/threadping/


, , — , . , , (50 — 50 ):


仕事が死ぬ


. , — , . — , .


, , , - .


Runspaces


— Beginning Use of PowerShell Runspaces: Part 1 . , — PowerShell , . (, PowerShell ), : ( ) . , .


WPF , PowerShell, . — , . — , "" . .


, .


wpf


 #     $GUISyncHash = [hashtable]::Synchronized(@{}) <# WPF  #> $GUISyncHash.FormXAML = [xml](@" <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Sample WPF Form" Height="510" Width="410" ResizeMode="NoResize"> <Grid> <Label Content=" " HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="37" Width="374" FontSize="18"/> <Label Content="" HorizontalAlignment="Left" Margin="16,64,0,0" VerticalAlignment="Top" Height="26" Width="48"/> <TextBox x:Name="BackupPath" HorizontalAlignment="Left" Height="23" Margin="69,68,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="300"/> <Label Content="" HorizontalAlignment="Left" Margin="16,103,0,0" VerticalAlignment="Top" Height="26" Width="35"/> <TextBox x:Name="RestorePath" HorizontalAlignment="Left" Height="23" Margin="69,107,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="300"/> <Button x:Name="FirstButton" Content="√" HorizontalAlignment="Left" Margin="357,68,0,0" VerticalAlignment="Top" Width="23" Height="23"/> <Button x:Name="SecondButton" Content="√" HorizontalAlignment="Left" Margin="357,107,0,0" VerticalAlignment="Top" Width="23" Height="23"/> <CheckBox x:Name="Check" Content="  " HorizontalAlignment="Left" Margin="16,146,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.113,-0.267" Width="172"/> <Button x:Name="Go" Content="Go" HorizontalAlignment="Left" Margin="298,173,0,0" VerticalAlignment="Top" Width="82" Height="26"/> <ComboBox x:Name="Droplist" HorizontalAlignment="Left" Margin="16,173,0,0" VerticalAlignment="Top" Width="172" Height="26"/> <ListBox x:Name="ListBox" HorizontalAlignment="Left" Height="250" Margin="16,210,0,0" VerticalAlignment="Top" Width="364"/> </Grid> </Window> "@) <#   #> $GUISyncHash.GUIThread = { $GUISyncHash.Window = [Windows.Markup.XamlReader]::Load(( New-Object System.Xml.XmlNodeReader $GUISyncHash.FormXAML )) $GUISyncHash.Check = $GUISyncHash.Window.FindName( "Check" ) $GUISyncHash.GO = $GUISyncHash.Window.FindName( "Go" ) $GUISyncHash.ListBox = $GUISyncHash.Window.FindName( "ListBox" ) $GUISyncHash.BackupPath = $GUISyncHash.Window.FindName( "BackupPath" ) $GUISyncHash.RestorePath = $GUISyncHash.Window.FindName( "RestorePath" ) $GUISyncHash.FirstButton = $GUISyncHash.Window.FindName( "FirstButton" ) $GUISyncHash.SecondButton = $GUISyncHash.Window.FindName( "SecondButton" ) $GUISyncHash.Droplist = $GUISyncHash.Window.FindName( "Droplist" ) $GUISyncHash.Window.Add_SourceInitialized({ $GUISyncHash.GO.IsEnabled = $true }) $GUISyncHash.FirstButton.Add_Click( { $GUISyncHash.ListBox.Items.Add( 'Click FirstButton' ) }) $GUISyncHash.SecondButton.Add_Click( { $GUISyncHash.ListBox.Items.Add( 'Click SecondButton' ) }) $GUISyncHash.GO.Add_Click( { $GUISyncHash.ListBox.Items.Add( 'Click GO' ) }) $GUISyncHash.Window.Add_Closed( { Stop-Process -Id $PID -Force }) $null = $GUISyncHash.Window.ShowDialog() } $Runspace = @{} $Runspace.Runspace = [RunspaceFactory]::CreateRunspace() $Runspace.Runspace.ApartmentState = "STA" $Runspace.Runspace.ThreadOptions = "ReuseThread" $Runspace.Runspace.Open() $Runspace.psCmd = { Add-Type -AssemblyName PresentationCore, PresentationFramework, WindowsBase }.GetPowerShell() $Runspace.Runspace.SessionStateProxy.SetVariable( 'GUISyncHash', $GUISyncHash ) $Runspace.psCmd.Runspace = $Runspace.Runspace $Runspace.Handle = $Runspace.psCmd.AddScript( $GUISyncHash.GUIThread ).BeginInvoke() Start-Sleep -S 1 $GUISyncHash.ListBox.Dispatcher.Invoke( "Normal", [action] { $GUISyncHash.ListBox.Items.Add( '' ) }) $GUISyncHash.ListBox.Dispatcher.Invoke( "Normal", [action] { $GUISyncHash.ListBox.Items.Add( '  ' ) }) foreach ( $item in 1..5 ) { $GUISyncHash.Droplist.Dispatcher.Invoke( "Normal", [action] { $GUISyncHash.Droplist.Items.Add( $item ) $GUISyncHash.Droplist.SelectedIndex = 0 }) } $GUISyncHash.ListBox.Dispatcher.Invoke( "Normal", [action] { $GUISyncHash.ListBox.Items.Add( 'While ( $true ) { Start-Sleep -S 10 }' ) }) while ( $true ) { Start-Sleep -S 10 } 

WPF github, , smart : https://github.com/snd3r/GetDiskSmart/ . , MVVM:


ビンビン


Visual Studio, Community Edition , xaml- wpf — https://github.com/punker76/kaxaml


カクサム


結論の代わりに


PowerShell — Windows-. , , , .


, , "PowerShell, ", . , — , . . , - , - .


— .


萜ち着いた


PS Boomburumは、2019幎のPowerShell構文の匷調衚瀺をサポヌトしおいたせん-ダッシュ文字列。



Source: https://habr.com/ru/post/J443256/


All Articles