Что нового

Как посылать команды в консоль CMD независимо от раскладки клавиатуры?

pvnn

Осваивающий
Сообщения
305
Репутация
32
Добрый день всем.
Помогите пожалуйста разобраться.

Есть форма с кнопкой, которая запускает консоль CMD, в которую посылается команда:
Код:
nbtstat -a 192.168.1.1
Если перед нажатием на кнопку сменить раскладку клавиатуры на Русскую, то команда посылается "криво":
Код:
nbtstat -a 192/168/1/1
Как правильно посылать команды в консоль CMD независимо от раскладки клавиатуры?

Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

AutoItSetOption('WinTitleMatchMode',-2)

$Form1 = GUICreate("Form1", 266, 99, 293, 179)
$Button1 = GUICtrlCreateButton("Button1", 88, 40, 75, 25)
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
			Run(@ComSpec&' /c '&'cmd')
			WinWaitActive(StringLower('cmd.exe'))
			ControlSend('cmd.exe', '', '', 'nbtstat -a '&'192.168.1.1'&@CR)
	EndSwitch
WEnd
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
pvnn,
Попробуйте сделать так: Обход проблемы с HotKeySet/Accelerators при разных раскладках клавиатуры
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt('WinTitleMatchMode', -2)

$Form1 = GUICreate("Form1", 266, 99, 293, 179)
$Button1 = GUICtrlCreateButton("Button1", 88, 40, 75, 25)
GUISetState(@SW_SHOW)
_WinAPI_LoadKeyboardLayoutEx(0x0409, $Form1)
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
			Run(@ComSpec & ' /c ' & 'cmd')
			WinWaitActive(StringLower('cmd.exe'));???
			ControlSend('cmd.exe', '', '', 'nbtstat -a ' & '192.168.1.1' & @CR)
	EndSwitch
WEnd

Func _WinAPI_LoadKeyboardLayoutEx($sLayoutID = 0x0409, $hWnd = 0)
	Local Const $WM_INPUTLANGCHANGEREQUEST = 0x50
	Local $aRet = DllCall("user32.dll", "long", "LoadKeyboardLayoutW", "wstr", Hex($sLayoutID, 8), "int", 0)

	If Not @error And $aRet[0] Then
		If $hWnd = 0 Then
			$hWnd = WinGetHandle(AutoItWinGetTitle())
		EndIf

		DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $aRet[0])
		Return 1
	EndIf

	Return SetError(1)
EndFunc   ;==>_WinAPI_LoadKeyboardLayoutEx
 

---Zak---

Скриптер
Сообщения
455
Репутация
120
Не по теме, но "вдруг"...

Код:
...
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button1
            Run(@ComSpec&' /c nbtstat -a 192.168.1.1 > C:\nbtstat.txt', '', @SW_HIDE)
    EndSwitch
...


на диске C: будет файл nbtstat.txt - в нем результат...
 
Автор
P

pvnn

Осваивающий
Сообщения
305
Репутация
32
Выяснил, чтобы все корректно работало, необходимо:
1. Перед вызовом CMD-консоли сделать раскладку Английской
2. После появления CMD-консоли, тоже сделать раскладку Английской
При таких условиях, команды в CMD-консоль посылаются всегда корректно
С учетом вышесказанного:
Код:
Case $Button1
_WinAPI_LoadKeyboardLayoutEx(0x0409,$Form1)
            Run(@ComSpec & ' /c ' & 'cmd')
            WinWaitActive(StringLower('cmd.exe'))
            _WinAPI_LoadKeyboardLayoutEx(0x0409,WinGetHandle("[Active]"))
            ControlSend('cmd.exe', '', '', 'nbtstat -a ' & '192.168.1.1' & @CR)


Но, данная конструкция в Windows 7 не работает, потому что
Код:
_WinAPI_LoadKeyboardLayoutEx(0x0409,$Form1)
не меняет раскладку в данной ОС
Доработанная функция имеет следующий вид:
Код:
Func _WinAPI_LoadKeyboardLayoutEx($sLayoutID = 0x0409, $hWnd = 0)
    Local Const $WM_INPUTLANGCHANGEREQUEST = 0x50
	Local $aRet = DllCall('user32.dll', 'uint_ptr', 'LoadKeyboardLayoutW', 'wstr', Hex($sLayoutID, 8), 'uint', BitOR(0x00000001, 0x00000100));0x00000101
    If Not @error And $aRet[0] Then
        If $hWnd = 0 Then
            $hWnd = WinGetHandle(AutoItWinGetTitle())
        EndIf
        DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $aRet[0])
        Return 1
    EndIf
    Return SetError(1)
EndFunc   ;==>_WinAPI_LoadKeyboardLayoutEx



Итого получилось:
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

AutoItSetOption('WinTitleMatchMode',-2)

$Form1 = GUICreate("Form1", 266, 99, 293, 179)
$Button1 = GUICtrlCreateButton("Button1", 88, 40, 75, 25)
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
                                  _WinAPI_LoadKeyboardLayoutEx(0x0409,WinGetHandle("[Active]"))
			Run(@ComSpec&' /c '&'cmd')
			WinWaitActive(StringLower('cmd.exe'))
			_WinAPI_LoadKeyboardLayoutEx(0x0409,WinGetHandle("[Active]"))
			ControlSend('cmd.exe', '', '', 'ping '&'192.168.1.1'&@CR)
	EndSwitch
WEnd



Func _WinAPI_LoadKeyboardLayoutEx($sLayoutID = 0x0409, $hWnd = 0)
    Local Const $WM_INPUTLANGCHANGEREQUEST = 0x50
	Local $aRet = DllCall('user32.dll', 'uint_ptr', 'LoadKeyboardLayoutW', 'wstr', Hex($sLayoutID, 8), 'uint', BitOR(0x00000001, 0x00000100));0x00000101
    If Not @error And $aRet[0] Then
        If $hWnd = 0 Then
            $hWnd = WinGetHandle(AutoItWinGetTitle())
        EndIf
        DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $aRet[0])
        Return 1
    EndIf
    Return SetError(1)
EndFunc   ;==>_WinAPI_LoadKeyboardLayoutEx
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
В _WinAPI_LoadKeyboardLayoutEx же нужно отправлять хэндл окна для которого мы хотим установить язык? Зачем мне менять язык для моего окна? А если у скрипта нет окна?
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
inververs
AutoIt запускается с раскладкой по умолчанию. Приложение, которое запускает скрипт, тоже запускается с раскладкой по умолчанию. Когда раскладки совпадают - проблем нет. Если раскладки не совпадают (см. фразу "Если перед нажатием на кнопку сменить раскладку клавиатуры на Русскую"), то получаются несоответствия. Следовательно, нужно либо синхронизировать раскладки, либо (что проще) установить одинаковую раскладку и у AutoIt и у принимающего клавиши приложения. Вот пример. Попробуйте с разными раскладками.
Код:
GUICreate("test")
$btn = GUICtrlCreateButton("send", 10, 10)
GUISetState()

Do
  Switch GUIGetMsg()
    Case -3
      Exit
    Case $btn
    Run(@ComSpec)
    WinWaitActive("C:\")
    Send("qwerйцук")
  EndSwitch
Until 0
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Я хочу отправить "йцук," на русском и с запятой, какой язык куда устанавливать? :stars:


Добавлено:
Сообщение автоматически объединено:

А, все понял, нужно что бы языки совпадали, а если у меня нет окна, то другому окну нужно ставить англ расскладку.


Добавлено:
Сообщение автоматически объединено:

А как узнать текущую расскладку скрипта? :-[


Добавлено:
Сообщение автоматически объединено:

А,
Код:
_WinAPI_GetKeyboardLayout
есть же
все вопросов нет
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
inververs [?]
если у меня нет окна, то другому окну нужно ставить англ расскладку
У AutoIt всегда есть окно. Если у вас по умолчанию русская раскладка и вы установите английскую только принимающему приложению, то получится несоответствие. Вот пример (для русской раскладки по умолчанию)
Код:
Run(@ComSpec)
$cmd = WinWaitActive("[class:ConsoleWindowClass]")
_WinAPI_LoadKeyboardLayoutEx(0x0409, $cmd)
Send("йцукqwert,")

Func _WinAPI_LoadKeyboardLayoutEx($sLayoutID = 0x0409, $hWnd = 0)
  Local Const $WM_INPUTLANGCHANGEREQUEST = 0x50
  Local $aRet = DllCall("user32.dll", "long", "LoadKeyboardLayoutW", "wstr", Hex($sLayoutID, 8), "int", 0)
  If Not @error And $aRet[0] Then
    If $hWnd = 0 Then
      $hWnd = WinGetHandle(AutoItWinGetTitle())
    EndIf
    DllCall("user32.dll", "ptr", "SendMessage", "hwnd", $hWnd, "int", $WM_INPUTLANGCHANGEREQUEST, "int", 1, "int", $aRet[0])
    Return 1
  EndIf
  Return SetError(1)
EndFunc   ;==>_WinAPI_LoadKeyboardLayoutEx



Добавлено:
Сообщение автоматически объединено:

OffTopic:
Сто лет пользуюсь программой StrokeIt. Когда проверял скрипты с удивлением обнаружил, что данная программа не работает при русской раскладке по умолчанию, если жесты основаны на отправке окну сочетаний клавиш. Т.е. горячие клавиши Ctrl+C, Ctrl+V и др. при русской раскладке по умолчанию отправляются "криво" и приложения эти команды игнорируют. Так что, похоже, это проблема многих "не русских" программ... Точнее, программ, не учитывающих разные раскладки.
 
Верх