「拒否された領域」を可視化する――FSOによるネットワーク監査スクリプトの極意
こんにちは。現場の自動化を支えるエンジニアの皆さん。
今日は、単なる「マクロの記録」から一歩踏み出し、「システムを制御するエンジニア」へとステップアップするための、非常に実践的で、かつ奥の深いテーマをお話ししましょう。
皆さんは、社内のファイルサーバーを巡回して、「誰がどこにアクセスできないのか」を調査するようなミッションを命じられたことはありませんか?
「全フォルダをチェックして、アクセス権限がない(Permission Denied)場所だけをリストアップしてほしい」
こうした要求に対し、手作業でクリックして回るなんてことは絶対にしません。そこで登場するのが、VBScript と FileSystemObject (FSO) です。
今回は、ネットワーク共有上の全ディレクトリを探索し、エラー(アクセス拒否)が発生したパスだけを抽出する「セキュリティ監査スクリプト」の構築を通じて、VBScriptの真髄を伝授します。ここをクリアすれば、VBScriptの基本はバッチリですよ。
1. 武器を手に入れる:FileSystemObject (FSO) とは?
まず、私たちが使う最大の武器、FileSystemObject (FSO) について理解しておきましょう。
VBScript自体は、あくまで「言語」です。しかし、言語だけでは「ファイルを作る」「フォルダを開く」といった、OS(Windows)の操作はできません。そこで、Windowsが用意してくれている「ファイル操作の専門家(オブジェクト)」を呼び出す必要があります。それがFSOです。
FSOの役割
- ファイル操作: 作成、削除、コピー、移動
- フォルダ操作: フォルダの作成、一覧取得、属性確認
- パスの操作: ファイル名と拡張子の分離、親フォルダの特定
これらを使いこなすことで、スクリプトは「目」と「手」を持ったことになります。
2. 戦略を立てる:再帰探索とエラーハンドリング
今回のミッションは「ネットワーク上の全ディレクトリを巡回する」ことです。ここで重要になる技術が2つあります。
① 再帰(Recursion)という手法
フォルダの中にフォルダがあり、その中にまたフォルダがある……。この「入れ子構造」をすべて辿るには、「フォルダを見つけたら、その中にあるフォルダに対して自分自身(同じ処理)をもう一度呼び出す」という「再帰処理」というテクニックを使います。
② エラーハンドリング(Err.Number = 70)
ネットワーク共有の世界は、非常に「不確実」です。
「アクセス権限がないフォルダ」に触れた瞬間、通常のプログラムは「エラーが発生しました!」と叫んで止まってしまいます。
監査スクリプトが途中で止まってしまったら、調査は失敗です。
そこで、「エラーが起きても無視して次へ進む。ただし、エラーが起きた場所(パス)だけは記録しておく」という高度な制御が必要になります。VBScriptでは、エラー番号 `70` が「書き込み禁止またはアクセス拒否」を意味します。
3. 実践:セキュリティ監査スクリプト
それでは、実際に動くコードを見てみましょう。これをコピーして `.vbs` ファイルとして保存すれば、すぐに試せます(※テストは必ず安全な環境で行ってくださいね)。
' ==========================================================================
' プログラム名: Security Audit Folder Scanner
' 目的: 指定されたパス配下の全フォルダを巡回し、アクセス拒否されるパスを抽出する
' 動作原理: FSOを用いた再帰探索 + エラーハンドリングによる権限エラーの捕捉
' ==========================================================================
Option Explicit
Dim fso, targetPath, logPath, logFile
Set fso = CreateObject("Scripting.FileSystemObject")
' --- 設定エリア ---
targetPath = "\\YourServer\SharedFolder" ' 調査したいネットワークパス
logPath = "C:\Temp\AccessDeniedReport.txt" ' 結果を出力するログファイル
' ------------------
' ログファイルの準備(既存のファイルがあれば上書き)
Set logFile = fso.CreateTextFile(logPath, True)
logFile.WriteLine "=== Security Audit Report: Access Denied Paths ==="
logFile.WriteLine "Scan Started: " & Now
logFile.WriteLine "Target: " & targetPath
logFile.WriteLine "--------------------------------------------------"
' 探索開始!
WScript.Echo "監査を開始します。時間がかかる場合がありますのでお待ちください..."
ScanFolder fso.GetFolder(targetPath)
' 終了処理
logFile.WriteLine "--------------------------------------------------"
logFile.WriteLine "Scan Finished: " & Now
logFile.Close
WScript.Echo "監査が完了しました。" & vbCrLf & "レポートを確認してください: " & logPath
' --------------------------------------------------------------------------
' 関数: ScanFolder (再帰的にフォルダを探索する)
' 引数: objFolder (FileSystemObjectのFolderオブジェクト)
' --------------------------------------------------------------------------
Sub ScanFolder(objFolder)
Dim subFolder, subFolderItem
' エラーが発生しても処理を続行するように設定(超重要!)
On Error Resume Next
' サブフォルダを一つずつ確認していく
For Each subFolder In objFolder.SubFolders
' --- ここからが核心部 ---
' サブフォルダにアクセスを試みる(ここで権限エラーが発生する可能性がある)
If Err.Number <> 0 Then
' エラー番号 70 は「Permission Denied (アクセス拒否)」
If Err.Number = 70 Then
logFile.WriteLine "[DENIED] " & subFolder.Path
Else
' それ以外の予期せぬエラー(ネットワーク切断など)
logFile.WriteLine "[ERROR] " & subFolder.Path & " (Err: " & Err.Number & ")"
End If
' エラー情報をクリアして次へ
Err.Clear
Else
' 正常にアクセスできた場合、そのフォルダの中身をさらに探索(再帰呼び出し)
ScanFolder subFolder
End If
' --- ここまで ---
Next
' エラーハンドリングを通常の状態に戻す
On Error GoTo 0
End Sub
4. コードの深層解説:プロの視点
このコード、ただ動くだけではありません。プロフェッショナルが意識している「勘所」がいくつかあります。
なぜ `On Error Resume Next` を使うのか?
通常、プログラミングにおいてエラーを無視するのは「禁忌」です。しかし、今回のような「未知の領域をスキャンする」という用途では、エラー(アクセス拒否)こそが「探している情報」そのものです。
`On Error Resume Next` を使うことで、エラーが起きた瞬間にスクリプトが停止するのを防ぎ、代わりに `Err.Number` をチェックして「何が起きたか」を判定する戦略をとっています。
オブジェクトのライフサイクル
`Set fso = CreateObject(“Scripting.FileSystemObject”)` で生成したオブジェクトは、スクリプトが終了するか、明示的に `Nothing` を代入するまでメモリに居座り続けます。大規模なループの中で大量のオブジェクトを生成しすぎると、メモリを食いつぶす原因になります。今回は `fso` 一つを使い回しているので、非常に効率的です。
再帰の「深さ」への配慮
ネットワークパスが非常に深い(フォルダの中にフォルダが100個ある等)場合、再帰呼び出しが重なりすぎてスタックオーバーフローを起こすリスクがゼロではありません。しかし、一般的なファイルサーバーの構造であれば、この書き方で十分実用的です。
5. 陥りやすいエラーと対策
皆さんが現場でこのスクリプトを動かす際、以下の3点には注意してください。
1. 「ネットワークの遅延」によるタイムアウト
ネットワーク越しに大量のフォルダを叩くと、応答が遅れることがあります。スクリプトが止まっているように見えても、裏で必死に動いていることが多いので、焦らず待ちましょう。
2. 「書き込み権限」の不足
ログファイル(`logPath`)を出力しようとしている場所に対して、実行ユーザーに書き込み権限がないと、スクリプトは開始直後にエラーになります。
3. 無限ループの恐怖(シンボリックリンク)
稀に、フォルダが自分自身を指し示すような特殊な構造(シンボリックリンク)があると、再帰が止まらなくなることがあります。本番環境では、`subFolder.Attributes` をチェックして、リンクではないことを確認する処理を加えると、より「鉄壁」なコードになります。
最後に
いかがでしたか?
単に「ファイルをコピーする」だけのスクリプトから、「エラーを検知して、意味のある情報を抽出する」スクリプトへ。この考え方の違いこそが、エンジニアとしての成長の証です。
VBScriptは決して古い言語ではありません。OSの深層に触れ、業務を劇的に効率化させるための、今なお強力な武器です。
「ここをクリアすれば、VBScriptの基本はバッチリですよ」
さあ、次はもっと複雑な自動化に挑戦してみましょう。応援しています!
