Jump to content
Sign in to follow this  

Special chars issue with Send/ControlSend and XTerm

Recommended Posts

Hi all !

I work on a tool for automating logon in a business software. This software is a Linux application, displayed in Windows with an EXPORT DISPLAY method, using a X-SERVER (Cygwin/Xterm).

The problem is when I use Send or ControlSend, special keys like @ or # (or some other keys needing an AltGr combination), the characters sent are the non-AltGr keys (# become 3, @ become 3 - I use a French keyboard).

I tried to send keys to the Linux-Firefox (instead of the business software), but I had the same result.

Does anyone has already try to make something like this, with the same issue ?

Thanks for help


Share this post

Link to post
Share on other sites

I've seen a couple posts on the forum about this same issue. Can you show us an example of what you're sending?

You can always try sending with Chr like so:

Send(Chr(35)) ; #

Just a thought. :)

Edited by MikahS

Snips & Scripts

My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ


Share this post

Link to post
Share on other sites

I tried with Chr but no, same problem.

for example, I use this code :

ControlSend("[REGEXPCLASS:cygwin/x; REGEXPTITLE:Utilisateur]", "", "", "P@$$w0rd!")

The characters received by the X-SERVER are pà$$wàrd (the french keyboards has 0, @ and à in the same key)

With another window (notepad), it works...


Share this post

Link to post
Share on other sites

Try using the Raw flag in ControlSend.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post

Link to post
Share on other sites

Try enclosing in brackets, like so:

ControlSend("[REGEXPCLASS:cygwin/x; REGEXPTITLE:Utilisateur]", "", "", "P{@}$$w{0}rd{!}")


Edited by MikahS

Snips & Scripts

My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ


Share this post

Link to post
Share on other sites

Same problem here. Problem is your Windows keyboard layout. If you change the keyboard layout to US it works fine, at least for me, at least in the cygwin CLASS:mintty window (default Cygwin terminal), even with characters like "¡²³" (which I just had to copypaste into the browser, btw, because these problems exist everywhere :) ).

There are the _WinAPI_[Get|Set]KeyboardLayout() functions, but with my keyboard layout "US-International" I can't get it to run stable. Sometimes it works and sometimes it doesn't. No idea, but maybe it can get you started.
/edit: seems to often not work on the first try after manually setting my keyboard layout back to US/International (which apparently doesn't have a nice code :( ), but works if I repeat the script.

Good luck and good night, I'm giving up now ;)

#include <APILocaleConstants.au3>
#include <WinAPILocale.au3>
#include <WinAPISys.au3>

$hWnd1 = WinGetHandle("")

_WinAPI_SetKeyboardLayout($hWnd1, 0x0409)

; start or activate terminal

Send("abc ¡²³")


Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post

Link to post
Share on other sites

So, I just tried each suggestion :

 - MikahS : i tried Send("P{@}$$w{0}rd{!}", 1). result is P'=$$w'0=rd'!= (also tried with 0 or 1 as 2nd parameter)

 - Mikell : I tried Send("{RALT DOWN}0{RALT UP}") : then result is ° (I don't know why because it's not the good key...)

 - SadBunny : I tried, but no. I used _WinAPI_GetKeyboardLayout to retrieve the active layout. The result is 0x04090409 (english).
With _WinAPI_SetKeyboardLayout($hWnd, 0x040C), I have the same behavior : it has no effect with the X-Window (the window seems to reject the WM_INPUTLANGCHANGEREQUEST message from _WinAPI_SetKeyboardLayout )


It works with this : Send("P{RALT DOWN}à{RALT UP}$$w0rd{!}"), but not with ControlSend (the @ becomes à)
So it seems I will have to map all shit/altgr keys and generate a string to use with Send with this kind of code :

Global $aKeys[13][2] = [["}", "{RALT DOWN}={RALT UP}"], _
                        ["{", "{RALT DOWN}'{RALT UP}"], _
                        ["!", "{!}"], _
                        ["+", "{+}"], _
                        ["~", "{RALT DOWN}é{RALT UP}"], _
                        ["#", "{RALT DOWN}""{RALT UP}"], _
                        ["[", "{RALT DOWN}({RALT UP}"], _
                        ["|", "{RALT DOWN}-{RALT UP}"], _
                        ["\", "{RALT DOWN}_{RALT UP}"], _
                        ["^", "{RALT DOWN}ç{RALT UP}"], _
                        ["@", "{RALT DOWN}à{RALT UP}"], _
                        ["]", "{RALT DOWN}){RALT UP}"], _
                        ["¤", "{RALT DOWN}${RALT UP}"] ]

$sPassword = "#P@$$w0rd!"

$sSendPassword = _MapAltGrKeys($sPassword)

Func _MapAltGrKeys($sString)
    For $i = 0 To UBound($aKeys) - 1
        $sString = StringReplace($sString, $aKeys[$i][0], $aKeys[$i][1])
    Return $sString

It works, but I'm not really fan of this method... I would prefer a cleaner way.

Thanks to all for your help, I can continue my code now !

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By CiaronJohn
      I would like to read the output of my cygwin terminal if it is already up and running.
      I searched the forum, but I think, the samples were cmd/cygwin needs to be re-run or not yet running.
      The purpose of the script is to check if compiling is done.
      Func _JAE_Rebuild_Software ($sSoftwarePath)
          Local $iMinty = 0
          ; Open cygwin process and check one instance only
          if ProcessExists("mintty.exe") Then
              $iMinty = ProcessExists("mintty.exe")
              ; Run cygwin if not yet running
              $iMinty = Run("C:\cygwin\bin\mintty.exe -i /Cygwin-Terminal.ico -", "", @SW_SHOW, $STDIN_CHILD + $STDOUT_CHILD)
          ; Loop to check if cygwin terminal is ready
          While 1
              ; if -sh is not error cygwin is still opening
              Local $hWnd = WinGetHandle("-sh")
              If @error Then
                  $hWnd = WinGetHandle("~")
                  $hWnd = 0
              ; If true cygwin is ready to be written
              if $hWnd <> '0x00000000' Then
          ; Change Directory
          $sSoftwarePath = StringReplace($sSoftwarePath,"\", "/")
          Send('cd ' & $sSoftwarePath & "{ENTER}" )
          ; Get New Class after Change Directory
          Local $sNewClass = WinGetTitle("[ACTIVE]")
          ; Sleep for 3 seconds.
          ; Change software path to access the makeFile
          $sSoftwarePath = StringReplace($sSoftwarePath,"/", "\")
          ; Open Makefile
          Local $hFileOpen = FileOpen($sSoftwarePath & "\makefile", $FO_READ)
          If $hFileOpen = -1 Then
              Return False
          Local $sFileRead = FileReadLine($hFileOpen, 12)
          Local $sSetSource = _StringBetween($sFileRead, "(", ")", $STR_ENDNOTSTART)
          Local $message
          Send('source ' & $sSetSource[0] & '.sh' & "{ENTER}")
          Send('make clean' & "{ENTER}")
          WinActivate($sNewClass, "")
          $hWnd = WinWait($sNewClass,"",1)
          Local $iPID = WinGetProcess($hWnd)
          While $iMinty
              $message &= StderrRead($iPID)
               If @error Then
         ; I only get blank output here since the while condition produces an error
         MsgBox(0, "Stdout Read:", $message)
      EndFunc ;==>_JAE_Rebuild_Software
    • By tremolux66
      Before I dive into the specifics of my problem, are there known, fatal issues when running a compiled AutoIt script (.exe file) from a Cygwin Bash script? Am I wasting my time trying to get it to work?
      If not, then here's my problem: I have 2 compiled AU3 scripts that are normally executed in the background by a Windows service. The Start script is executed by the service with a directory path as a command-line argument, does some processing, and creates a database record. After an external (human) activity finishes, the Stop script is executed, does some more processing, and updates the database record for the directory. The Bash script emulates the service for purposes of re-processing directories that had errors during the "live" pass: it loops through a text file containing a list of failed directories and executes the Start and Stop scripts.
      If the AU3 script executions are commented-out (e.g., to test other logic in the loop), the Bash script reads through the entire directory-list file; the Start and Stop scripts are treated as if they had run successfully. But if the AU3 scripts are actually executed, the loop exits after the first full iteration (i.e., without skips caused by error-detection).
      Subsequent runs of the Bash script process one directory each and exit (the list file shrinks with each pass). It seems like something about the execution of the AU3 scripts is changing the Bash loop execution (e.g., causing it to see end-of-file for the directory list file). A puzzling aspect is that an earlier version of the Bash script executed successfully (all directories processed), but in that case the directory list was taken from a Bash array variable rather than a file. Since there could be hundreds (or more) directories requiring re-processing, I modified the Bash script to read from a file, with the intention of making it more robust.
      Any suggestions for troubleshooting this will be welcome.
      Outline of the script; the actual script is much longer:
      #!/bin/bash # Initialize variables... export START_EXEPATH="C:/mydir/StartScript.exe" export STOP_EXEPATH="C:/mydir/StopScript.exe" # Generate (unix) text file containing (unix) directory paths, one per line find C:/somedir -type d [some other criteria...] -print >/tmp/dir_list.out # Core code: let errcnt=0 while IFS='' read -r dpath do # Validate the last component of dpath... dpath_base="$(basename "$dpath")" regexp="some-extended-regexp" if [[ "$dpath_base" =~ $regexp ]]; then dpath_bad=0; else dpath_bad=1; fi if [ $dpath_bad -eq 1 ]; then let errcnt+=1; echo "error message"; continue; fi win_dpath="$(cygpath -a -w "$dpath")" # Run 1st AutoIt script "$START_EXEPATH" "$win_dpath" "another-argument" if [ $? -ne 0 ]; then let errcnt+=1; echo "error message"; continue; fi # Run 2nd AutoIt script "$STOP_EXEPATH" "$win_dpath" if [ $? -ne 0 ]; then let errcnt+=1; echo "error message"; fi done </tmp/dir_list.out echo "$errcnt errors" if [ $errcnt -ne 0 ]; then exit 2; fi exit 0  
  • Create New...