P-COMマクロでホスト作業を自動化

 ホスト(=メインフレーム)ってまだ結構使っているところが多いように思います。
筆者が知る限り(3270系しか知りませんが)、エミュレータにPersonal Communications(P-COM)かFalconのどちらかを使っていて、どちらもマクロ機能があり、主に画面操作を自動化することが出来ます。
で、ちょっと前に、とあるホストの運用作業を自動化したいという話があったので、P-COMのホスト・アクセス・クラス・ライブラリーを使ったVBスクリプトを作ってみました。P-COMのホスト・アクセス・クラス・ライブラリーについては下記が参考になります。
http://www-01.ibm.com/support/knowledgecenter/SSEQ5Y_5.9.0/com.ibm.pcomm.doc/books/html/host_access08.htm?lang=ja
基本的にP-COM起動やホスト接続、終了以外は、画面の座標軸(縦と横)に対して文字を入力したり、指定場所に表示されているのが特定の文字かをチェックするという繰り返しになると思いますので、VBSではそれらをサブルーチンにしてます。
また、スクリプトの引数として、ログインIDとパスワード及び、事前に用意が必要な接続プロファイル(拡張子がwsのやつ)を指定する形になってます。

'2秒*30でタイムアウト判定
Const DEF_MAXCOUNT = 30

Dim oConnMGR, oECLPS, oECLOIA
Dim oParam, HUserID, HPassWd, ProFile
Dim i, idx

Set oParam = WScript.Arguments

For idx = 0 To oParam.Count - 1 
   Select Case idx
   Case 0
      HUserID = UCase( oParam(idx) )
   Case 1
      HPassWd = UCase( oParam(idx) )
   Case 2
      ProFile = oParam(idx)
   End Select
Next
'''''引数エラー処理割愛

'PCOMオブジェクトの作成
Set oConnMGR = CreateObject("PCOMM.autECLConnMgr")
Set oECLPS = CreateObject("PCOMM.autECLPS")
Set oECLOIA = CreateObject("PCOMM.autECLOIA")

'接続開始
Host_Start

If Check_Host("DISP3270") = false Then
	WScript.Sleep(10000)
	If Check_Host("DISP3270") = false Then
		Host_End
		WScript.Quit(-11)
	End If
End If

'(13/01) ログイン [LOGON ユーザーID] + CTL
Host_Input 13, 1, "LOGON " & HUserID , "[enter]", 1

'(8/20) パスワード [      ] + CTL 2回
Host_Input 8, 20, HPassWd , "[enter]", 2

Dim iPutLine, InputCmd

'画面遷移チェック (4,59) ユーザーIDが表示されるのをチェック
If Host_OutputChk(4, 59, Len(HUserID), HUserID) = False Then
	'エラー
	Host_Input 0, 0, "", "[pf3]", 2
End If

・・・以下省略

'終了
'F3 2回で後処理へ戻る
Host_Input 0, 0, "", "[pf3]", 2

'(5/27) 印刷せずにデータセットを削除「2」を選択 [2] + CTL
Host_Input 4, 27, "2", "[enter]", 1

'(2/01) ログオフ [LOGOFF] + CTL
Host_Input 2, 1, "LOGOFF", "[enter]", 1

'切断
Host_End

'ここでスクリプト終了
WScript.Quit(0)

'以下サブルーチン
'1 ホスト接続開始
Sub Host_Start
	
	oConnMGR.autECLConnList.Refresh
	
	'事前に取得したコネクションの数だけループして接続を停止する
	For i = 1 To oConnMGR.autECLConnList.Count   
		oConnMGR.autECLConnList(i).StopCommunication()
		WScript.Sleep 5000
		oConnMGR.StopConnection oConnMGR.autECLConnList(i).Name, "saveprofile=no"
		WScript.Sleep 5000
	Next

	Dim strCmd
	strCmd = "profile=" & ProFile & " connname=A"
	oConnMGR.StartConnection strCmd 
End Sub

'2 ホスト接続終了
Sub Host_End
	
	oConnMGR.autECLConnList.Refresh
	If oConnMGR.autECLConnList.Count > 0 Then
		oConnMGR.StopConnection "A", "saveprofile=no"
		WScript.Sleep 3000
	End If
End Sub

'3 ホストセッションの取得(接続タイプ)
Function Check_Host(ConnType)

	For i = 0 To DEF_MAXCOUNT
		oConnMGR.autECLConnList.Refresh
		If oConnMGR.autECLConnList.Count > 0 Then
			Exit For
		End If
		WScript.Sleep 2000
	Next

	For i = 1 To oConnMGR.autECLConnList.Count   '取得したコネクションの数だけループ
	    If oConnMGR.autECLConnList(i).ConnType = ConnType Then
	        '該当セッションのハンドルからセッションオブジェクトをセット
	        oECLPS.SetConnectionByHandle (oConnMGR.autECLConnList(i).Handle)
	        oECLOIA.SetConnectionByHandle (oConnMGR.autECLConnList(i).Handle)
	        Exit For
	    End If
	Next
	Check_Host = True
	If i > oConnMGR.autECLConnList.Count Then
		Check_Host = False
	Else
		For i = 0 To DEF_MAXCOUNT
			WScript.Sleep 2000
			'処理完了待ち
			If oECLOIA.InputInhibited = 0 Then
				If Host_OutputChk(12, 16, 5, "*****") = True Then
					Exit For
				End If
			End If
		Next
		'起動確認タイムアウト
		If i >= DEF_MAXCOUNT Then
			Host_End
			WScript.Quit(-2)
		End If
	End If

End Function

'4 ホスト画面への入力(Y座標、X座標、文字列、キー入力、キー入力回数)
Sub Host_Input(argY, argX, argStr, argKeyStr, argKeyCnt)
	Dim iKey
	
	If argY <> 0 And argX <> 0 Then
		oECLPS.SetCursorPos argY, argX
		oECLPS.SendKeys argStr
	End If
	
	'エンターキー
	If argKeyStr <> "" Then
		For iKey = 1 To argKeyCnt
			oECLPS.SendKeys argKeyStr
			For i = 0 To DEF_MAXCOUNT * 10
				WScript.Sleep 200
				'処理完了待ち
				If oECLOIA.InputInhibited = 0 Then
					Exit For
				End If
			Next
			If i >= DEF_MAXCOUNT * 10 Then
				Host_End
				WScript.Quit(-2)
			End If
		Next
	End If

End Sub

'5 画面表示内容のチェック(Y座標、X座標、文字列の長さ、文字列 一致したらtrueを返す
Function Host_OutputChk(argY, argX, argLen, argStr)

	Dim strBuff
	
	strBuff = oECLPS.GetTextRect(argY, argX, argY, argX + argLen-1)
	If Trim(strBuff) = Trim(argStr) Then
		Host_OutputChk = True
	Else
		Host_OutputChk = False
	End If

End Function

やっかいなのは、あくまで画面操作なので接続とか応答に時間が掛かったり、いろいろ問題が出てきます。
ちょっと雑にSleepをガンガンかましていますが、お察しください。。