概要
VBAからPowerShellを非同期で実行し、.NETのSendWaitを実行するだけ
コード
''' <param name="iKeys">
'''送信する文字列
'''</param>
''' <param name="pSendDelayMilliSec">
'''SendWaitを実行する前の待ち時間(ミリ秒)。
'''PowerShell起動そのもののオーバヘッドもあるため、既定値は0ミリ秒
'''</param>
Public Sub AsyncSendKeys(ByVal iKeys As String, Optional ByVal pSendDelayMilliSec As Long = 0)
Dim psCmdTxt(4) As String
Let psCmdTxt(0) = "PowerShell.exe -sta -Command &""{"
Let psCmdTxt(1) = "Start-Sleep -Milliseconds " & pSendDelayMilliSec & ";"
Let psCmdTxt(2) = "Add-Type -AssemblyName System.Windows.Forms;"
Let psCmdTxt(3) = "[System.Windows.Forms.SendKeys]::SendWait('" & iKeys & "')"
Let psCmdTxt(4) = "}"
Call VBA.Shell(VBA.Join(psCmdTxt, ""), vbHide)
End Sub
経緯
- あるプログラムの操作を自動化しようと考えた。
- 該当のプログラムはCOMオブジェクトとして操作可能なため、自分の慣れもあってVBAを使うことにする。
- 大部分の処理が出来た時点で、一部操作がCOM側から操作不可能なことが判明(確認漏れ)。
- 幸いOfficeの
ExecuteMso
に相当するものが存在したので、GUIを表示させて、キーボード操作で対応することにする。 -
ExecuteMso
相当コマンドが、GUI表示中は呼び出し元の動作を停止する仕様であることが判明。 - 非同期でSendKeysすれば良いのでは?(上記のコード)
- 「呼び出し元」の動作を停止するので、PowerShellから非同期で
ExecuteMso
相当をすれば良いじゃん(最終結論)。
まとめ
PowerShellを使えばコマンドライン実行でも、COMオブジェクト操作・.NETライブラリの使用が可能。
あまり常用すべきでは無いと思うが、可能であることを知っておくのは悪くないと思う。