実際に書いたスクリプトはこちらが先なんですが、さらに良い方法がないかと考えた結果、代替データストリームを利用した方法を投稿しました。
が、Windows7のPowerShell ver2ではうまく動かなかったのでオリジナル版も投稿しておきます。
自分自身が起動された日付をファイルに書き込む
5行目でログファイルに書き込まれているであろう前回の起動日情報と今日の日付を照合しています。処理が終わったら12行目で今日の日付をログファイルに書き込んで終了します。
10行目には実際に実行させたい処理を記述します。
$today = Get-Date
$logfile = "$HOME\OneTime.log"
$execute = $True
if (Test-Path $logfile) {
if ((Get-Content $logfile) -eq $today.Date.toString()) {
$execute = $False
}
}
if ($execute) {
"本日最初の起動です。"
}
Set-Content $logfile $today.Date
5行目でファイルが存在しない場合、スクリプトはエラーを吐きます。なので代替データストリーム版で代替データストリームの存在確認をしたように、ログファイル版でもファイルの存在確認をします。
ファイルの存在確認コマンドレットはTest-Path。指定ファイルが存在しなければ$Falseを返します。
論理がちょっと面倒くさい
データストリーム版ではデータが存在しない場合も今日ではないという判定になるため、初回起動か否かをif文一発で判定できました。
+---------------------------+
| Start |
+---------------------------+
|
|
v
+------------------+ yes +---------------------------+
| Terminate script | <----- | Is the data stream today? |
+------------------+ +---------------------------+
|
| no
v
+---------------------------+
| Execute script |
+---------------------------+
ところが、ログファイル版では実行する条件が2回出現してしまうため、一旦$executeを介して実際の処理をおこなうかどうかを判定しています。
+----------------+
| Start |
+----------------+
|
|
v
+----------------+
| Exist logfile? | -+
+----------------+ |
| |
| yes |
v |
+------------------+ yes +----------------+ |
| Terminate script | <----- | Is it today? | | no
+------------------+ +----------------+ |
| |
| no |
v |
+----------------+ |
| Execute script | <+
+----------------+
ログファイル版とデータストリーム版を統合してみる
ログファイル版のスクリプトであればどのバージョンのPowerShellでも動くのでわざわざ統合する必要もないですが、できるだけ余計なファイルを作りたくないのでデータストリームが使えるときは使うように書き換えてみました。
$today = Get-Date
$execute = $True
$myname = $MyInvocation.MyCommand.Path
$logfile = "$HOME\OneTime.log"
if ($PSVersionTable.PSVersion.Major -ne 5) {
if (Test-Path $logfile) {
if ((Get-Content $logfile) -eq $today.Date.toString()) {
$execute = $False
}
}
Set-Content -Path $logfile $today.Date
} else {
$Keyword = Get-Item -Path $myname -Stream * | Where-Object {$_.Stream -match 'LastBoot'}
if ((Get-Content -Path $myname -Stream $Keyword.Stream) -eq $today.Date.toString()) {
$execute = $False
}
Set-Content -Path $myname -Value $today.Date.toString() -Stream 'LastBoot'
}
if ($execute) {
"本日最初の起動です。"
}
これならワンクッションおいて$executeを使う意義が出てきたかな。