2020年6月19日金曜日

[VBA] 14. 他のプログラムを実行

VBAから他のプログラムを実行する方法について。Shell関数を使う方法もあるが、どうやら非同期(処理が終わるまで待ってくれない)らしいので今回は記載しない。



WshShell オブジェクト
object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])

 strCommand : 起動するプログラムのコマンド (環境変数に対応)
 intWindowStyle : ウィンドウの外観を示す整数値
 bWaitOnReturn : プログラムの実行が終了するまで待つかどうか (TRUE/FALSE)

intWindowStyle の整数値の割り当てを以下に示す。

整数値 内容
0 ウィンドウを非表示にし、別のウィンドウをアクティブにします。
1 ウィンドウをアクティブにして表示します。
ウィンドウが最小化または最大化されている場合は、元のサイズと位置に戻ります。
アプリケーションでウィンドウを最初に表示するときには、このフラグを指定してください。
2 ウィンドウをアクティブにし、最小化ウィンドウとして表示します。
3 ウィンドウをアクティブにし、最大化ウィンドウとして表示します。
4 ウィンドウを最新のサイズと位置で表示します。
アクティブなウィンドウは切り替わりません。
5 ウィンドウをアクティブにし、現在のサイズと位置で表示します。
6 指定したウィンドウを最小化し、Z オーダー上で次に上位となるウィンドウをアクティブにします。
7 ウィンドウを最小化ウィンドウとして表示します。
アクティブなウィンドウは切り替わりません。
8 ウィンドウを現在の状態で表示します。
アクティブなウィンドウは切り替わりません。
9 ウィンドウをアクティブにして表示します。
ウィンドウが最小化または最大化されている場合は、元のサイズと位置に戻ります。
アプリケーションで最小化ウィンドウを復元するときには、このフラグを指定してください。
10 アプリケーションを起動したプログラムの状態に基づいて、表示状態を設定します。


メモ帳を起動してみる
試しにデスクトップに用意したテキストファイル(AAA.txt)をメモ帳で開いてみた。
Dim txtPATH As String
Dim wsh     As Object
Dim resp    As Integer

txtPATH = "C:\Users\xxxx\Desktop\AAA.txt"  '全角禁止

Set wsh = CreateObject("WScript.Shell")
wsh.Run "notepad.exe" & " " & txtPATH, 1, True
Set wsh = Nothing


TeraTermを起動してみる
VBA からTeraTerm を起動して処理するには、TeraTermマクロ(ttlファイル)を使うと簡単にできるらしいので実際にやってみた。
今回はttlファイルをVBAで書いて出力したが、ベースとなるttlファイルを用意しておいて、変数を引数で与えたり値を置換したりする方がいいのでは思う。
Sub TeraTermSample()

    'パラメータ情報
    '------------------------------
    Dim PATH As String  'TeraTermマクロパス
    Dim HOST As String  'ホスト
    Dim USER As String  'ログインユーザ
    Dim PASS As String  'ログインパスワード
    
    PATH = "C:\Program Files (x86)\teraterm\ttpmacro.exe"
    HOST = "127.0.0.1"
    USER = "xxxx"
    PASS = "yyyy"
    
    'ttlファイル作成
    '------------------------------
    Dim ttlPATH As String
    Dim FN As Integer
    
    ttlPATH = "C:\Users\xxxx\Desktop\temp.ttl"  '全角禁止
    FN = FreeFile
    
    Open ttlPATH For Output As #FN
    
    Print #FN, "; 接続"
    Print #FN, "connect '"; HOST; ":22 /ssh /2 /auth=password /user="; USER; " /passwd="; PASS; " /nosecuritywarning'"
    Print #FN, "if result != 2 then"
    Print #FN, "    setexitcode 1"
    Print #FN, "    end"
    Print #FN, "endif"
    Print #FN, ""
    Print #FN, "; 処理"
    Print #FN, "wait '$' '#'"
    Print #FN, "sendln 'cd work'"
    Print #FN, "sendln './test.sh'"
    Print #FN, ""
    Print #FN, "; 終了"
    Print #FN, "closett"
    Print #FN, "end"
    
    Close #FN
    
    'TeraTerm実行 (WScript.Shell)
    '------------------------------
    Dim wsh As Object
    Dim resp As Integer
    
    Set wsh = CreateObject("WScript.Shell")
    resp = wsh.Run("""" & PATH & """""" & ttlPATH & """", 1, True)
    
    If resp = 1 Then
        MsgBox "失敗"
    End If
    
    Set wsh = Nothing

    'ttlファイル削除
    '------------------------------
    Kill ttlPATH

End Sub

とりあえず、上記でSSH接続とコンソール処理はできた。
戻り値が不要であれば、Runメソッドの記述は以下のようになる。
wsh.Run """" & PATH & """""" & ttlPATH & """", 1, True

また、ttlファイルとTeraTermマクロ(ttpmacro.exe)の関連付けを行っているならば、TeraTermマクロのパスは不要になる。
関連付けは、適当なttlファイルを右クリック → プログラムから開く → 別のプログラムを選択 → TeraTermマクロを選択 & 「常にこのアプリを使って .ttl ファイルを開く」のチェックボックスにチェック → [OK] で出来るはず。
resp = wsh.Run(ttlPATH, 1, True)


おまけ
VBAの話から脱線するが、、、TeraTermマクロはたくさんのコマンドが用意されていて、色々なことができるみたい。その中でもSCPプロトコルでファイルを送受信するコマンドが気になったので試してみた。以下の2つのコマンドを使う。

scpsend <file name> [<destination file name>]
scprecv <remote file name> [<local file name>]

ただ、困ったことにファイルの送受信が完了するまで待ってくれないらしく、一工夫必要とのこと。
call login
call file_send
call file_recv
closett  ; TeraTerm 終了
end      ; マクロ終了

;---------------------------------------
; ログイン
;---------------------------------------
:login

    ; 接続
    connect '127.0.0.1:22 /ssh /2 /auth=password /user=xxxx /passwd=yyyy /nosecuritywarning'

    ; 接続できなかった場合は 1 を返す
    if result != 2 then
        setexitcode 1
        end
    endif

    ; 入力できる状態まで待つ
    wait '$' '#'

    ; 作業ディレクトリに移動
    sendln 'cd work'

return

;---------------------------------------
; SCPプロトコルでファイルを送信
;---------------------------------------
:file_send

    ; ローカルファイル名と送信先ファイル名を指定
    localfn = 'C:\Users\xxxx\Desktop\AAA.txt'
    destfn  = '~/work'

    ; 送信
    scpsend localfn destfn

    ; 転送完了まで待つ
    do
      mpause 3000
      sendln 'ps -ef | grep -v grep | grep -c scp'
      waitln '0' '1'
    loop while result != 1

return

;---------------------------------------
; SCPプロトコルでファイルを受信
;---------------------------------------
:file_recv

    ; リモートファイル名とローカルファイル名を指定
    remotefn = '/home/etoh/work/AAA.txt'
    localfn  = 'C:\Users\xxxx\Desktop\BBB.txt'  ; ファイル名まで必要

    ; ローカルファイルが既に存在する場合は削除しておく
    filesearch localfn
    if result then
        filedelete localfn
    endif

    ; 受信
    scprecv remotefn localfn

    ; 転送完了まで待つ
    do
      mpause 3000
      sendln 'ps -ef | grep -v grep | grep -c scp'
      waitln '0' '1'
    loop while result != 1

return



0 件のコメント:

コメントを投稿