皆さん、こんにちは。「ソフトウェア」カテゴリ 初投稿です(祝)
マニアックタイム です(笑)
はじめに、くろねこは自称プログラマです。
もう長いです(汗)扱ってきた言語もいろいろやっていますが、古いものばかりですね ^^;
IT関連会社を離れ、別の業種の今は、最新のプログラミング言語事情や開発環境からはすっかり遠のいてます。
それなので、最近は簡単に「ちょろっと」使えるもので、「ちょっとしたツール的なもの」で効率化を図ってるので、ExcelVBAやバッチが中心です。
ExcelVBAはその名の通り、Visual Basicファミリの一つで、Visual Basic for Applicationsの略です。Visual Basic(以下、VB)はバージョン6.0までのものと、VB.Netで大きく分かれます。
くろねこの周辺では、前者を「VB」、後者を「VB.Net」と呼んでる人が多いです。
ちなみに、くろねこはVB側の人間で(古!)、VB2.0~VB6.0で変なもの作ってました(汗)
VBAは、Microsoft Officeファミリに実装されたVBで、基本的な文法や構造を継承し、実装されたアプリケーションのオブジェクトをそのまま扱えるようになっています。例えば、ExcelならWorkBookやWorkSheetなどのオブジェクトです。
VBAは、Excelのほかにも、Word、Access、PowerPoint、Outlookにも実装されているので、オブジェクトの扱い方さえ理解すれば、「大体のこと」は実現できます。
そのほかには、VBScript(VBS)というVBのサブセット版的なものが、ほぼすべてのWindowsに実装されてます。
くろねこはこのVBSを駆使していろんなことやってます!
今回はその簡単な例をご紹介しますね。
WMIを使ってみよう!
WMIって聞いたことありますか?
Windows Management Instrumentation の略で、Windowsのいろいろな情報を取得・設定するためのものです。詳しいことは「WMIとは」でグーグル先生に聞いてみてください。
今回の記事は、WMIを使って対象のPCにpingしてみよう! です。もちろんVBSで汎用的なサンプルを作る企画です。出来上がったら使ってみてください。
利用シチュエーションはこんな感じです。
PC-01,PC-02,PC-03,・・・,PC-10 の10台のうち、停止しているPCの一覧を表示する。
仕様
プログラムの仕様を検討します。
求められる要件は次のようになります。
- 汎用性を考えると単機能のものを用意し、それを必要な数だけ繰り返す。というのが自然です。
- 上記のシチュエーションのように、PC名(マシン名)での指定が可能とする。
- PC以外のネットワークデバイスにもpingで確認することはよくあることなので、IPアドレスでの指定も可能とする。
それでは、上記1~3を実現するプログラムをVBSで作成しましょう。プログラム名称は「GetPCStatus.vbs」とします。
実行イメージは以下のようになります。
cscript GetPCStatus.vbs PC名
プログラムのパーツ
VBSでの引数の取得
VBSでプログラム起動時に指定された引数の取得は、WScript.Argumentsオブジェクトを使用します。
もちろん、プログラムの一番最初の部分でこのオブジェクトを使って引数を取得します。WScript.Argumentsを簡単に説明すると以下のようになります。
- WScript.Arguments.Count : 指定された引数の数
- WScript.Arguments.Item() : 指定された引数が格納されている配列
引数は1つのみなので、WScript.Arguments.Item(0)で参照できます。
下記のサンプルは、引数1を変数wkStrに設定するものです。
Set mvParam = WScript.Arguments If mvParam.Count > 0 Then wkStr = mvParam.Item(0) Else WScript.Echo "引数は指定されませんでした" End If
WMIでping(ICMP)を実行
今回、WMIを使ってpingを実行するので、その心臓部となる部分を先に作成します。
下記のサンプルは、IPアドレスが192.168.1.1の機器にpingを実行するものです。
Set pvObjLocator = CreateObject("WbemScripting.SWbemLocator") Set pvObjServer = pvObjLocator.ConnectServer() Set pvObjPing = pvObjServer.ExecQuery("Select * From Win32_PingStatus Where Address='192.168.1.1' And Timeout=500") For Each pvPing In pvObjPing Script.Echo pvPing.StatusCode Next Set pvPing = Nothing Set pvObjPing = Nothing Set pvObjServer = Nothing Set pvObjLocator = Nothing
IPアドレス部分をPC名で指定すると、このVBSを実行しているPCがDNSサーバに名前解決の問い合わせをしてくれるので、要件3は意識せずに実現できます。
プログラムの復帰値の設定
VBSで復帰値を設定するには、WScript.Quit の引数で復帰値を指定します。
具体的には以下のような感じです。(復帰値で12を設定する。)
WScript.Quit 12
サンプルプログラム(GetPCStatus.vbs)
ここまで説明した内容で、一通り動作するサンプルプログラムです。
このプログラムのままでも利用可能ですが、いろいろ改良してみてください。
Option Explicit '*************************************************************************************************** ' GetPCStatus.vbs ' 指定したIPアドレス(マシン名)へのpingを実施し、その結果を復帰値として返却する。 ' <使用方法> ' cscript //NOLOGO GetPCStatus.vbs IPAddr ' IPAddr : 対象PCのIPアドレス、または、マシン名 ' <復帰値> ' 0 : 応答あり ' 32767 : Usage表示(引数なし時) ' 65535 : 名前解決エラー ' その他 : 応答なし(詳細はICMPの状態コードを参照) '*************************************************************************************************** Const mcICMPtimeout = 500 Const mcUsage_000 = "[Command usage]" Const mcUsage_010 = "cscript //NOLOGO GetPCStatus.vbs { IPAddress | PCName }" Const mcNameError = 65535 Const mcShowUsage = 32767 Dim mvAns Dim mvParam mvAns = mcShowUsage Set mvParam = WScript.Arguments If mvParam.Count > 0 Then mvAns = IssueICMP(mvParam.Item(0),mcICMPtimeout) Else Call Echo(mcUsage_000) Call Echo(mcUsage_010) End If Set mvParam = Nothing WScript.Quit mvAns Public Function IssueICMP (pIPAddr, pTimeout) '*************************************************************************************************** ' IssueICMP ' 指定したIPアドレスへのpingを実施する。 ' <引数> ' pIPAddr : IPアドレス または マシン名 ' pTimeout : タイムアウト時間(ms) ' <復帰値> ' ICMPのStatuscodeの値 ' ※ 名前解決できない場合は65535を返却 '*************************************************************************************************** Const pcWQL = "Select * From Win32_PingStatus Where Address='%0%' And Timeout=%1%" Dim pvAns Dim pvWQL Dim pvAddr Dim pvObjLocator Dim pvObjServer Dim pvObjPing Dim pvPing pvAns = mcNameError pvWQL = pcWQL pvWQL = Replace(pvWQL,"%0%",pIPAddr) pvWQL = Replace(pvWQL,"%1%",FormatNumber(pTimeout,0,-1,0,0)) 'WMIでICMPを実行 Set pvObjLocator = CreateObject("WbemScripting.SWbemLocator") Set pvObjServer = pvObjLocator.ConnectServer() Set pvObjPing = pvObjServer.ExecQuery(pvWQL) For Each pvPing In pvObjPing pvAns = pvPing.StatusCode Next Set pvPing = Nothing Set pvObjPing = Nothing Set pvObjServer = Nothing Set pvObjLocator = Nothing On Error GoTo 0 '名前解決エラーの場合、pvAnsの値を補正 On Error Resume Next pvAns = Int(FormatNumber(pvAns,0,-1,0,0)) If Err.Number <> 0 Then pvAns = mcNameError End If On Error GoTo 0 IssueICMP = pvAns End Function Public Sub Echo (pStr) '*************************************************************************************************** ' Echo ' 指定した文字列を画面に出力する。 ' <引数> ' pStr : 出力する文字列 '*************************************************************************************************** WScript.Echo pStr End Sub
実行用バッチファイル
GetPCStatus.vbsを実行するサンプルバッチファイルです。
@echo off cd /d %~dp0 cscript //NOLOGO GetPCStatus.vbs %1 IF ERRORLEVEL 32768 GOTO NAMEERR IF ERRORLEVEL 16384 GOTO USAGE IF ERRORLEVEL 1 GOTO OFFLINE ECHO %1 is online (return : %ERRORLEVEL%) GOTO ENDING :NAMEERR ECHO %1 is name error (return : %ERRORLEVEL%) GOTO ENDING :USAGE ECHO Show usage (return : %ERRORLEVEL%) GOTO ENDING :OFFLINE ECHO %1 is offline (return : %ERRORLEVEL%) GOTO ENDING :ENDING