Jump to content

ControlSend $ shows 4 sometimes?


 Share

Recommended Posts

I have a script that puts amounts into another application, about 1000+ one after the other.  While reviewing, it appears there are some rare occasions where the $ is actually entered as a 4.

ControlSend($hReceiptHwnd, "Check Amount", "Edit1", Stringreplace($iAmt, ",", ""))

I also filewriteline that $iAmt into a runtime log and the $ shows fine in there, so it must be the ControlSend

So I'm wondering how ControlSend actually sends the dollar sign?  Does it send Shift+4 or does it send the actual Ascii character 36?

Perhaps I should also do a StringReplace($iAmt, "$", Chr(36)) or would it even matter?

 

Thanks,

Mike

 

Link to comment
Share on other sites

I have made a little test that I am pretty sure you will appreciate :

Opt ("MustDeclareVars", 1)

run ("notepad.exe")
Global  $h = WinWaitActive("[CLASS:Notepad]")

For $i = 1 to 1000
  ControlSend ($h, "", "Edit1", "$?*({ENTER}")
Next

Now if I don't do anything on my comp while the script is running, I have no error.  BUT if I press shift , or if I click on tray,  on rare occasion, the character sent is a number, like you are experiencing.  And if I add $SEND_RAW, well.......doesn't matter, it will still send a number.

So the question, is what is happening on your comp while script is running ?

Link to comment
Share on other sites

So what you want to do is to take the value $10,583 and send it to the window as $10583 but sometimes it sends it as 410583? Do I understand correctly?

Link to comment
Share on other sites

Thank you for that demo Nine, keeps me from having to verify with a run this morning. "our test db refreshes nightly"

The script is actually running inside a Citrix desktop window on my one screen while I continue my normal job on my other screen.   Often I have another application open over the Citrix window as well.

I wonder if there's a way to use BlockInput only for keyboard?

edit:  Yes there is a BlockInputEx:  https://www.autoitscript.com/forum/topic/87735-blockinputex-udf

 

Jaberwacky, yes your understanding of the issue is correct.

Edited by BigDaddyO
Link to comment
Share on other sites

I tried the BlockInputEx and just blocking the keyboard doesn't help either.  so weird.

#include <BlockInputEx.au3>

;================== hWindows usage Example ==================
run ("notepad.exe")
Global  $h = WinWaitActive("[CLASS:Notepad]")

;Here we block *All* keyboard keys for specific window (in this case the Notepads window).
;~ _BlockInputEx(3, "", "", $h) ;blocking keyboard input for the window doesnt help either.

;Here we block only *Keyboard* input (without mouse).
_BlockInputEx(3)        ;This doesn't help either


For $i = 1 to 400
  ControlSend ($h, "", "Edit1", "$?*({ENTER}")
Next

While testing (rapid-tap shift), I'd get the Sticky Keys popup prompt, and then I'd see a bunch of mistypes displayed.

 

ScreenCap_20.JPG

 

 

edit:  I also confirmed that using Chr() doesn't help:  ControlSend ($h, "", "Edit1", Chr(36) & Chr(63) & Chr(42) & Chr(40) & "{ENTER}")

Edited by BigDaddyO
Link to comment
Share on other sites

Try this as just a test please:

#include "AutoItConstants.au3"

Run("Notepad.exe")

Const $hNotepad = WinWaitActive("[CLASS:Notepad]")

For $i = 1 To 1000
    ControlSend($hNotepad, "Untitled", "Edit1", "$?*({ENTER}" & @CRLF, $SEND_RAW)
Next

 

Link to comment
Share on other sites

Better yet!

Run("Notepad.exe")

Const $hNotepad = WinWaitActive("[CLASS:Notepad]")

For $i = 1 To 1000
    ControlFocus($hNotepad, "Untitled", "Edit1")

    ControlSend($hNotepad, "Untitled", "Edit1", "$?*({ENTER}")
Next

 

Link to comment
Share on other sites

@jaberwacky Neither of those get around the issue, tapping the Shift key manually while running still messes them up.

I even tried this: and it doesn't help.

Run("Notepad.exe")

Const $hNotepad = WinWaitActive("[CLASS:Notepad]")

For $i = 1 To 400
    ControlSend($hNotepad, "Untitled", "Edit1", "+4+/+8+9{ENTER}")
Next

 

@Zedna the issue i'm encountering isn't so much that ControlSend doesn't work, its that it's sometimes interrupted by external factors.  "Shift key manually tapped", "Selecting the System Tray or another Application while it's running"

 

The only thing that has worked 100% of the time is to do the BlockInput(1) but that needs the #RequireAdmin to work which really sucks.

Link to comment
Share on other sites

  • 2 weeks later...

Hello @BigDaddyO,

Check out my take on the issue from @jaberwacky's example:

;https://www.autoitscript.com/forum/topic/200176-controlsend-shows-4-sometimes/
#include <GuiRichEdit.au3>

HotKeySet('{END}', '_Exit') ; Just in case you want to end it early

;~ AutoItSetOption('SendKeyDelay', 0)       ; Used when testing sending the keys, and sending ^v
;~ AutoItSetOption('SendKeyDownDelay', 0)   ; Used when testing sending the keys, and sending ^v
OnAutoItExitRegister('_Exit') ; Just so that we can restore our previous Clipboard

Run("Notepad.exe")

Const $hNotepad = WinWaitActive("[CLASS:Notepad]")
Const $sClip = ClipGet() ; Store the current Clip, to be nice :)

ClipPut("$?*(" & @CRLF) ; Put the text that you want into the Clipboard, so that we don't have to 'send' the characters
;~ ClipPut(Chr(36) & Chr(63) & Chr(42) & Chr(40) & @CRLF)

$hNotepadEdit = ControlGetHandle($hNotepad, "Untitled", "Edit1")
WinSetState($hNotepad, '', @SW_MINIMIZE) ; Using _GUICtrlRichEdit_Paste, we don't need the window to have any focus, and it actually returns MUCH faster if the window DOESN'T have focus. Like ~35s vs ~2.6s

For $i = 1 To 1000
;~  ControlFocus($hNotepad, "Untitled", "Edit1") ; This isn't needed with _GUICtrlRichEdit_Paste
;~  ControlSend($hNotepad, "Untitled", "Edit1", "$?*({ENTER}")
;~  ControlSend($hNotepad, "Untitled", "Edit1", "^v")   ; This caused issues if I held Right 'Ctrl' down, occasionally I would just get "v", though the failure rate was much less than holding Right 'Shift' with the above ControlSend
    _GUICtrlRichEdit_Paste($hNotepadEdit)
    ; Specifically, WM_PASTE. I have no idea how to use this outside of this UDF, though you could easily look at the UDF function and see, here would be the "direct" call without the UDF's other layers:
    ; DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hNotepadEdit, "uint", 0x00000302, "wparam", 0, "lparam", 0)
    ; There doesn't seem to be any real benefit to using the call directly, however, takes about the same amount of time. There's not a lot of extra things or error checking happening

    If Mod($i, 10) = 0 Then ConsoleWrite(($i / 1000) * 100 & '% done' & @CRLF) ; Just a little logging
Next

WinSetState($hNotepad, '', @SW_RESTORE) ; All 1000 lines are there, I promise :)

Func _Exit()
    ClipPut($sClip) ; Restore the previous Clip, to be nice :)
    Exit
EndFunc   ;==>_Exit

Using that example, I was able to get this to complete with (as far as I can tell) 100% success, though the actual keys aren't "sent", if that's a requirement of yours. Let me know if this works for you, as it looks like that it should be *much* faster than ControlSend (though the fastest would probably be to just build your Clipboard with the final output, and send it once, or set the text directly).

Edited by mistersquirrle
Fix script

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

@Nine You solution seems to work great!  It only takes 7ms to block and re-enable access so I can stick it just before and after my ControlSend and from my testing it works great!

#include "BlockInputEX.au3"

Run("Notepad.exe")
Const $hNotepad = WinWaitActive("[CLASS:Notepad]")
For $i = 1 To 400
    _BlockInput(1)    ;Disable input
    ControlSend($hNotepad, "Untitled", "Edit1", "$?({ENTER}")
    _BlockInput(0)    ;Enable input
Next

@mistersquirrle Yes, send was a requirement, otherwise I would just use ControlSetText.

Edited by BigDaddyO
Link to comment
Share on other sites

11 minutes ago, BigDaddyO said:

@mistersquirrle Yes, send was a requirement, otherwise I would just use ControlSetText.

Oh well, at least I can say that I tried. Question about it though, is each keystroke required? Or is just the 'ENTER' required? Because you can still (in the Notepad example) use my solution of the paste for the actual data, and then ControlSend the ENTER no problem. I didn't have any issues with holding/ pressing Ctrl or Shift this way, was still able to do things, and it could still be done while minimized.

I obviously don't know how your "Check Amount" window works, but I would personally prefer not blocking input. When I tried it and tried to disrupt it by holding 'Shift' or 'Ctrl', it actually ended up getting my 'Shift' key stuck down for a while, and it's impossible to do anything else (obviously) while input is blocked, or constantly being blocked. But, if it works for you, go for it, don't let me try to stop you.

Here's my code with the 'ENTER' key actually 'sent', but pasting the other data.

;https://www.autoitscript.com/forum/topic/200176-controlsend-shows-4-sometimes/
#include <GuiRichEdit.au3>
#include "BlockInputEX.au3"

HotKeySet('{END}', '_Exit') ; Just in case you want to end it early
OnAutoItExitRegister('_Exit') ; Just so that we can restore our previous Clipboard

Run("Notepad.exe")

Const $hNotepad = WinWaitActive("[CLASS:Notepad]")
Const $sClip = ClipGet() ; Store the current Clip, to be nice :)

ClipPut("$?*(") ; Put the text that you want into the Clipboard, so that we don't have to 'send' the characters

$hNotepadEdit = ControlGetHandle($hNotepad, "Untitled", "Edit1")
;~ WinSetState($hNotepad, '', @SW_MINIMIZE) ; Using _GUICtrlRichEdit_Paste, we don't need the window to have any focus, and it actually returns MUCH faster if the window DOESN'T have focus. Like ~35s vs ~2.6s

For $i = 1 To 1000
    _GUICtrlRichEdit_Paste($hNotepadEdit)
    ControlSend($hNotepad, '', "Edit1", "{ENTER}")
;~  ControlSend($hNotepadEdit, '', $hNotepadEdit, "{ENTER}") ; This also works

;~  _BlockInput(1) ;Disable input
;~  ControlSend($hNotepad, "Untitled", "Edit1", "$?({ENTER}")
;~  _BlockInput(0) ;Enable input

    If Mod($i, 10) = 0 Then ConsoleWrite(($i / 1000) * 100 & '% done' & @CRLF) ; Just a little logging
Next

;~ WinSetState($hNotepad, '', @SW_RESTORE) ; All 1000 lines are there, I promise :)

Func _Exit()
    ClipPut($sClip) ; Restore the previous Clip, to be nice :)
    Exit
EndFunc   ;==>_Exit

 

We ought not to misbehave, but we should look as though we could.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...