minrさんの代替データストリーム(ADS)について色々調べてみたを読んで実際に代替データストリームを使ってみた。
※最初の投稿に不備があったので一部訂正します。
代替データストリームの読み書き
代替データストリームはNTFS上のファイルやディレクトリに付与できる情報とのこと。PowerShellでこれにアクセスするコマンドは次の6つ。
コマンドレット | 機能 |
---|---|
Add-Content -Path ファイル名 -Value 値 -Stream ストリーム名 | 指定された既存のストリームに値を追記 |
Clear-Content -Path ファイル名 -Stream ストリーム名 | 指定された既存のストリームから値のみを削除 |
Get-Content -Path ファイル名 -Stream ストリーム名 | 指定された既存のストリームの値を得る |
Set-Content -Path ファイル名 -Value 値 -Stream ストリーム名 | 指定されたストリームに値を設定(存在しない場合はストリームを作成) |
Get-Item -Path ファイル名 -Stream ストリーム名 | 指定された既存のストリームの値とサイズを得る |
Remove-Item -Path ファイル名 -Stream ストリーム名 | 指定された既存のストリームそのものを削除 |
似たようなコマンドレットがありますが、それぞれ微妙に違いがあります。
-
Add-Content
は値を追記するが、Set-Content
は値を上書きしてしまう -
*-Content
系コマンドレットはストリーム名の指定にワイルドカードが使えないが、*-Item
系はストリーム名の指定にワイルドカードが使える -
Clear-Content
はストリーム名を残したまま値を削除するが、Remove-Item
はストリームそのものを削除する
自分自身が起動された日付を覚えよう
毎日決められた時刻までに残業申請をしなくてはいけません。(´Д` )
なので朝イチPC起動時にスタートアップから立ち上がるPowerShellコンソールの$profile
に、その日最初の1回だけ残業申請ファイルを立ち上げるスクリプトを書くのです。
if ($PSVersionTable.PSVersion.Major -ne 5) {
"このPowerShellでは動作しません。"
} else {
$today = Get-Date
$myname = $MyInvocation.MyCommand.Path
$Keyword = Get-Item -Path $myname -Stream * | Where-Object {$_.Stream -match 'LastBoot'}
if ((Get-Content -Path $myname -Stream $Keyword.Stream) -ne $today.Date.toString()) {
"本日最初の起動です。"
}
Set-Content -Path $myname -Value $today.Date.toString() -Stream 'LastBoot'
}
6行目でスクリプトファイル自身に付与されているであろう代替データストリームの内容を抽出し、7行目でこれを照合しています。処理が終わったら10行目で今日の日付を代替データストリームに書き込んで終了します。
実際には8行目のメッセージのところを残業申請ファイルの立ち上げプロセスに書き換えて使用します。
必ず存在する:$DATA
Get-Item
でストリーム名を*にして検索すると、必ず表示されるストリーム名があります。ファイルサイズを表す:$DATA
ストリームです。
代替データストリームを扱うコマンドレットはいずれも存在しないストリーム名を指定するとエラーを吐きます。なので、このスクリプトの初回起動時にLastBootというデータストリームが存在しない場合を想定して、3行目ではあえてすべてのデータストリームの中からLastBootを抽出するというまどろっこしいことをしました。
これができるのも、:$DATA
という必ず存在する代替データストリームのおかげです。
追記:Windows7では動かなかった
代替データストリーム自体はNTFSの機能なのでWindows7にもあるはずですが、Get-Item
やGet-Content
、Set-Content
がStream
パラメータを扱えませんでした。
Windows7のPowerShellはVersion2です。当初このスクリプトを動かして確認したWindows10のPowerShellはVersion5。
3や4で動くのかどうかわかりませんが、とりあえず動作確認の取れているVersion5のみ動作するように書き換えました。
1行目で自動変数の値をみてPowerShellのVersion5かどうかをチェックしています。