【入門編】【CPU優先度変更】WMI経由で自スクリプトや特定プロセスの Priority(優先度)を動的変更しシステム負荷を制御する技術 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
普段、何気なくダブルクリックして実行しているバッチファイルやVBScriptですが、大量のデータを処理する最中、パソコン全体が重くなって他の作業ができなくなった……なんて経験はありませんか?

「重い処理をさせたいけれど、裏でこっそり、他のアプリの邪魔をしないように動いてほしい」
あるいは逆に、
「今すぐ終わらせなきゃいけない緊急の処理だから、PCのパワーを全集中させたい!」

そんなワガママを叶えてくれるのが、今回解説する「WMI(Windows Management Instrumentation)を使ったプロセスの優先度(Priority)動的変更技術」です。

ここをクリアすれば、単に「コードを書ける人」から、OSの挙動までコントロールできる「ワンランク上の自動化エンジニア」の仲間入りです。一緒に本質をマスターしていきましょう!

1. なぜ「優先度」をコントロールする必要があるのか?

Windowsは、CPUに対して「どのアプリにどれくらい処理能力を割り振るか」を常に調整しています。これを決めているのがプロセスの「優先度(Priority)」です。

デフォルトでは、私たちが起動するスクリプトやアプリは「標準(Normal)」で動作します。しかし、深夜に数万件のファイルを処理するような重いスクリプトが「標準」で暴走すると、OSの応答性がガクッと落ちてしまいます。

ここで、VBScriptからWMI(Windowsの奥深くを操作できる万能ツール)を召喚し、「自分のプロセス」や「特定のタスク」の優先度を「低(Idle)」にしたり「高(High)」にしたりして、システム負荷を完全にコントロールするのです。

2. 優先度のレベルを知る

WMIを通じて設定できるプロセスの優先度には、いくつかの段階があります。現場でよく使う主要なものを押さえておきましょう。

  • 64 (Idle / 低):PCが暇な時だけ働く。他の作業の邪魔を絶対にしたくないバックグラウンド処理に最適。
  • 16384 (Below Normal / 通常以下):標準より少し控えめ。
  • 32 (Normal / 標準):通常のアプリと同じ。指定しない場合はこれ。
  • 32768 (Above Normal / 通常以上):少し急ぎの処理。
  • 128 (High / 高):OSの機能を維持するのに必要なレベルに近い。ここぞという緊急処理用(※使いすぎ注意)。

今回は、最も実用的で安全な「自分自身の優先度を『低』に変更して、PCに優しく動くスクリプト」をメインに実装してみましょう。

3. 実践!自スクリプトの優先度を動的変更するコード

以下のコードをメモ帳に貼り付け、拡張子を `.vbs` (例:`low_priority_task.vbs`)で保存してください。

‘ ==============================================================================
‘ スクリプト名: SetMyPriorityToLow.vbs
‘ 概要: 実行中の自分自身のプロセスを検出し、CPU優先度を「低(Idle)」に変更する
‘ ==============================================================================
Option Explicit

Sub Main()
Dim wmi, services, processes, process
Dim currentProcessId
Dim result

‘ 1. 現在実行中のプロセスID(PID)を取得するテクニック
‘ WMIで自分自身を特定するため、Win32_Processから親プロセスやスクリプトホストを辿ります。
currentProcessId = GetCurrentProcessId()

WScript.Echo “現在の自プロセスID: ” & currentProcessId & ” を検出しました。”

‘ 2. WMIサービスへの接続 (cimv2 ネームスペース)
Set wmi = GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2”)

‘ 3. 対象のプロセスオブジェクトをWMIから取得
Set processes = wmi.ExecQuery(“Select from Win32_Process Where ProcessId = ” & currentProcessId)

For Each process in processes
‘ 4. 優先度の変更メソッド(SetPriority)を呼び出す
‘ 引数 64 は「Idle(低)」を意味します。
result = process.SetPriority(64)

If result = 0 Then
WScript.Echo “【成功】プロセスのCPU優先度を「低 (Idle)」に変更しました。” & vbCrLf & _
“これでPCの他の動作を妨げずに処理を実行できます。”
Else
WScript.Echo “【失敗】優先度の変更に失敗しました。エラーコード: ” & result
End If
Next

‘ 後片付け
Set processes = Nothing
Set wmi = Nothing

‘ ここに本来の重い処理を記述します
‘ 例: HeavyTask()

End Sub

‘ — ヘルパー関数: 自プロセスのPIDを取得する —
Function GetCurrentProcessId()
Dim wmi, items, item, pid
pid = 0

Set wmi = GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2”)
‘ WScript.ProcessId はWindows 7以降のWSH環境で利用可能です
‘ より確実に取得するため、CIM_Processから自分のコマンドライン等を探すこともできますが、
‘ モダンなWSHであれば WScript.ProcessId がスマートです。

‘ ※互換性を考慮し、ここではWScriptオブジェクトの拡張プロパティを利用
On Error Resume Next
pid = WScript.ProcessId
On Error GoTo 0

‘ 万が一取得できない場合のフォールバック(簡易的に「cscript.exe」または「wscript.exe」の最新を取得)
If pid = 0 Then
Set items = wmi.ExecQuery(“Select ProcessId from Win32_Process Where Name = ‘cscript.exe’ OR Name = ‘wscript.exe'”)
For Each item in items
pid = item.ProcessId ‘ 簡易的な取得(同名プロセス複数時は注意が必要ですが学習用として)
Next
End If

GetCurrentProcessId = pid
End Function

‘ メイン処理の実行
Main()

4. コードの深掘り解説:ここがエンジニアの急所!

初心者から一歩抜け出すために、このコードの重要なポイントを3つ解説します。

① WMI(`winmgmts`)の魔法

`GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2”)`
この呪文のような一行は、WindowsのOS内部を管理するデータベース(WMI)への扉を開いています。
`impersonationLevel=impersonate` を指定することで、スクリプトが管理者権限などを正しく引き継いでOSのリソースを操作できるようになります。

② `SetPriority` メソッドの仕組み

WMIの `Win32_Process` クラスには、プロセスを操作するための便利なメソッドが用意されています。その一つが `SetPriority(Value)` です。
返り値として `0` が返ってきたら「変更成功」の合図。もし `2` などのエラー値が返ってきた場合は、権限不足(管理者として実行していない等)が原因であることがほとんどです。

③ 「自分自身」を特定するスマートさ

タスクマネージャーから手動で優先度を変えるのは簡単ですが、「スクリプト自身が起動した瞬間に、自分のPID(プロセスID)を調べて、自分で自分を低速化する」というアプローチをとることで、完全な自動化(人手がいらないバッチ処理)が完成します。

5. 陥りやすい罠とエラー回避の知見

実務でこの技術を使う際、プログラマが必ずハマる「罠」があります。

  • 罠1:権限の壁(アクセス拒否)
  • 現象: `SetPriority` でエラー(例:エラーコード 2 または 8)が出る。
  • 原因: 操作しようとしているプロセスが、自分よりも上位の権限(SYSTEM権限や別ユーザーの管理者プロセスなど)で動いている場合、VBScriptからの変更は拒絶されます。
  • 対策: スクリプト自体を「管理者として実行」するか、変更対象のプロセスが自分と同じ権限であることを確認してください。
  • 罠2:プロセスの寿命が短すぎて追いつかない
  • 現象: 一瞬で終わるスクリプトに対して優先度を変えようとしても、コードが実行される前にプロセスが消滅してエラーになる。
  • 対策: 優先度変更が必要なのは「数分〜数時間単位でCPUを占有する重い処理」だけです。一瞬の処理には不要ですので安心してください。

まとめ:VBScriptを「ただの自動化ツール」から「OSの調律師」へ

今回はWMIを経由してプロセスの優先度を動的に変更する技術を解説しました。

  • 重いバッチ処理は 優先度を「低 (64)」 にして、他の業務アプリを快適に保つ。
  • WMIの `Win32_Process` と `SetPriority` を使いこなせば、VBScriptからOSのリソースを自由自在に支配できる。

ここをクリアできれば、VBScriptの基礎はもうバッチリ、胸を張って「自動化エンジニア」と名乗れるレベルです!
現場のシステム環境に優しい、スマートでスマートな自動化ライフをぜひ楽しんでくださいね。

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