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)」は、下記よりダウンロードして下さい。
ダウンロード


コメント
コメントを投稿