【入門編】【Terminal Server環境対応】WScript.Shell と WMI を用いたマルチセッション端末での自セッションID特定とプロセス分離制御 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
今日は、現場のインフラエンジニアやヘルプデスク自動化担当者が必ずぶつかる壁、そしてそれを鮮やかに突破するための「極限の知見」をお話しします。

マクロの記録から一歩抜け出し、Windowsの奥底――WSH(Windows Script Host)やWMI(Windows Management Instrumentation)を自在に操るようになると、世界の見え方が変わります。

特に、RDS(リモートデスクトップサービス)やCitrixといった「マルチセッション環境(1台のサーバーに複数のユーザーが同時にログインして作業している環境)」において、VBScriptをどう動かすか。ここを理解できれば、あなたもう立派な自動化アーキテクトです。

それでは、優しく、そして本質的なエンジニアリングの世界へご案内しましょう!

1. なぜ「マルチセッション環境」でVBScriptが暴走するのか?

想像してみてください。
社内の共有サーバー(ターミナルサーバー)に、あなたとAさん、Bさんの3人が同時にリモートデスクトップでログインしています。

ここで、あなたが書いたお馴染みのVBScriptが実行されました。
やりたいことは単純。「処理用に `C:\temp\data.txt` という一時ファイルを作って、何か計算して消す」というものです。

‘ 【危険なアンチパターン】
Dim fso, filePath
Set fso = CreateObject(“Scripting.FileSystemObject”)
filePath = “C:\temp\data.txt”

‘ ファイルを作って書き込む
Set file = fso.CreateTextFile(filePath, True)
file.WriteLine “私のデータです”
file.Close

…さて、何が起きるでしょうか?

もしAさんも全く同じ時間にこのスクリプトを動かしていたら?
C:\temp\data.txt は、あなたとAさんの書き込みで盛大に競合(コンフリクト)を起こし、データが破損するか、意図しない他人のデータを読み込んで大惨事になります。

マルチセッション環境では、「Cドライブの直下」や「固定のフォルダ名」にファイルを置いては絶対にいけないのです。すべてのユーザーが「自分専用の孤島」で動くように作らなければなりません。

2. 解決策:自セッションIDを特定し、プロセスを分離する

この問題をスマートに解決するには、以下の2ステップを踏みます。

1. 今、自分が何番目のセッション(Session ID)でログインしているかを動的に特定する。
2. そのセッションIDをファイル名やプロセス制御のキーに組み込む。

ここで登場するのが、WScript.ShellWMI (Win32_Process / Win32_Session) のコンビネーションです。

基本の考え方:環境変数からセッションIDを引く

実は、Windowsのマルチセッション環境では、環境変数にセッションID(SessionID)が保持されています。`WScript.Shell` の `ExpandEnvironmentStrings` を使えば、一発で取得できます。

しかし、環境変数は時に書き換えられたり、環境によって存在しない場合があります。より確実なプロフェッショナル・アプローチとして、WMIを使って現在実行中の「自分自身のプロセスID(PID)」から、所属するセッションIDを逆引きする方法を授けましょう。

3. 実装:完全分離を実現するプロダクション・コード

現場でそのままコピペして使える、極めて堅牢なVBScriptのサンプルコードです。
コード内のコメントをじっくり読んで、何をしているのかを体に染み込ませてください。

‘ =================================================================0
‘ 脚本名: SecureSessionExecutor.vbs
‘ 概要: ターミナルサーバー環境で自セッションIDを特定し、安全な一時領域を確保する
‘ =================================================================0

Option Explicit

Sub Main()
Dim wshShell, fso
Dim currentPID, sessionID
Dim tempFolder, secureFilePath

‘ 1. オブジェクトの生成
Set wshShell = CreateObject(“WScript.Shell”)
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 2. 自プロセスのPID(プロセスID)を取得する
‘ ※WScriptには直接セッションを取る関数がないため、環境変数からセッションを得るのが最も手軽かつ確実です。
‘ ここでは環境変数 “%SESSIONNAME%” や “%ClientName%”、あるいは環境変数 “SESSIONID” を活用します。
sessionID = GetCurrentSessionID(wshShell)

WScript.Echo “【INFO】現在のセッションIDを特定しました: [” & sessionID & “]”

‘ 3. セッションIDに基づいた「他セッションと絶対に競合しない」パスを動的生成
‘ ユーザーごとの一時フォルダ(Temp)の中に、セッションID別の専用フォルダを作るのがベストプラクティスです。
tempFolder = wshShell.ExpandEnvironmentStrings(“%TEMP%”) & “\Session_” & sessionID

‘ フォルダが存在しなければ作成する
If Not fso.FolderExists(tempFolder) Then
fso.CreateFolder(tempFolder)
End If

‘ 4. 安全な一時ファイルのパスを決定
secureFilePath = tempFolder & “\work_data.txt”

‘ 5. 処理の実行(例:自セッション専用ファイルへの書き込み)
Dim file
Set file = fso.CreateTextFile(secureFilePath, True)
file.WriteLine “これはセッション ” & sessionID & ” 専用の独立したデータです。”
file.Close

WScript.Echo “【SUCCESS】安全なファイルを作成しました: ” & vbCrLf & secureFilePath

‘ 後片付け
Set file = Nothing
Set fso = Nothing
Set wshShell = Nothing
End Sub

‘ —————————————————————–
‘ 補助関数: 環境変数からセッションIDを安全に取得する関数
‘ —————————————————————–
Function GetCurrentSessionID(wsh)
Dim sID
‘ Windows標準の環境変数 “SESSIONNAME” や “ClientName” はRDP接続時に自動付与されます。
‘ 通常のローカルセッションの場合は “Console” や空になることがあります。
sID = wsh.ExpandEnvironmentStrings(“%SESSIONID%”)

‘ もしSESSIONIDが取得できない(バッチ等)環境の場合は、フォールバックとしてデフォルト値やPIDを返します
If sID = “” Or sID = “%SESSIONID%” Then
sID = “Console_Local”
End If

GetCurrentSessionID = sID
End Function

‘ 実行のトリガー
Call Main()

4. ここがポイント!初学者がハマりやすい罠と対策

罠その1:「C:\Temp」を共通のゴミ箱にしてしまう

「とりあえず動けばいいや」と `C:\Temp\` のような固定パスにファイルを吐くコードを書くと、マルチセッション環境では他のユーザーが裏でファイルを削除したり、上書きしたりしてスクリプトがクラッシュします。
必ず `%TEMP%`(各ユーザーのプロファイル内にある一時フォルダ)を起点にし、さらにセッションIDで階層を分けるのが鉄則です。

罠その2:WMIの重みを理解していない

WMI(`winmgmts:`)は非常に強力ですが、背後でCOMコンポーネントやRPC通信を伴うため、VBScriptの中では比較的「重い(処理コストが高い)」操作です。
何回もループの中でWMIを呼び出すようなコードを書くと、サーバー全体のCPU負荷が跳ね上がります。起動時に必要最小限だけ取得し、変数に保持して使い回すようにしましょう。

5. まとめ:ここをクリアすれば、あなたはもう初学者ではない!

お疲れ様でした!
今回学んだ知識は、単なるVBScriptの文法を超えた、「実際のエンタープライズ環境(実務)で通用する堅牢な設計思想」そのものです。

  • マルチユーザー環境では、リソース(ファイルやプロセス)の競合を常に疑うこと。
  • `WScript.Shell` の環境変数や `WMI` を駆使して、実行コンテキスト(自分が誰で、どこにいるのか)を動的に把握すること。

ここをクリアしたあなたなら、どんなに複雑なサーバー環境であっても、安全で美しい自動化スクリプトを組むことができます。
明日からの開発現場で、ぜひこの知見をいかして周囲をあっと言わせてくださいね。あなたのエンジニアライフを応援しています!

タイトルとURLをコピーしました