tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルキーストロークのシュミレートについて
記事No3186
投稿日: 2006/02/24(Fri) 23:38
投稿者hide
[OSのVer]:WindowsXP SP2  [VBのVer]:VB.NET 2005

いろいろ教えてください。
DOSのアプリをVBから操作しようと思い情報を探していたところ
このページにたどり着きました。
花ちゃんさんやなおこ(・∀・)さんのキーストローク関連のサンプルコード
hhttp://www.bcap.co.jp/hanafusa/bbs/wforum.cgi?mode=allread&no=2550#2558
をそのままコピペして使用したところDOS窓で動くアプリでの使用ができなくて困っています。
いくつかのDOSアプリを試してみましたがUp,Down,Right,Leftキーは問題なく動作するのですが
それ以外のキーについてはうまく動いてくれません。
どのような理由で動かないのか初心者の私には全く見当もつきません。
ちなみにVB6 + Windows98の環境では問題なく花ちゃんさんのサンプルコードで
思い通りの動作をしてくれます。よろしかったら理由など教えてください。
環境は
WindowsXP SP2 + VB2005にて
ファイル管理ツール FD (hhttp://www.vector.co.jp/download/file/dos/util/fh045270.html)
を使用して動作確認しています。

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Button1.Click
        '試しにアプリケーションの終了
        AppActivate("コマンド プロンプト - fd")
        Me.StopTime(100)         'アクティブになるまで待つ
        'For i As Integer = 1 To 10 'このような連続使用も問題なし
        Me.sSetSendKeys(Keys.Escape)
        Me.sSetSendKeys(Keys.Y)
        'Next
End Sub

[ツリー表示へ]
タイトルRe: キーストロークのシュミレートについて
記事No3188
投稿日: 2006/02/25(Sat) 00:42
投稿者YAS
SendKeysはDOS窓にもキーストロークを送信できるようです。
しかし,AppActive関数がDOS窓のコンソールアプリケーションをアクティブにできるのかは
疑問です。AppActive関数のヘルプにもできないようなことが書いてあります。(VB6.0のヘルプではな
いですが。)

hhttp://www.microsoft.com/japan/msdn/library/default.asp?
url=/japan/msdn/library/ja/vblr7/html/vastmappactivate.asp

マウスを使って手動でDOS窓をアクティブにして試してみたらどうでしょう?

[ツリー表示へ]
タイトル残念ながら・・・
記事No3195
投稿日: 2006/02/26(Sun) 15:15
投稿者hide
YASさんありがとうごさいました。
ご指摘通りアクティブ関係をいろいろ試してみましたが
結果は変わりませんでした。
ただのコマンドプロンプトにはキー情報が送信されますが
(ってことはアクティブになってる!?)DOSアプリケーション
になると使用できるキーと使用できないキーがあるようです。
VB6+Win98では問題なくキーが送信されてDOSアプリが操作できるんですが・・・
.NETにも方法があるようなきがしますが自分の能力では苦しい
感じがします。ほかにも良き情報がありましたら宜しくお願い致します。

[ツリー表示へ]
タイトルRe: 残念ながら・・・
記事No3197
投稿日: 2006/02/26(Sun) 19:13
投稿者YAS
-----訂正 このコメントは大嘘でした こめんなさい YAS -----

ちょっと調べてみたところ,コマンドプロンプトと俗にいうDOS窓は違ったものの
ようです。

コマンドプロンプトはCMD.exeという(たぶん)32bitのソフトウェアですが,
DOS窓はDOS用の16bitソフトウェアを動かすためのNTVDM(NT Virtual Dos Machine)
です。

この2つは見た目は似ているのですが,内部的には全然異なるもののようです。
素人考えですが,簡単な方法で32bit-16bitの境界を越えてキーストロークを
送るのは無理なのではないかと思います。

DOS窓の中のソフトを自動化したければ,DOS窓の中に常駐する16bitのソフトを作成し,
そのソフトでキーストロークをエミュレーションしたらよいのではないでしょうか。

[ツリー表示へ]
タイトルRe^2: 残念ながら・・・
記事No3200
投稿日: 2006/02/26(Sun) 21:25
投稿者YAS
前に書いたことは大嘘でした!!
すみません。

・VB2005のSendkeys.Send
・Win32APIのSendInput
・Win32APIのkeybd_event

の3つを試してみまたところ,
SendInputとkeybd_eventでキーストロークを送れました。

[ツリー表示へ]
タイトルRe^3: 残念ながら・・・
記事No3201
投稿日: 2006/02/26(Sun) 21:34
投稿者花ちゃん
> ・VB2005のSendkeys.Send
> ・Win32APIのSendInput
> ・Win32APIのkeybd_event
>
> の3つを試してみまたところ,
> SendInputとkeybd_eventでキーストロークを送れました。

私も試したのですが送れませんでしたが、どのようにされたのでしょうか?

[ツリー表示へ]
タイトルRe^4: 残念ながら・・・
記事No3202
投稿日: 2006/02/26(Sun) 21:55
投稿者YAS
まず,keybd_eventの例です。(VB2005です)

FD55.COMをダブルクリックして起動しておきます。
タスクマネージャでntvdn.exeのプロセスIDを調べておきます。

フォームにButtonコントロールを1つ配置します。
下のコードを貼り付けます。
ntvdn.exeのプロセスIDにAppActivate関数の引数を書き換えます。
実行して,フォームのButtonコントロールをクリックします。
「FDを終了しますか?」とFDがメッセージを表示します。

Imports System.Runtime.InteropServices
Imports System.Threading.Thread

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles Button1.Click
        AppActivate(10752) 'タスクマネージャを見て,プロセスID(PID)を入れる
        Sleep(100)
        KeyBoardEvent.Send(bVk.VK_ESCAPE)
    End Sub

End Class

Public Class KeyBoardEvent

    Private Const KEYEVENTF_KEYUP As Integer = &H2

    <DllImport("user32.dll")> Public Shared Sub keybd_event( _
        ByVal bVk As Byte, ByVal bScan As Byte, _
        ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
    End Sub

    <DllImport("user32.dll")> Public Shared Function MapVirtualKey( _
        ByVal wCode As Integer, _
        ByVal wMapType As Integer) _
        As Integer
    End Function

    Public Shared Sub Send(ByVal bVk As Byte)
        Call keybd_event(bVk, MapVirtualKey(CInt(bVk), 0), _
                         ExtendedKeyFlag(bVk) Or 0, 0)
        Call keybd_event(bVk, MapVirtualKey(CInt(bVk), 0), _
                         ExtendedKeyFlag(bVk) Or
KEYEVENTF_KEYUP, 0)
    End Sub

    Private Shared Function ExtendedKeyFlag(ByVal Key As Byte) As Byte
        Return 0 'ExtendedKeyの処理を省略しています(矢印キーはExtendedKeyなので注意)
    End Function

End Class

Public Enum bVk As Byte
    VK_ESCAPE = &H1B 'ESC key
    VK_X = &H58 'X key
    VK_C = &H43 'C key
    VK_D = &H44 'D key
    VK_R = &H52 'R key
    VK_S = &H53 'S key
    VK_F = &H46 'F key
    VK_T = &H54 'T key
    VK_L = &H4C 'L key
    VK_U = &H55 'U key
End Enum

[ツリー表示へ]
タイトルRe^4: 残念ながら・・・
記事No3203
投稿日: 2006/02/26(Sun) 22:08
投稿者YAS
次にSendInputの例です。
手順はkeybd_eventの例と同じです。
手持ちのSendInputのコードそのままなので,長くてもうし訳ありません。

Imports System.Runtime.InteropServices
Imports System.Threading.Thread

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, _
                           ByVal e As System.EventArgs) Handles MyBase.Load
        AppActivate(10752) 'タスクマネージャを見て,プロセスID(PID)を入れる
        Sleep(100)
        SendKeys.SendInput(wVk.VK_ESCAPE)
    End Sub

End Class

Public Module SendKeys

    Private Enum dwFlags As Integer
        KEYEVENTF_EXTENDEDKEY = &H1
        KEYEVENTF_KEYUP = &H2
        KEYEVENTF_SCANCODE = &H8
        KEYEVENTF_UNICODE = &H4
    End Enum

    Private Enum type As Integer
        INPUT_MOUSE = 0
        INPUT_KEYBOARD = 1
        INPUT_HARDWARE = 2
    End Enum

    <DllImport("user32.dll")> _
    Private Function SendInput( _
        ByVal nInputs As Integer, _
        ByRef pInputs As INPUT, _
        ByVal cbSize As Integer) _
        As Integer
    End Function

    <DllImport("user32.dll")> _
    Private Function GetMessageExtraInfo() _
        As IntPtr
    End Function

    <DllImport("user32.dll")> _
    Private Function MapVirtualKey( _
        ByVal uCode As Integer, _
        ByVal uMapType As Integer) _
        As Integer
    End Function

    Public Sub SendInput(ByVal VirtualKeyCode As wVk)
        SendInput(VirtualKeyCode, 0)
        SendInput(VirtualKeyCode, dwFlags.KEYEVENTF_KEYUP)
    End Sub

    Private Sub SendInput(ByVal VirtualKeyCode As wVk, ByVal Flag As dwFlags)
        Dim inputevents As New INPUT
        inputevents.type = type.INPUT_KEYBOARD
        inputevents.ki.wVk = VirtualKeyCode
        inputevents.ki.wScan = CShort(MapVirtualKey(CInt(VirtualKeyCode), 0))
        inputevents.ki.dwFlags = ExtendedKeyFlag(VirtualKeyCode) Or Flag
        inputevents.ki.time = 0
        inputevents.ki.dwExtraInfo = GetMessageExtraInfo()
        SendInput(1, inputevents, Marshal.SizeOf(inputevents))
    End Sub

    Private Function ExtendedKeyFlag(ByVal Key As wVk) As dwFlags
        Dim Flag As dwFlags = 0
        Select Case Key
            Case wVk.VK_CANCEL, wVk.VK_PRIOR, wVk.VK_NEXT, wVk.VK_END, wVk.VK_HOME, _
                 wVk.VK_LEFT, wVk.VK_UP, wVk.VK_RIGHT, wVk.VK_DOWN, _
                 wVk.VK_SNAPSHOT, wVk.VK_INSERT, wVk.VK_DELETE, _
                 wVk.VK_DEVIDE, wVk.VK_NUMLOCK, wVk.VK_RSHIFT, wVk.VK_RCONTROL, wVk.VK_RMENU
                Flag = dwFlags.KEYEVENTF_EXTENDEDKEY
        End Select
        Return Flag
    End Function

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure INPUT
        <FieldOffset(0)> Dim type As Integer
        <FieldOffset(4)> Dim mi As MOUSEINPUT
        <FieldOffset(4)> Dim ki As KEYBDINPUT
        <FieldOffset(4)> Dim hi As HARDWAREINPUT
    End Structure

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure MOUSEINPUT
        <FieldOffset(0)> Public dx As Integer
        <FieldOffset(4)> Public dy As Integer
        <FieldOffset(8)> Public mouseData As Integer
        <FieldOffset(12)> Public dwFlags As Integer
        <FieldOffset(16)> Public time As Integer
        <FieldOffset(20)> Public dwExtraInfo As IntPtr
    End Structure

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure KEYBDINPUT
        <FieldOffset(0)> Public wVk As wVk
        <FieldOffset(2)> Public wScan As Short
        <FieldOffset(4)> Public dwFlags As dwFlags
        <FieldOffset(8)> Public time As Integer
        <FieldOffset(12)> Public dwExtraInfo As IntPtr
    End Structure

    <StructLayout(LayoutKind.Explicit)> _
    Private Structure HARDWAREINPUT
        <FieldOffset(0)> Public uMsg As Integer
        <FieldOffset(4)> Public wParamL As Short
        <FieldOffset(6)> Public wParamH As Short
    End Structure

    Public Enum wVk As Short
        VK_CANCEL = &H3 'BREAK(Control+Pause) key(ExtendedKey)
        VK_BACK = &H8 'BACKSPACE key
        VK_TAB = &H9 'TAB key
        VK_CLEAR = &HC
        VK_RETURN = &HD 'ENTER key
        VK_SHIFT = &H10 'SHIFT key
        VK_CONTROL = &H11 'CTRL key
        VK_MENU = &H12 'ALT key
        VK_PAUSE = &H13 'PAUSE key
        VK_CAPITAL = &H14 'CAPS LOCK key
        VK_KANA = &H15 'IME かな mode
        VK_JUNJA = &H17
        VK_FINAL = &H18
        VK_KANJI = &H19 'IME 漢字 mode
        VK_ESCAPE = &H1B 'ESC key
        VK_CONVERT = &H1C 'IME 変換 key
        VK_NONCONVERT = &H1D 'IME 無変換 key
        VK_ACCEPT = &H1E
        VK_MODECHANGE = &H1F
        VK_SPACE = &H20 'SPACEBAR
        VK_PRIOR = &H21 'PAGE UP key(ExtendedKey)
        VK_NEXT = &H22 'PAGE DOWN key(ExtendedKey)
        VK_END = &H23 'END key(ExtendedKey)
        VK_HOME = &H24 'HOME key(ExtendedKey)
        VK_LEFT = &H25 '← key(ExtendedKey)
        VK_UP = &H26 '↑ key(ExtendedKey)
        VK_RIGHT = &H27 '→ key(ExtendedKey)
        VK_DOWN = &H28 '↓ key(ExtendedKey)
        VK_SELECT = &H29
        VK_PRINT = &H2A
        VK_EXECUTE = &H2B
        VK_SNAPSHOT = &H2C 'PRINT SCREEN key(ExtendedKey)
        VK_INSERT = &H2D 'INS key(ExtendedKey)
        VK_DELETE = &H2E 'DEL key(ExtendedKey)
        VK_HELP = &H2F
        VK_0 = &H30 '0 key
        VK_1 = &H31 '1 key
        VK_2 = &H32 '2 key
        VK_3 = &H33 '3 key
        VK_4 = &H34 '4 key
        VK_5 = &H35 '5 key
        VK_6 = &H36 '6 key
        VK_7 = &H37 '7 key
        VK_8 = &H38 '8 key
        VK_9 = &H39 '9 key
        VK_A = &H41 'A key
        VK_B = &H42 'B key
        VK_C = &H43 'C key
        VK_D = &H44 'D key
        VK_E = &H45 'E key
        VK_F = &H46 'F key
        VK_G = &H47 'G key
        VK_H = &H48 'H key
        VK_I = &H49 'I key
        VK_J = &H4A 'J key
        VK_K = &H4B 'K key
        VK_L = &H4C 'L key
        VK_M = &H4D 'M key
        VK_N = &H4E 'N key
        VK_O = &H4F 'O key
        VK_P = &H50 'P key
        VK_Q = &H51 'Q key
        VK_R = &H52 'R key
        VK_S = &H53 'S key
        VK_T = &H54 'T key
        VK_U = &H55 'U key
        VK_V = &H56 'V key
        VK_W = &H57 'W key
        VK_X = &H58 'X key
        VK_Y = &H59 'Y key
        VK_Z = &H5A 'Z key
        VK_LWIN = &H5B 'Left Windows key
        VK_RWIN = &H5C 'Right Windows key
        VK_APPS = &H5D ' Applications key
        VK_NUMPAD0 = &H60 'Numeric keypad 0 key
        VK_NUMPAD1 = &H61 'Numeric keypad 1 key
        VK_NUMPAD2 = &H62 'Numeric keypad 2 key
        VK_NUMPAD3 = &H63 'Numeric keypad 3 key
        VK_NUMPAD4 = &H64 'Numeric keypad 4 key
        VK_NUMPAD5 = &H65 'Numeric keypad 5 key
        VK_NUMPAD6 = &H66 'Numeric keypad 6 key
        VK_NUMPAD7 = &H67 'Numeric keypad 7 key
        VK_NUMPAD8 = &H68 'Numeric keypad 8 key
        VK_NUMPAD9 = &H69 'Numeric keypad 9 key
        VK_MULTIPLY = &H6A '* key
        VK_ADD = &H6B '+ key
        VK_SEPERATOR = &H6C '
        VK_SUBTRACT = &H6D '- key
        VK_DECIMAL = &H6E 'テンキーの . key
        VK_DEVIDE = &H6F '/ key(ExtendedKey)
        VK_F1 = &H70 'F1 key
        VK_F2 = &H71 'F2 key
        VK_F3 = &H72 'F3 key
        VK_F4 = &H73 'F4 key
        VK_F5 = &H74 'F5 key
        VK_F6 = &H75 'F6 key
        VK_F7 = &H76 'F7 key
        VK_F8 = &H77 'F8 key
        VK_F9 = &H78 'F9 key
        VK_F10 = &H79 'F10 key
        VK_F11 = &H7A 'F11 key
        VK_F12 = &H7B 'F12 key
        VK_F13 = &H7C 'F13 key
        VK_F14 = &H7D 'F14 key
        VK_F15 = &H7E 'F15 key
        VK_F16 = &H7F 'F16 key
        VK_F17 = &H80 'F17 key
        VK_F18 = &H81 'F18 key
        VK_F19 = &H82 'F19 key
        VK_F20 = &H83 'F20 key
        VK_F21 = &H84 'F21 key
        VK_F22 = &H85 'F22 key
        VK_F23 = &H86 'F23 key
        VK_F24 = &H87 'F24 key
        VK_NUMLOCK = &H90 'NUM LOCK key(ExtendedKey)
        VK_SCROLL = &H91 'SCROLL LOCK key
        VK_LSHIFT = &HA0 'Left SHIFT key
        VK_RSHIFT = &HA1 ' Right SHIFT key(ExtendedKey)
        VK_LCONTROL = &HA2 'Left CONTROL key
        VK_RCONTROL = &HA3 'Right CONTROL key(ExtendedKey)
        VK_LMENU = &HA4 'Left MENU key
        VK_RMENU = &HA5 'Right MENU key(ExtendedKey)
        VK_BROWSER_BACK = &HA6 'Browser Back key
        VK_BROWSER_FORWARD = &HA7 'Browser Forward key
        VK_BROWSER_REFRESH = &HA8 'Browser Refresh key
        VK_BROWSER_STOP = &HA9 'Browser Stop key
        VK_BROWSER_SEARCH = &HAA 'Browser Search key
        VK_BROWSER_FAVORITES = &HAB 'Browser Favorites key
        VK_BROWSER_HOME = &HA6 'Browser Start and Home key
        VK_VOLUME_MUTE = &HAD 'Volume Mute key
        VK_VOLUME_DOWN = &HAE 'Volume Down key
        VK_VOLUME_UP = &HAF 'Volume Up key
        VK_MEDIA_NEXT_TRACK = &HB0 'Next Track key
        VK_MEDIA_PREV_TRACK = &HB1 'Previous Track key
        VK_MEDIA_STOP = &HB2 'Stop Media key
        VK_MEDIA_PLAY_PAUSE = &HB3 'Play/Pause Media key
        VK_LAUNCH_MAIL = &HB4 'Start Mail key
        VK_LAUNCH_MEDIA_SELECT = &HB5 'Select Media Key
        VK_LAUNCH_APP1 = &HB6 'Start Application 1 key
        VK_LAUNCH_APP2 = &HB7 'Start Application 2 key
        VK_OEM_1 = &HBA ': *  key
        VK_OEM_PLUS = &HBB '; + key
        VK_OEM_COMMA = &HBC ', < key
        VK_OEM_MINUS = &HBD '- = key
        VK_OEM_PERIOD = &HBE '. > key
        VK_OEM_2 = &HBF '/ ? key
        VK_OEM_3 = &HC0 '@ ` key
        VK_OEM_4 = &HDB '[ { key
        VK_OEM_5 = &HDC '\ | key
        VK_OEM_6 = &HDD '] } key
        VK_OEM_7 = &HDE '^ ~ key
        VK_OEM_8 = &HDF
        VK_PROCESSKEY = &HE5
        VK_OEM_ATTN = &HF0 '英数
        VK_OEM_102 = &HE2 '\ _ key
        VK_OEM_COPY = &HF2 'カタカナひらがな
        VK_OEM_AUTO = &HF3 '全角/半角
        VK_OEM_ENLW = &HF4 '全角/半角
        VK_OEM_BACKTAB = &HF5 'ローマ字
        VK_PACKET = &HE7
        VK_ATTN = &HF6
        VK_CRSEL = &HF7
        VK_EXSEL = &HF8
        VK_EREOF = &HF9
        VK_PLAY = &HFA
        VK_ZOOM = &HFB
        VK_NONAME = &HFC
        VK_PA1 = &HFD
        VK_OEM_CLEAR = &HFE
    End Enum

End Module

[ツリー表示へ]
タイトルRe^4: 残念ながら・・・
記事No3204
投稿日: 2006/02/26(Sun) 22:16
投稿者YAS
うぅ,重ねてすみません。
Win32APIの仮想キーコードって.NETのKeysと違うと今の今まで
思っていたのですが,同じだったのですね。
上のリストの仮想キーコードの定義のところは全くの無駄でした。
ごめんなさい。

[ツリー表示へ]
タイトルRe^5: 納得
記事No3205
投稿日: 2006/02/26(Sun) 23:06
投稿者花ちゃん
ありがとうございます。
結局拡張コードを指定していた事が間違いの原因だったのですね。
そこまでは、試していませんでした。

# でも、元質問者の方はどうされたのでしょうね?


Button1 をクリックしてからすぐに FD55 をクリックする。

Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles Button1.Click
   System.Threading.Thread.Sleep(2000)
   Call keybd_event(Keys.S, MapVirtualKey(Keys.S, 0), 0, 0)
   Call keybd_event(Keys.S, MapVirtualKey(Keys.S, 0), KEYEVENTF_KEYUP, 0)
End Sub

[ツリー表示へ]
タイトルRe^6: 完璧です
記事No3213
投稿日: 2006/02/28(Tue) 12:14
投稿者hide
YASさん花ちゃんさんありがとうございました。完璧です!

DOSのフル画面での使用も全く問題ありませんでした。
さすがにコードを見る限りでは自分では思いもつかない方法で
唖然としてしまいました。
Win98とWinXPでのDOSアプリの動作の違いまで勉強させていただいて
本当に感謝感激です。花ちゃんさんの運営するこの掲示板にも
初心者のような私には神様に見えます。
掲示板の管理も大変かと思いますが、これからもがんばってください。
YASさん花ちゃんさん本当にありがとうございました。

[ツリー表示へ]