HSPでコマンドプロンプトを制御する
1.概要
最近は、Excel VBAやPythonなどによる自動化というキーワードを良く耳にしますが、昔からある自動化で最も安定性が
あり、比較的単純な手順の記述とコマンド発行といったコマンドプロンプトによる操作およびバッチファイルによる自動処理
があります。システムの運用管理者やネットワーク管理者の人達も多く利用されています。
筆者も一時期は、良く利用していましたがGUIの操作に慣れ過ぎて最近は利用する機会も減ってきています。
今回は、HSP言語によるコマンドプロンプトを操作して外部から文字列(コマンド)を送信する方法を模索して見たいと思います。
2.コマンドプロンプトに文字列送信
コマンドプロンプトにGUI画面上からキー入力された文字列を送信する方法について説明します。
まず、概略の処理の流れを整理します。
(1) コマンドプロンプトを起動させる。
ただし、環境依存を無くすため環境変数'comspec'より取得したパス名を、exec命令のp1パラメータとして渡す。
(2) 入力ボックス等より入力したコマンド( テキスト文字列 )をクリップボードにコピーする。
(3) コマンドプロンプト画面をアクティブにする。
(4) クリップボードよりコマンドを貼り付ける。 整理すると、これらの処理を実現させるためには、
マジックNoの送信は、Windows APIのPostMessageを利用して行います。
(例)コピー操作を実行する場合
PostMessage hDosWin,WM_COMMAND,65520,0 とします。このコード送信でコマンドプロンプトのメニューからコピー操作を実行したことになります。 3.使用方法 コマンドプロンプトの遠隔操作 (cmdctrl.exe)を起動します。画面は、dirコマンドを 実行した様子です。直接、コマンドプロンプト画面にコマンドを入力するか、GUI画面の入力ボックスにコマンドを 入力して、[Enter]キーもしくは、実行ボタンをクリックします。
各操作ボタンの機能は、次の通りです。
5.ダウンロード 提供するソースコードのライセンスは、CC0 (クレジット表示不要、改変可、商用可) とします。自由に利用して頂いてかまいません。 尚、データの取得やプログラム実行において損害等が生じた場合は、筆者は一切の責任も負いません。全て自己責任でお願いします。
「コマンドプロンプトの遠隔操作(cmdctrl.exe)」は、下記よりダウンロードして下さい。
ダウンロード
まず、概略の処理の流れを整理します。
(1) コマンドプロンプトを起動させる。
ただし、環境依存を無くすため環境変数'comspec'より取得したパス名を、exec命令のp1パラメータとして渡す。
(2) 入力ボックス等より入力したコマンド( テキスト文字列 )をクリップボードにコピーする。
(3) コマンドプロンプト画面をアクティブにする。
(4) クリップボードよりコマンドを貼り付ける。 整理すると、これらの処理を実現させるためには、
-
・環境変数'comspec'よりパス名を取得する処理
・クリップボードにテキスト文字列をコピーする処理
・任意の画面をアクティブにする処理
・クリップボードよりテキスト文字列を貼り付ける処理
MENU | 機能 | Magic No |
0 | コピー | 65520 |
1 | 貼り付け | 65521 |
4 | 検索 | 65524 |
5 | 全て選択 | 65525 |
マジックNoの送信は、Windows APIのPostMessageを利用して行います。
(例)コピー操作を実行する場合
PostMessage hDosWin,WM_COMMAND,65520,0 とします。このコード送信でコマンドプロンプトのメニューからコピー操作を実行したことになります。 3.使用方法 コマンドプロンプトの遠隔操作 (cmdctrl.exe)を起動します。画面は、dirコマンドを 実行した様子です。直接、コマンドプロンプト画面にコマンドを入力するか、GUI画面の入力ボックスにコマンドを 入力して、[Enter]キーもしくは、実行ボタンをクリックします。
各操作ボタンの機能は、次の通りです。
-
・[非表示] : コマンドプロンプト画面を非表示にします。
・[表示] : 非表示状態のコマンドプロンプト画面を表示にします。
・[閉じる] : cmdctrl.exeを終了します。
・[全て選択] : コマンドプロンプト画面の表示を全て選択状態にします。
・[複写] : コマンドプロンプト画面上の内容(選択したもの)をコピーします。
・[貼付] : クリップボード内にコピーしてある内容を貼付します。
・[検索] : コマンドプロンプトの検索ダイアログを表示します。
・[Editor] : メモ帳を表示します。
;**** (cmdmod.hsp) ***** #module "cmdmod" ;***** 必要となるAPIや定数の定義 ***** #uselib "user32.dll" #cfunc global GetForegroundWindow "GetForegroundWindow" #cfunc global GetWindowThreadProcessId "GetWindowThreadProcessId" int,int #func global AttachThreadInput "AttachThreadInput" int,int,int #func global SetForegroundWindow "SetForegroundWindow" int #func global SendMessage "SendMessageA" int,int,int,int #func global FindWindow "FindWindowA" int,int #func global MoveWindow "MoveWindow" int,int,int,int,int,int #func global GetWindowRect "GetWindowRect" int,int #func global OpenClipboard "OpenClipboard" int #func global SetClipboardData "SetClipboardData" int,int #func global EmptyClipboard "EmptyClipboard" #func global CloseClipboard "CloseClipboard" #func global ShowWindow "ShowWindow" int,int #func global PostMessage "PostMessageA" int,int,int,int #func global MapVirtualKey "MapVirtualKeyA" int,int #func global keybd_event "keybd_event" int,int,int,int #uselib "kernel32.dll" #cfunc global GetCurrentThreadId "GetCurrentThreadId" #func global GetEnvironmentVariable "GetEnvironmentVariableA" var,var,int #func global GlobalAlloc "GlobalAlloc" int,int #func global GlobalLock "GlobalLock" int #func global GlobalUnlock "GlobalUnlock" int #func global lstrcpy "lstrcpy" int,int #func global GetVersionEx "GetVersionExA" int #define global CF_OEMTEXT $00000007 #define global MAX_PATH 260 #define global WM_SYSCOMMAND $00000112 #define global SC_CLOSE $0000F060 #define global WM_COMMAND $00000111 #define global SW_HIDE 0 #define global SW_SHOW 5 #define global SW_RESTORE 9 #define global EM_SETMARGINS $000000D3 ;***** アクティブウィンドウの制御 ***** #deffunc actwin int prm1 ; prm1 : アクティブのウィンドウハンドル handle=prm1 if handle!0 : hsphwnd=handle : else : hsphwnd=hwnd if hsphwnd==0 : return -1 ThreadId1=GetWindowThreadProcessId(GetForegroundWindow(),varptr(PID)) ThreadId2=GetCurrentThreadId() AttachThreadInput ThreadId2,ThreadId1,1 SetForegroundWindow hsphwnd AttachThreadInput ThreadId2,ThreadId1,0 return 0 ;***** 環境変数の取得 (COMSPEC) ***** #deffunc getenvval var prm1 ; prm1 : 境変数の取得用変数 sdim cp,MAX_PATH+2 ev="Comspec" ;環境変数(COMSPEC)を設定 GetEnvironmentVariable ev,cp,MAX_PATH+2 prm1=cp : ret=stat sdim cp,0 return ret ;***** クリップボードにテキストデータを設定 ***** #deffunc setcliptext str prm1 ; prm1 : テキストデータ設定用文字列 or 文字列変数 OpenClipboard ret=stat : if ret!0 : EmptyClipboard ;GMEM_MOVEABLE 2 ls=strlen(prm1)+1 : sdim strData,ls strData = prm1 GlobalAlloc 2,ls lngHwnd=stat if lngHwnd!0 { GlobalLock lngHwnd lngMem=stat if lngMem!0 { lstrcpy lngMem,varptr(strData) : ret=stat if ret!0 { SetClipboardData CF_OEMTEXT,lngHwnd lngRet=stat } GlobalUnlock lngHwnd : lngRet=stat } } CloseClipboard : sdim strData,0 return stat ;***** コンソール画面の表示・非表示モード制御 ***** #deffunc dosdspshow int prm1,int prm2 ; prm1 : コンソールのウィンドウハンドル ; prm2 : 表示モード = 0 , 非表示モード = 1 hDosWin = prm1 : if hDosWin==0 : return -1 nMode = prm2 : if (nMode<=0)|(nMode>1) : nMode=0 if nMode==0 : dspflg=SW_RESTORE if nMode==1 : dspflg=SW_HIDE ShowWindow hDosWin,dspflg return 0 ;***** 起動しているコンソール画面を閉じる ***** #deffunc dosclose int prm1 ; prm1 : コンソールのウィンドウハンドル hDosWin = prm1 : if hDosWin==0 : return -1 SendMessage hDosWin,WM_SYSCOMMAND,SC_CLOSE,0 return 0 ;***** コンソール画面のリモート制御モード設定 ***** #deffunc doscmd int prm1,int prm2 ; prm1 : コンソールのウィンドウハンドル ; prm2 : 制御モード ; mode=0 : コピー ; mode=1 : 貼付 ; mode=3 : 検索 ; mode=4 : 全て選択 hDosWin = prm1 : if hDosWin==0 : return -1 nMode = prm2 : if (nMode<=0)|(nMode>4) : nMode=0 if nMode==0 : PostMessage hDosWin,WM_COMMAND,65520,0 if nMode==1 : PostMessage hDosWin,WM_COMMAND,65521,0 if nMode==3 : PostMessage hDosWin,WM_COMMAND,65524,0 if nMode==4 : PostMessage hDosWin,WM_COMMAND,65525,0 return 0 ;***** コンソール画面にキーコードを送信 ***** #deffunc doskeysend int prm1,int prm2,int prm3 ; prm1 : 仮想キーコード(1個目) ; prm2 : 仮想キーコード(2個目) ; prm3 : キー送信モード ; mode=0 : 単独キー送信, mode=1 : 同時キー送信 ; (例) ; doskeysend 13 : Enter Keyのみ送信 ; doskeysend ,,2 : ハンドルのみを取得 ; doskeysend 18,70,1 : ALT + F nKeyCode1 = prm1 : if (nKeyCode1<=0)|(nKeyCode1>255) : nKeyCode1=0 nKeyCode2 = prm2 : if (nKeyCode2<=0)|(nKeyCode2>255) : nKeyCode2=0 nMode = prm3 : if (nMode<=0)|(nMode>2) : nMode=0 ;OSの種別取得 dim os_ver_info,37 : os_ver_info(0)=148 GetVersionEx varptr(os_ver_info) if os_ver_info(4)=2 { lpClassName="ConsoleWindowClass" }else{ lpClassName="tty" } dim os_ver_info,0 FindWindow varptr(lpClassName),0 hDosWin=stat : if hDosWin=0 : return -1 ;ハンドルのみを取得 if nMode==2 : return hDosWin SetForegroundWindow hDosWin ;単独キー送信の場合 if nMode==0 { MapVirtualKey nKeyCode1,0 : convkey=stat keybd_event nKeyCode1,convkey,0,0 keybd_event nKeyCode1,convkey,2,0 } ;同時キー送信の場合 if nMode==1 { MapVirtualKey nKeyCode1,0 : convkey=stat keybd_event nKeyCode1,convkey,0,0 MapVirtualKey nKeyCode2,0 : convkey=stat keybd_event nKeyCode2,convkey,0,0 wait 2 keybd_event nKeyCode1,convkey,2,0 keybd_event nKeyCode2,convkey,2,0 } return hDosWin #global
;***** コマンドプロンプトの遠隔操作 (cmdctrl.hsp) ***** ;***** 実行ファイル自動作成 **** #packopt type 0 #packopt name "cmdctrl" #packopt runtime "hsprt" #packopt manifest "app.manifest" #packopt icon "sample.ico" #packopt hide 1 #include "cmdmod.hsp" #uselib "user32.dll" #func SetFocus "SetFocus" int #const WshNormalNoFocus 4 #const WshHide 0 ;***** 起動ディレクトリ取得 ***** sdim Startdir,512 if hspstat&1=0 { Startdir=dir_exe+"¥¥" : chdir dir_exe } else { Startdir=dir_cur+"¥¥" } chdir Startdir onexit *owari screen 0,650,120,0,ginfo(20)-650>>1,(ginfo(21)-120>>1)+200 title "Command Prompt - KeySendConsole Ver1.0" ;***** 利用するエディタ ***** editfile="notepad.exe" ;***** コマンドプロンプトを起動 ***** getenvval cp newcom WshShell, "WScript.Shell" WshShell->"Run" cp,WshHide,0 wait 50 gosub *dosmove delcom WshShell wait 10 sdim ms,1024 redraw 0 font "Meiryo UI",12 : objmode 2 pos 10,4 : input ms,ginfo(10)-80,22 PostMessage objinfo(0,2),EM_SETMARGINS,3,3 objsize 50,22 pos ginfo(10)-68,3 : button "実行", *mode01 objsize 60,24 pos 10,32 : button "非表示", *mode02 pos 72,32 : button "表示", *mode03 pos 134,32 : button "閉じる", *mode04 pos 10,62 : button "全て選択",*mode05 pos 72,62 : button "複写", *mode06 pos 134,62 : button "貼付", *mode07 pos 196,62 : button "検索", *mode08 pos 258,62 : button "Editor", *editor objsize 40,20 pos 210,38 : mes "Left" : pos 245,34 : input x pos 300,38 : mes "Top" : pos 330,34 : input y pos 375,38 : mes "Width" : pos 415,34 : input w pos 460,38 : mes "Height" : pos 500,34 : input h objsize 94,24 pos 544,32 : button "位置サイズ変更",*winposchg onkey *kevent gsel 0,1 SetFocus hwnd : actwin hwnd : objsel 0 redraw 1 stop ;***** Enterキーで実行 ***** *kevent if (iparam!13)|(lparam>>30) : stop objsel -1 : if (stat!0)|(ms="") : actwin hDosWin goto *mode01 ;***** コマンドをクリップボードにセットして送信する ***** *mode01 ;ハンドルを再確認して画面が閉じられていたら、起動させる gosub *getdoshwnd if hDosWin=-1 : exec cp : wait 50 gosub *getdoshwnd ;コマンドをクリップボードにセットしてコンソール画面に貼付ける ;***** 空のEnterキーのみも受け付けるように修正 ***** ls=strlen(ms) : if ls==0 : actwin hDosWin setcliptext ms gosub *clipset wait 10 actwin hwnd : objsel 0 sendmsg objinfo(0,2),$0303,0,0 stop ;***** コンソール画面を非表示にする ***** *mode02 gosub *getdoshwnd if hDosWin=-1 : stop dosdspshow hDosWin,1 wait 10 actwin hwnd : objsel 0 stop ;***** コンソール画面を表示する ***** *mode03 gosub *getdoshwnd if hDosWin=-1 : stop dosdspshow hDosWin,0 wait 10 actwin hwnd : objsel 0 stop ;***** コンソール画面を閉じる ***** *mode04 gosub *getdoshwnd if hDosWin=-1 : stop dosclose hDosWin end ;***** 全て選択 ***** *mode05 gosub *getdoshwnd if hDosWin=-1 : stop doscmd hDosWin,4 stop ;***** 複写 ***** *mode06 gosub *getdoshwnd if hDosWin=-1 : stop doscmd hDosWin,0 stop ;***** 貼付 ***** *mode07 gosub *getdoshwnd if hDosWin=-1 : stop doscmd hDosWin,1 stop ;***** 検索 ***** *mode08 gosub *getdoshwnd if hDosWin=-1 : stop doscmd hDosWin,3 stop ;***** コンソール画面のサイズ・位置を変更(起動時のみ) ***** *dosmove gosub *getdoshwnd if hDosWin=-1 : stop dim rc,4 GetWindowRect hDosWin,varptr(rc) w = rc(2)-rc(0) h = rc(3)-rc(1) ; HSPのScreen横幅と同じとする MoveWindow hDosWin,ginfo(20)-650>>1,(ginfo(21)-h>>1)-130,650,h,1 ; コンソール画面を表示 (起動時は非表示のものを戻す処理) gosub *getdoshwnd if hDosWin=-1 : stop dosdspshow hDosWin,0 wait 10 actwin hwnd ; デフォルトの位置とサイズを再取得 GetWindowRect hDosWin,varptr(rc) w = rc(2)-rc(0) h = rc(3)-rc(1) x = rc(0) y = rc(1) return ;***** コンソール画面のサイズ・位置を変更 ***** *winposchg gosub *getdoshwnd if hDosWin=-1 : stop MoveWindow hDosWin,x,y,w,h,1 stop ;***** コンソール画面のハンドル取得 ***** *getdoshwnd doskeysend ,,2 : hDosWin=stat return ;***** 貼付処理 ***** *clipset doscmd hDosWin,1 ;▼▼▼ 十分なウェイトを確保して下さい。 ▼▼▼ wait 50 doskeysend 13 return *editor if editfile="" : editfile="notepad.exe" exec editfile stop ;***** 終了処理 ***** *owari ;終了時に開いているコンソール画面を閉じる gosub *getdoshwnd if hDosWin!-1 : dosclose hDosWin end
5.ダウンロード 提供するソースコードのライセンスは、CC0 (クレジット表示不要、改変可、商用可) とします。自由に利用して頂いてかまいません。 尚、データの取得やプログラム実行において損害等が生じた場合は、筆者は一切の責任も負いません。全て自己責任でお願いします。
「コマンドプロンプトの遠隔操作(cmdctrl.exe)」は、下記よりダウンロードして下さい。
ダウンロード
コメント
コメントを投稿