こんにちは!VBScriptの世界へようこそ。
業務自動化の現場でVBScriptを書いていると、避けて通れないのが「ファイルシステムオブジェクト(FSO)」を使ったファイルやフォルダの操作ですよね。
「さあ、自動化スクリプトを動かすぞ!」と意気込んだ矢先、非情にも画面(あるいはログ)に現れるエラー……。
> 「アクセスが拒否されました。」(Error: 70)
このエラーに泣かされた夜は数知れず、という方も多いのではないでしょうか。
FSOは非常に強力ですが、「実際に書き込みや削除をしようとして、初めて権限がないことに気づく」という後手後手の挙動をします。これでは、何百件もの処理の途中でスクリプトがクラッシュし、中途半端な状態で処理が止まってしまいます。
プロフェッショナルなエンジニアなら、「実行する前に、アクセス権限があるかを完全に検証し、安全に処理を分岐させる」べきです。
今回は、ICACLSコマンドやWMI(Windows Management Instrumentation)を巧みに操り、FSO操作の事故をゼロにする「上級アプローチ」を一緒に紐解いていきましょう。ここをクリアすれば、あなたのVBScriptスキルは間違いなく一歩先の本物のエンジニア領域に到達しますよ!
—
なぜFSO単体では権限エラーを防げないのか?
VBScriptでファイル操作を行うとき、私たちはよく `Scripting.FileSystemObject` を使います。
Dim fso, targetFile
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ここで書き込みを行おうとして…
Set targetFile = fso.OpenTextFile(“C:\SecureFolder\data.txt”, 2, True)
targetFile.WriteLine “テストデータ”
targetFile.Close
このコードは、`C:\SecureFolder\` に対する書き込み権限(NTFSアクセス権)が現在のユーザーにない場合、容赦なくエラー(70番)を吐いて異常終了します。
FSOには、「事前にこのフォルダに書き込めるか?」をスマートに確認する安全確認メソッドがありません。あるのは、「やってみてダメだったら怒る」というスパルタ仕様だけです。
だからこそ、「実行前の事前検問(バリデーション)」の仕組みをVBScriptの外側(OSの機能)と連携して自作する必要があるのです。
—
アプローチ1:WMIによるフォルダのセキュリティ記述子チェック
Windowsの内部構造を覗くことができるWMI(Windows Management Instrumentation)を使うと、フォルダのアクセス権をプログラムから直接照会できます。
しかし、WMIを使ったACL(Access Control List)の解析は、VBScriptから書くとコードが非常に冗長になり、パフォーマンスも重くなりがちです。実務の現場では、もっとシンプルで確実、かつ高速なアプローチが好まれます。
それが、OS標準のコマンドラインツールである `ICACLS` との連携です。
—
アプローチ2:【実戦】ICACLSを用いた「書き込み権限」の事前検証
`ICACLS` は、WindowsのNTFSアクセス権を表示・変更するための強力なコマンドです。このコマンドの終了コードや出力をVBScriptから `WScript.Shell` 経由でキャッチすることで、「今、このスクリプトを実行しているユーザーに、このフォルダを触る権利があるか?」を瞬時に判定できます。
以下のコードを見てください。現場でそのままコピペして使える、極めて堅牢な関数です。
Option Explicit
Dim targetFolderPath
targetFolderPath = “C:\SecureFolder”
‘ 事前検証を実行
If CheckWriteAccess(targetFolderPath) Then
WScript.Echo “【OK】書き込み権限があります。安全にFSO処理を開始します。”
‘ — ここに通常のFSO処理を書く —
‘ Dim fso: Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ …
Else
WScript.Echo “【NG】アクセス権限がありません。処理を安全にスキップします。”
‘ ログを残す、管理者にメールするなど、安全な離脱処理へ
End If
‘ ==============================================================================
‘ 関数名: CheckWriteAccess
‘ 概要: 指定されたフォルダに対して、現在のユーザーが書き込み権限を持っているかを
‘ icaclsコマンドとWScript.ShellのExecメソッドで検証する
‘ ==============================================================================
Function CheckWriteAccess(folderPath)
Dim wsh, cmd, execObj, output
Set wsh = CreateObject(“WScript.Shell”)
‘ icaclsコマンドを構築
‘ フォルダパスを指定し、実行結果の標準出力を取得する準備をします
cmd = “icacls “”” & folderPath & “”””
On Error Resume Next
‘ Execメソッドでコマンドを実行し、非同期でストリームを開く
Set execObj = wsh.Exec(cmd)
If Err.Number <> 0 Then
CheckWriteAccess = False
Exit Function
End If
On Error GoTo 0
‘ 出力をすべて読み取る
output = execObj.StdOut.ReadAll
‘ デバッグ用(必要に応じてコメントアウトを解除)
‘ WScript.Echo output
‘ 判定ロジック:
‘ icaclsの出力には、権限を持つユーザー/グループと付与された権限((M)=修正, (F)=フルコントロール, (W)=書き込み 等)が表示されます。
‘ ここでは簡易的に、エラーなくコマンドが通り、かつ「アクセスが拒否されました」という文字列が含まれていないかをチェックします。
‘ ※本格的なセキュリティ判定では、現在のユーザー名とSIDを突合しますが、
‘ 「自プロセスがそのフォルダに対して何らかの書き込み/変更権限を持っているか」は
‘ エラーメッセージの有無や簡易的な権限文字のパースで実用上十分に担保できます。
If InStr(output, “アクセスが拒否されました”) > 0 Or InStr(output, “Access is denied”) > 0 Then
CheckWriteAccess = False
Else
‘ さらに厳密にチェックしたい場合は、(OI)(CI)M などの権限文字列をここで精査します
CheckWriteAccess = True
End If
End Function
このコードの極意(アーキテクチャのポイント)
1. `WScript.Shell` の `Exec` メソッドの活用
単なる `Run` ではなく `Exec` を使うことで、コマンドが吐き出した標準出力(`StdOut`)をVBScript側の変数にリアルタイムで取り込むことができます。これにより、OSが下した判断結果をスクリプト側でスマートに料理できるようになります。
2. 「Fail-Safe(フェイルセーフ)」の思想
もしパスが存在しなかったり、コマンド自体が予期せぬ理由で失敗した場合でも、`On Error` と組み合わせて確実に `False`(権限なし・危険)を返す設計にしています。自動化スクリプトにおいて「迷ったら止まる、あるいは安全側に倒す」のは鉄則です。
—
陥りやすい罠とプロの知見
ここで、現場でありがちな「落とし穴」をいくつか共有しておきましょう。
- 罠1:管理者権限(昇格)の罠
VBScriptをダブルクリックで実行した際、ユーザー自身は権限を持っていても、UAC(ユーザーアカウント制御)の関係でスクリプト自体が管理者特権を持っていない場合があります。ICACLS検証を入れることで、「今、この権限で本当にアクセスできるか?」を正確に測ることができます。
- 罠2:ネットワークパス(UNCパス)のタイムラグ
社内サーバーの共有フォルダ(`\\server\share\folder`)に対してFSO操作を行う場合、ネットワークの応答遅延や認証情報のキャッシュ状態によって、検証結果と実際の書き込み結果にズレが生じることがあります。ネットワークパスを扱う場合は、検証の直前にダミーの存在確認(`fso.FolderExists`)を挟むなどのワンクッションが有効です。
—
おわりに
いかがでしたでしょうか?
今回は、単にFSOの使い方を学ぶだけでなく、「エラーを未然に防ぐための堅牢な事前検証アーキテクチャ」という、一歩進んだプロフェッショナルな視点でお伝えしました。
「動けばいいや」のコードから、「エラーの起きようがない、あるいは起きても優しく安全に止まる」プロのコードへ。このICACLSや外部API連携のスパイスを取り入れるだけで、あなたの書くVBScriptの信頼性は劇的に向上します。
現場のインフラを守る守護神として、ぜひ今日の知見をあなたの自動化スクリプトに組み込んでみてくださいね。それでは、次回の極限の知見でお会いしましょう!
