【実務・中級編】【タイムスタンプ変更】Shell.Application と FileSystemObject を組み合わせたファイル作成日・更新日・アクセス日の動的改変 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを支配せよ:Shell.Applicationによるタイムスタンプ改変の極意

VBScriptは「レガシー」と呼ばれ、軽んじられることが多い。だが、OSの深淵に直接触れ、数行のコードでシステム管理のボトルネックを解消できるこの言語を、私は「究極の軽量自動化兵器」と呼んでいる。

特にファイルシステムを操作する際、標準の`Scripting.FileSystemObject (FSO)`だけで済ませようとするのは素人のやることだ。FSOはファイルの「読み書き」には適しているが、ファイルシステムが持つ「属性(タイムスタンプ)」を制御する能力は極めて限定的だ。

今回は、業務自動化の現場で頻発する「テストデータ作成」「ログの時系列調整」において、なぜ`Shell.Application`を組み合わせる必要があるのか。そして、いかに堅牢なコードを組むべきかを伝授する。

1. なぜFSOだけでは不十分なのか

まず、前提を共有しよう。多くのエンジニアがFSOで試みるのは `file.DateLastModified = …` といった代入だ。しかし、これではエラーが発生するか、あるいは無視される。FSOはOSのメタデータ更新において、読み取り専用の側面が強すぎるからだ。

ここで登場するのが `Shell.Application` である。これはWindowsのエクスプローラーをプログラム的に制御するためのオブジェクトだ。フォルダの `GetDetailsOf` メソッドや、アイテムの属性変更を通じて、OSが管理する「作成日時」「更新日時」「アクセス日時」を強制的に書き換える。

2. 堅牢な実装への指針

プロダクションレベルのコードでは、以下の3点を徹底しなければならない。

1. オブジェクトの解放: VBScriptはガベージコレクションが脆弱だ。`Set obj = Nothing` を怠ることは、メモリリークという名の爆弾を仕掛けることと同義である。
2. パスの完全修飾: 相対パスは禁忌だ。OSの実行コンテキストに依存しないよう、`Scripting.FileSystemObject` の `GetAbsolutePathName` を使い、絶対パスを確定させろ。
3. エラーハンドリング: ファイルがロックされている、あるいは属性変更の権限がない場合のハンドリングを忘れるな。

3. 実践:タイムスタンプ改変エンジン

以下に、再利用性を高めた「タイムスタンプ変更スクリプト」を提示する。このままライブラリとして組み込める設計だ。

‘ =================================================================
‘ Function: SetFileTimestamp
‘ 目的: 指定ファイルのタイムスタンプを強制的に書き換える
‘ 引数: filePath (フルパス), dt (目標日時)
‘ =================================================================
Function SetFileTimestamp(filePath, dt)
Dim fso, shellApp, folder, fileItem

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ ファイル存在確認の堅牢化
If Not fso.FileExists(filePath) Then
Err.Raise 53, , “ファイルが見つかりません: ” & filePath
End If

‘ Shell.Applicationオブジェクトの生成
Set shellApp = CreateObject(“Shell.Application”)
Set folder = shellApp.Namespace(fso.GetParentFolderName(filePath))
Set fileItem = folder.ParseName(fso.GetFileName(filePath))

‘ ここでタイムスタンプを強制更新
‘ 注意: 日本語環境等のOS言語設定により、インデックス番号が変わる可能性があるため
‘ 本来は「作成日時」「更新日時」を指すインデックスを確認すること
‘ 今回は標準的な「更新日時(Date Modified)」をターゲットとする
fileItem.ModifyDate = dt

‘ オブジェクトの完全解放
Set fileItem = Nothing
Set folder = Nothing
Set shellApp = Nothing
Set fso = Nothing
End Function

‘ — 実行例 —
Dim targetFile, targetDate
targetFile = “C:\Projects\Log\test_data.log”
targetDate = #2023/12/31 23:59:59#

On Error Resume Next
SetFileTimestamp targetFile, targetDate
If Err.Number <> 0 Then
WScript.Echo “エラー発生: ” & Err.Description
Else
WScript.Echo “タイムスタンプの改変に成功しました。”
End If
On Error GoTo 0

4. プロの視点:アーキテクトからの助言

  • タイムゾーンの罠: `Date`型を扱う際、システム日付とUTCの乖離に注意せよ。データベース連携を行う場合、DB側のタイムスタンプ形式とVBScriptが解釈する日付形式を合わせるための正規化レイヤーを一枚噛ませるのが定石だ。
  • 権限の壁: このスクリプトは、実行ユーザーにファイルの「書き込み権限」がなければ動作しない。もしシステムサービスとしてバックグラウンド実行させるなら、実行ユーザーの権限設定をOS側で事前確認すること。
  • 保守性の極意: もしこのスクリプトを多用するのであれば、引数に「作成日時」「更新日時」「アクセス日時」のフラグを持たせ、クラスモジュールのような構造(VBScriptにはクラス機能があることを忘れるな)でカプセル化すべきだ。

VBScriptは、死んでいない。正しく使えば、最新の言語をわざわざインストールするまでもない領域で、驚異的なパフォーマンスを叩き出す。「なぜ動くのか」を理解した上でコードを書く。それこそが、自動化エンジニアとしての品格だ。

君の現場での成功を祈る。