これは何
個人的なPowershell備忘録です。
思い出したり記事を探すのが手間だったりするものを中心に。
ディープな部分も含めてとりあえず記録しておこうと思ったものを追記予定。
特に明記してない場合はPowershell 7.x
の内容です。
未翻訳ドキュメント要約と私的補足
Powershellの未翻訳ドキュメントからあれこれ
知らなかったそんな機能……って沢山感じました。
About calculated properties
一部コマンドレットのproperties
パラメーターやGroupby
パラメータでは連想配列で手の込んだ処理が出来ます。
その解説。
連想配列のキー構成
-
name
/label
- 作成するプロパティの名前を指定する。どちらを使っても良い。 -
expression
- プロパティの値を計算するためのスクリプトブロックを指定する。 -
alignment
- 表形式の出力を生成するコマンドレットで、値が列にどのように表示されるかを定義するために使用する。値は'left'
、'center'
、または'right'
のいずれかでなければならない。 -
formatstring
- フォーマット文字列を指定する。文法は-f
演算子、[string]::Format
と同じ。 -
width
- カラムの幅を指定する。0より大きい数値を指定しなければならない。 -
depth
-Format-Custom
の-Depth
パラメータは全プロパティの展開深度を指定するが、depth
キーを使うと個別に深度を設定出来る。 -
ascending
/descending
- ソート順を指定する。boolean
値。
expression
のみが必須。連想配列ではなくScriptblock
を指定した場合はexpression
のみが指定される。
連想配列キーは他のPowershellのパラメータ指定と同様に被りが起きないところまで省略可能。
手打ちでは1文字だけで指定していく場合がほとんど。
# 省略なしの場合
ps code | ft id,
name,
@{name='Handles';expression={$_.Handles};alignment='left'},
@{name='CPU';expression={$_.CPU};formatstring="####0.00"}
# 省略した場合
ps code | ft id,name,@{n='Handles';e={$_.Handles};a='left'},@{n='CPU';e={$_.CPU};f="####0.00"}
結果
Id Name Handles CPU
-- ---- ------- ---
6924 Code 1059 756.02
7344 Code 213 0.95
7552 Code 464 1.92
15900 Code 398 49.06
15948 Code 279 7.13
16116 Code 403 33.30
21404 Code 214 1.19
22532 Code 215 0.48
36224 Code 501 274.56
38748 Code 259 1.86
40000 Code 305 0.11
40684 Code 535 210.70
41032 Code 1836 225.59
41332 Code 223 1.45
41564 Code 220 204.81
41724 Code 218 0.53
Compare-Object
expression
Compare-Object
はプロパティで比較基準を設定出来る。
[Process]
型を様々な方法で比較してみる。
$ps= get-process code
$ps[0] | fl
$ps[1] | fl
結果
Id : 6924
Handles : 1065
CPU : 536.8125
SI : 1
Name : Code
Id : 7344
Handles : 213
CPU : 0.953125
SI : 1
Name : Code
通常はNameが比較対象になるので「同じ」だと判定される。
Compare-Object $ps[0] $ps[1]
プロパティ名を指定すると比較対象が変わる。
Compare-Object $ps[0] $ps[1] -Property Id
Id SideIndicator
-- -------------
7344 =>
6924 <=
Select-Object
と同様に複数プロパティの指定も可能。
Compare-Object $ps[0] $ps[1] -Property Name,Id
Name Id SideIndicator
---- -- -------------
Code 7344 =>
Code 6924 <=
プロパティで演算を行った例。
Id
は偶数なので{$_.Id % 2}
は両方とも0で同じなのでこの結果になる。
Compare-Object $ps[0] $ps[1] -Property Name,{$_.Id % 2}
演算なしとの比較
Compare-Object $ps[0] $ps[1] -Property Name,{$_.Id % 2},Id
Name $_.Id % 2 Id SideIndicator
---- --------- -- -------------
Code 0 7344 =>
Code 0 6924 <=
Compare-Object
応用
型を比較する
メンバーの型定義をすることによりダックタイピングを実現出来るかも?
[ValidateScript]
で使えそう。
※Idは可視化のためにつけている。
Compare-Object $ps[0] $ps[1] -Property {$_.Name.Gettype()},{$_.Id.Gettype()},{$_.Parent.Gettype()},Id
$_.Name.Gettype() : System.String
$_.Id.Gettype() : System.Int32
$_.Parent.Gettype() : System.Diagnostics.Process
Id : 7344
SideIndicator : =>
$_.Name.Gettype() : System.String
$_.Id.Gettype() : System.Int32
$_.Parent.Gettype() : System.Diagnostics.Process
Id : 6924
SideIndicator : <=
発想を自由にする
Get-Processをスクリプトブロック内で行うことで、Compare-Object実行時に実行されているプロセス数を比較している。
Compare-Object pwsh code -Property {(get-process $_).count}
(get-process $_).count SideIndicator
---------------------- -------------
16 =>
4 <=
Compare-Object
実践
ファイル比較
準備
PS >"---test.txt---"
>> cat .\test.txt
>>
>> "`n---test.log---"
>> cat .\test.log
---test.txt---
Line 1
Line 2
Line 3
Line 4
Line 5
---test.log---
Name Value
---- -----
args {}
e System.IO.FileSystemEventArgs
Error {}
event System.Management.Automation.PSEventArgs
eventArgs System.IO.FileSystemEventArgs
eventSubscriber System.Management.Automation.PSEventSubscriber
false False
MyInvocation System.Management.Automation.InvocationInfo
null
PSBoundParameters {[source, System.IO.FileSystemWatcher], [e, System.IO.FileSystemEventArgs]}
PSCommandPath
PSDefaultParameterValues {}
PSScriptRoot
script:Error {}
sender System.IO.FileSystemWatcher
source System.IO.FileSystemWatcher
true True
パス名は文字列比較になってしまう
PS >Compare-Object .\test.txt .\test.log
InputObject SideIndicator
----------- -------------
.\test.log =>
.\test.txt <=
公式のドキュメントではこのようにして比較してる
PS >Compare-Object (Get-Content .\test.txt) (Get-Content .\test.log)
InputObject SideIndicator
----------- -------------
=>
Name Value =>
---- ----- =>
args {} =>
e System.IO.FileSystemEventArgs =>
Error {} =>
event System.Management.Automation.PSEventArgs =>
eventArgs System.IO.FileSystemEventArgs =>
eventSubscriber System.Management.Automation.PSEventSubscriber =>
false False =>
MyInvocation System.Management.Automation.InvocationInfo =>
null =>
PSBoundParameters {[source, System.IO.FileSystemWatcher], [e, System.IO.FileSystemEventArgs]} =>
PSCommandPath =>
PSDefaultParameterValues {} =>
PSScriptRoot =>
script:Error {} =>
sender System.IO.FileSystemWatcher =>
source System.IO.FileSystemWatcher =>
true True =>
=>
Line 1 <=
Line 2 <=
Line 3 <=
Line 4 <=
Line 5 <=
Property
パラメータで演算を行うとこうなる
結果が違うのは公式の例はファイル内容の1行ごとの文字列動詞を比較しているのに対し、この例ではファイル内容全体で比較しているため。
PS >Compare-Object .\test.txt .\test.log -Property {cat $_}
cat $_ SideIndicato
r
------ ------------
{, Name Value, ---- -----, args {}...} =>
{Line 1, Line 2, Line 3, Line 4...} <=
ファイルハッシュの比較も行える
PS >Compare-Object ((Get-FileHash .\test.txt).hash) ((Get-FileHash .\test.log).hash)
InputObject SideIndicator
----------- -------------
48B6D671ED303B15C649F94163DD8167280DE44D6673C67A7C1BEE834CEAFFB6 =>
7B2C588D37C473A32203AFAF5C7628EA75EB79B33C799850E509CA37BCBE4195 <=
PS >Compare-Object .\test.txt .\test.log -Property {(Get-FileHash $_).Hash}
(Get-FileHash $_).Hash SideIndicator
---------------------- -------------
48B6D671ED303B15C649F94163DD8167280DE44D6673C67A7C1BEE834CEAFFB6 =>
7B2C588D37C473A32203AFAF5C7628EA75EB79B33C799850E509CA37BCBE4195 <=
組み合わせる
$hashParams = @{
ReferenceObject = get-item .\test.txt
DifferenceObject = get-item .\test.log
Property = @(
{ $_.name }
{ (Get-FileHash $_).Hash }
{ $_.Attributes }
{ $_.LastWriteTime }
)
}
Compare-Object @hashParams
結果
$_.name : test.log
(Get-FileHash $_).Hash : 48B6D671ED303B15C649F94163DD8167280DE44D6673C67A7C1BEE834CEAFFB6
$_.Attributes : Archive
$_.LastWriteTime : 2020/09/19 16:00:41
SideIndicator : =>
$_.name : test.txt
(Get-FileHash $_).Hash : 7B2C588D37C473A32203AFAF5C7628EA75EB79B33C799850E509CA37BCBE4195
$_.Attributes : Archive
$_.LastWriteTime : 2020/10/12 22:12:50
SideIndicator : <=
`
`IncludeEqual`パラメータで同じものを表示させる事も出来る
ファイルをコピーして比較する
```powershell
copy .\test.txt .\test_copied.txt -Force
$hashParams = @{
ReferenceObject = get-item .\test.txt
DifferenceObject = get-item .\test_copied.txt
Property = @(
{ $_.name }
{ (Get-FileHash $_).Hash }
{ $_.Attributes }
{ $_.LastWriteTime }
)
}
この条件ではname以外は一致
$_.name : test_copied.txt
(Get-FileHash $_).Hash : 7B2C588D37C473A32203AFAF5C7628EA75EB79B33C799850E509CA37BCBE4195
$_.Attributes : Archive
$_.LastWriteTime : 2020/10/12 22:12:50
SideIndicator : =>
$_.name : test.txt
(Get-FileHash $_).Hash : 7B2C588D37C473A32203AFAF5C7628EA75EB79B33C799850E509CA37BCBE4195
$_.Attributes : Archive
$_.LastWriteTime : 2020/10/12 22:12:50
SideIndicator : <=
名前以外を比較する
$hashParams = @{
ReferenceObject = get-item .\test.txt
DifferenceObject = get-item .\test_copied.txt
Property = @(
# { $_.name }
{ (Get-FileHash $_).Hash }
{ $_.Attributes }
{ $_.LastWriteTime }
)
IncludeEqual = $true
ExcludeDifferent = $true
}
Compare-Object @hashParams
結果
(Get-FileHash $_).Hash $_.Attributes $_.LastWriteTime SideIndicator
------------------------ --------------- ------------------ -------------
7B2C588D37C473A32203AFAF5C7628EA75EB79B33C799850E509CA37BCBE4195 Archive 2020/10/12 22:12:50 ==
ConvertTo-Html
ConvertTo-Html
name
/label
- optional (added in PowerShell 6.x)expression
width
- optionalalignment
- optional
Format-Custom
Format-Custom
expression
depth
- optional
Format-List
Format-List
name
/label
- optionalexpression
formatstring
- optionalThis same set of key-value pairs also apply to calculated property values
passed to the GroupBy parameter for allFormat-*
cmdlets.
Format-Table
Format-Table
name
/label
- optionalexpression
formatstring
- optionalwidth
- optionalalignment
- optional
Format-Wide
Format-Wide
expression
formatstring
- optional
Group-Object
Group-Object
expression
Measure-Object
Measure-Object
- Only supports a script block for the expression, not a hashtable.
- Not supported in PowerShell 5.1 and older.
Select-Object
Select-Object
name
/label
- optionalexpression
Sort-Object
Sort-Object
expression
ascending
/descending
- optional
補足
[!NOTE]
The value of theexpression
can be a script block instead of a
hashtable. For more information, see the Notes section.
お気に入りの拡張モジュール・Nugetのライブラリ
Powershellの真価はModule/外部ライブラリ取り込める拡張性にあり。
※PowershellGetの扱い方はググると出てくると思います。
ClassExplorer
.NETの型情報を調べるツールです。
何を入れるのがオススメかと聞かれたらClassExplorerと応えます。
- パラメータ、返り値の型からエラー解析や応用を探る
- Powershellで行いたいことがあるとき、良い感じのクラス、メソッドなどがあるのか確認
- インストールしたモジュールが使っているアセンブリの解析
- 主にNugetで公開されているライブラリ、そのラッパーモジュールで使用。
❯ gcm -mo ClassExplorer
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Find-Member 1.1.0 ClassExplorer
Cmdlet Find-Namespace 1.1.0 ClassExplorer
Cmdlet Find-Type 1.1.0 ClassExplorer
Cmdlet Get-Assembly 1.1.0 ClassExplorer
Cmdlet Get-Parameter 1.1.0 ClassExplorer
使用例:Eventを持つオブジェクトを確認する
例
~
❯ Find-Member -MemberType Event
ReflectedType: System.AppContext
Name MemberType IsStatic Definition
---- ---------- -------- ----------
UnhandledException Event True Void UnhandledExceptionEventHandler.Invoke(Object sender, UnhandledExc…
FirstChanceException Event True Void EventHandler`1.Invoke(Object sender, FirstChanceExceptionEventArg…
ProcessExit Event True Void EventHandler.Invoke(Object sender, EventArgs e)
ReflectedType: System.AppDomain
Name MemberType IsStatic Definition
---- ---------- -------- ----------
UnhandledException Event False Void UnhandledExceptionEventHandler.Invoke(Object sender, UnhandledExc…
DomainUnload Event False Void EventHandler.Invoke(Object sender, EventArgs e)
FirstChanceException Event False Void EventHandler`1.Invoke(Object sender, FirstChanceExceptionEventArg…
ProcessExit Event False Void EventHandler.Invoke(Object sender, EventArgs e)
AssemblyLoad Event False Void AssemblyLoadEventHandler.Invoke(Object sender, AssemblyLoadEventA…
AssemblyResolve Event False Assembly ResolveEventHandler.Invoke(Object sender, ResolveEventArgs ar…
ReflectionOnlyAssem… Event False Assembly ResolveEventHandler.Invoke(Object sender, ResolveEventArgs ar…
TypeResolve Event False Assembly ResolveEventHandler.Invoke(Object sender, ResolveEventArgs ar…
ResourceResolve Event False Assembly ResolveEventHandler.Invoke(Object sender, ResolveEventArgs ar…
ReflectedType: System.Progress`1[T]
Name MemberType IsStatic Definition
---- ---------- -------- ----------
ProgressChanged Event False Void EventHandler`1.Invoke(Object sender, T e)
ReflectedType: System.Threading.Tasks.TaskScheduler
Name MemberType IsStatic Definition
---- ---------- -------- ----------
UnobservedTaskExcep… Event True Void EventHandler`1.Invoke(Object sender, UnobservedTaskExceptionEvent…
ReflectedType: System.Runtime.Loader.AssemblyLoadContext
Name MemberType IsStatic Definition
---- ---------- -------- ----------
ResolvingUnmanagedD… Event False IntPtr Func`3.Invoke(Assembly arg1, String arg2)
Resolving Event False Assembly Func`3.Invoke(AssemblyLoadContext arg1, AssemblyName arg2)
Unloading Event False Void Action`1.Invoke(AssemblyLoadContext obj)
ReflectedType: System.Reflection.Assembly
Name MemberType IsStatic Definition
---- ---------- -------- ----------
ModuleResolve Event False Module ModuleResolveEventHandler.Invoke(Object sender, ResolveEventArg…
# (中略)
ReflectedType: Microsoft.Windows.HostGuardianService.Diagnostics.Synthesizer`2[TTrace,THost]
Name MemberType IsStatic Definition
---- ---------- -------- ----------
TargetDiscovered Event False Void EventHandler`1.Invoke(Object sender, TargetDiscoveredEventArgs e)
ReflectedType: Microsoft.Windows.RemoteAttestation.Core.TcgPcrEvent
Name MemberType IsStatic Definition
---- ---------- -------- ----------
UnknownPcrEvent Event True Void EventHandler`1.Invoke(Object sender, TcgParserEventArgs e)
ReflectedType: System.Drawing.Printing.PrintDocument
Name MemberType IsStatic Definition
---- ---------- -------- ----------
BeginPrint Event False Void PrintEventHandler.Invoke(Object sender, PrintEventArgs e)
EndPrint Event False Void PrintEventHandler.Invoke(Object sender, PrintEventArgs e)
PrintPage Event False Void PrintPageEventHandler.Invoke(Object sender, PrintPageEventArgs e)
QueryPageSettings Event False Void QueryPageSettingsEventHandler.Invoke(Object sender, QueryPageSett…
Disposed Event False Void EventHandler.Invoke(Object sender, EventArgs e)
ReflectedType: System.IO.FileSystemWatcher
Name MemberType IsStatic Definition
---- ---------- -------- ----------
Changed Event False Void FileSystemEventHandler.Invoke(Object sender, FileSystemEventArgs …
Created Event False Void FileSystemEventHandler.Invoke(Object sender, FileSystemEventArgs …
Deleted Event False Void FileSystemEventHandler.Invoke(Object sender, FileSystemEventArgs …
Error Event False Void ErrorEventHandler.Invoke(Object sender, ErrorEventArgs e)
Renamed Event False Void RenamedEventHandler.Invoke(Object sender, RenamedEventArgs e)
Disposed Event False Void EventHandler.Invoke(Object sender, EventArgs e)
ImportExcel
Excelファイルを生成するならこのモジュール一択です。
使用例:パイプラインでExcelファイル生成
Find-Member -MemberType Event | select * | Export-Excel Temp:/Events.xlsx -AutoSize -Show
オプション豊富です。一番気に入っているのは複数テーブル構成のExcelを作るのが苦痛ではなくなることです。
Find-Member -MemberType Event | group {$_.ReflectedType.Namespace -replace "(^[^\.]+\.[^\.]+)\..+$",'$1'} | % {
$_.Group | Export-Excel Temp:/ObjectEventsGroupByNameSpace.xlsx -WorksheetName $_.Name -AutoSize -TableStyle Medium1
}
AngleParse
PowerShellから簡単にスクレイピングするためのツールを作った
Powershellの考え方でスクレイピング出来るありがたいモジュール。パイプラインセレクタが嬉しい。