Sign in to follow this  
Followers 0
D3STROY3R

Last IN - First OUT (LIFO) or First IN - First OUT (FIFO)

21 posts in this topic

Hi, I want to create a last in first out event callback system or a first in first out

currently my problem is when i receive an event it executes a function, during that functions NO OTHER EVENT is accepted

instead of missing other potential events, I would rather those events be logged so that after the current event is done the

next one can be executed

I am using a GUI with OnEventMode

Side question: does GuiGetMsg (the polling mode) stack events?

like if i am in the loop executing some function due to a GuiGetmsg... what happens if another event is fired?

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

My understanding is that events aren't stacked by AutoIt, they are stacked by Windows. GUIGetMsg simply an event from the event queue.

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

My understanding is that events aren't stacked by AutoIt, they are stacked by Windows. GUIGetMsg simply an event from the event queue.

Okay, if I understand this correctly, then there is a distinct difference between GUIOnEventMode and GUIGetMsg polling

Example: 2 events are requested to your GUI within the same 250 ms frame

In GUIOnEventMode: The first event is captured, appropriate function is called, however, since the main script is paused, the 2nd event is ignored.

In GUIGetMsg: The first event is retrieved from the event queue, then it is processed, then the 2nd event is retrieved from the event queue... so on

Distinction: GUIOnEventMode can miss events, GUIGetMsg mode will process all events in the order they exist in the event queue.

Please let me know if my assumption is correct.

Share this post


Link to post
Share on other sites

A good description how this two modes work can be found here and here.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

D3STROY3R,

I take it you are looking to detect events from your own AutoIt GUI. If that is so then take a look at the Interrupting a running function tutorial in the Wiki. You will see a number of ways to detect controls on your GUI being actioned even though the script is in a long function - in both OnEvent and MessageLoop modes. In your case you could add the detected event to a list for later actioning rather than interrupting the current function - but the basic principle is the same. :D

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Thanks for your responses, I have read that wiki and the other links posted several times but I can't seem to address my problem.

Basically I have an Autoit GUI and a separate application lets call it "AppA"

AppA uses sendCopyData to send a message to the Autoit GUI

example: update a spot on a listview item

In response, the Autoit GUI (which currently uses GUIRegisterMsg($WM_COPYDATA, "funcitonname"))

pauses the main script and then runs the function then unpauses the main script

However, while its running "functionname" it blocks all other $WM_COPYDATA requests

so my problem is I am having "dropped" events because i have more than 1 "AppA" instances that are concurrently sending copydata requests to the GUI to update a listview item but since they are being dropped the listview is not being updated as it should

My attempt at a solution: create a buffer to hold copydata requests and handle them in the main loop instead of using GUIRegisterMsg

My question is how can I create an event queue for Windows message just like how GUIGetMsg() works

because in the wiki, you can press button 1 many times and then 2 and it will actually execute all the buttons in the order pressed (not necessarily at the time pressed) but for me my copydata only processes the current copydata and will drop the other ones that came in during the busy time

i tried something like this:

$hGUI = GUICreate("Test", 500, 500)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        case $WM_COPYDATA
            msgbox("","CopydataRecieved","") 
    EndSwitch
WEnd

But, it seems like GUIGetMsg() does not hold Windows Message events, those have to be done using GUIRegisterMsg which does not hold all requests in a queue like GUIGetMsg()

Edited by D3STROY3R

Share this post


Link to post
Share on other sites

D3STROY3R,

Take a look at trancexx's MailSlot UDF. If you were to use that rather than $WM_COPYDATA you can easily read the stacked requests. I realise you might well be limited in how "AppA" communicates with your AutoIt GUI but this could be a possible solution. :D

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

D3STROY3R,

Take a look at trancexx's MailSlot UDF. If you were to use that rather than $WM_COPYDATA you can easily read the stacked requests. I realise you might well be limited in how "AppA" communicates with your AutoIt GUI but this could be a possible solution. :D

M23

Yes, I looked at the _MailSlot UDF as well and it would work as I would want it to however just as you said, "AppA" does not have the ability to to utilize the mailslot system.

The only methods to communicate for "AppA" are dde server or windows message copydata

Thanks for your help.

Edited by D3STROY3R

Share this post


Link to post
Share on other sites

D3STROY3R,

"AppA" does not have the ability to to utilize the mailslot system

I feared as much - life can be very annoying at times! :oops:

Last suggestion - how about an intermediate AutoIt script to intercept the $WM_COPYDATA messages from AppA which then uses the MailSlot UDF to communicate with the original AutoIt script? I realise we are adding another layer here, but at the end of a long and rather busy day I can think of nothing else. :D

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

D3STROY3R,

I feared as much - life can be very annoying at times! :)

Last suggestion - how about an intermediate AutoIt script to intercept the $WM_COPYDATA messages from AppA which then uses the MailSlot UDF to communicate with the original AutoIt script? I realise we are adding another layer here, but at the end of a long and rather busy day I can think of nothing else. :oops:

M23

I think this /might/ have the potential to work however, I have been searching for what the internal delay of GUIRegisterMsg call is

because as far as I can tell, my functions are minimal and are NON-Blocking (they should take less than 1 ms to complete and return...)

However, I think GUIRegisterMsg has a internal delay that only allows it to register a certain number of requests per second

I can't seem to find documentation on what this delay is or if there is a way to adjust it.

Summary: if the internal delay of GUIRegisterMsg is smaller then the rate at which requests are being received an intermediary script will work

D3STROY3R,

Stick around, I will ask a Dev to pop in and take a look. :rip:

M23

Edit: Done - stand by for incoming! :D

Appreciate the Help :D, ty.

Edited by D3STROY3R

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

D3STROY3R,

Stick around, I will ask a Dev to pop in and take a look. :D

M23

Edit: Done - stand by for incoming! :oops:

Edited by Melba23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Alright, so I have dealt with my problem Application side

Here is the real problem:

Any function that is more than changing a few variables (like loops) /may/ cause blocking when multiple clients are sending messages to an autoit script.

Solution:

Keep sending the message from your client until autoit returns a 1.

When autoit "drops" the message, it automatically returns a 0.

So instead of creating a buffer to hold all requests, I just keep requesting until I receive a correct response from autoit,

Thanks for your help, but I will no longer be implementing a buffer style holder for this purpose.

Share this post


Link to post
Share on other sites

AutoIt shouldn't be dropping messages at all. AutoIt polls the message queue like any other application and if there is a message it puts it into another queue which the script handles (or not depending on what events are registered). If you are seeing dropped messages that normally come through then you either found a bug in AutoIt, I'm missing something obvious or you have some really odd code. Keep in mind that long-running code should never be placed in a callback function or it will block. It could be that your code takes a bit to process and the blocking fills up some internal buffer and subsequent messages are discarded. This would likely be an issue with your script, though, and not AutoIt unless you demonstrate it happens in non-blocking situations.

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

AutoIt shouldn't be dropping messages at all. AutoIt polls the message queue like any other application and if there is a message it puts it into another queue which the script handles (or not depending on what events are registered). If you are seeing dropped messages that normally come through then you either found a bug in AutoIt, I'm missing something obvious or you have some really odd code. Keep in mind that long-running code should never be placed in a callback function or it will block. It could be that your code takes a bit to process and the blocking fills up some internal buffer and subsequent messages are discarded. This would likely be an issue with your script, though, and not AutoIt unless you demonstrate it happens in non-blocking situations.

then I think there may be an error with the autoit core with how the internal buffer operates

my update function calls approximately 4 lines of code

3 lines of codes are compare statements (comparing 2 array locations)

1 line of code that updates a listview item using setitem

total execution should be very minimal

This is how I performed my testing:

Launch 2x application clients that repeatedly use windows SendMessage function (which does not timeout)

they concurrently send n number of sendmessage to autoit gui in very short amount of time (like ~200 within 1 second)

If my autoit handler function has no operations, all messages are registered and handled properly

If I add a 100 ms delay in my autoit handler function, my application prints out "0" for the return from sendcopydata function that I am using (meaning they are not being handled)

I believe this is caused by the fact that autoit pauses the main script while the handler function is performing, while the handler function is performing the event queue is blocked and new event requests are not taken in.

In GUIGetMsg mode (which works for all alerts OTHER THAN WINDOWS MESSAGE) this problem does not exist, because GUIGetMsg mode uses polling thus main script is never paused, GUIGetMsg is basically a wrapper for the windows function GetMessage which properly handles an event queue which GUIGetMsg retrieves from.

However, GUIRegisterMessage does not work the same way, when using a registered message autoit actively checks for an interrupt flag and when it is set the proper function is called but the main script is paused allowing it not to check for subsequent interrupt flags...

Also I think there maybe a problem when multiple handles send autoit msgs, usually when I run with 1 client my error rate is significantly lower

It might be that multiple handles sending autoit msgs is not handled in the internal queue properly, regardless, I think there is an error with the RegisterMessage handling protocol

This is my application side code that I used to test (note 2 clients ran this simultaneously):

function main()
{
var send;
addEventListener("keydown",
  function (key) {
   if (key === 45) { // insert
    send = true;
   }
  }
);
while (1)
{
  if (send)
  {
   doSomething( );
   send = false;
  }
  delay(100);
}
}

function doSomething()
{
for( var i = 0; i < 25; i++ )
{
  var data = sendCopyData(null, title, 0, message);
  if(data)
   return true;
  else
   return print(data);
  
  }
}
Edited by D3STROY3R

Share this post


Link to post
Share on other sites

Another way would be to intercept the autoit window proc, and install yours before, that checks for $wm_copydate. you can just call autoits after, and since your client code uses sendmessage, you are avoiding the getmessage queue.


Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

I'm currently implementing a command-line interface for AMT. My approach is that when an instance of AMT is already running that the new process sends the $CmdLineRaw via WM_COPYDATA to the first instance and exits. The first instance adds the data received to a scripting.dictionary object. When AMT becomes idle again I check the object for data (FIFO) to process.

Edited by KaFu

Share this post


Link to post
Share on other sites

That's what I've done with my applications too ...


_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 04/09/2015

Share this post


Link to post
Share on other sites

So from what I understand... basically take any received messages and reroute them to a "dummy" (which is hopefully not blocking) so that it is registered as a guigetmsg

and then handle it using the guigetmsg queue?

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Give this one a try...

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=test.exe
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$hwnd_AutoIt = _EnforceSingleInstance('e15ff08b-84ac-472a-89bf-5f92db683165') ; any 'unique' string; created with http://www.guidgen.com/Index.aspx
Opt("TrayIconHide", 1)

Global $oDict_ProcessingBuffer = ObjCreate('Scripting.Dictionary'), $iDict_ProcessingBuffer = 0
If Not IsObj($oDict_ProcessingBuffer) Then
    If MsgBox(4 + 16 + 262144, "Startup Error!", "Creating a ""Scripting.Dictionary"" object failed." & @CRLF & @CRLF & "If you are running XP without SP3, it might be necessary to install the Microsoft ""Windows Script"" for Windows XP redistributable." & @CRLF & @CRLF & "Do you want to search Google for the download?") = 6 Then
        ShellExecute("http://www.google.com/search?q=%22Windows+Script%22+download+microsoft")
    EndIf
    Exit
EndIf

Run(@ComSpec,@ScriptDir)

$hGUI = GUICreate("My GUI " & $hwnd_AutoIt, 300, 300, Default, Default,Default,$WS_EX_TOPMOST) ; will create a dialog box that when displayed is centered
$label = GUICtrlCreateLabel($CmdLineRaw, 10, 10, 300, 100)
GUISetState(@SW_SHOW) ; will display an empty dialog box

ControlSetText($hwnd_AutoIt, '', ControlGetHandle($hwnd_AutoIt, '', 'Edit1'), $hGUI) ; to pass hWnd of main GUI to AutoIt default GUI
GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA")

_CMDLine_Add2Buffer($CmdLineRaw)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch

    if $iDict_ProcessingBuffer Then GUICtrlSetData($label,TimerInit() & @TAB & _CMDLine_Process())

WEnd

_CMDLine_Flush_Queue()
GUIDelete()
Exit

Func _EnforceSingleInstance($GUID_Program = "")
    If $GUID_Program = "" Then Return
    $hwnd = WinGetHandle($GUID_Program)
    If IsHWnd($hwnd) Then
        $hwnd_Target = ControlGetText($hwnd, '', ControlGetHandle($hwnd, '', 'Edit1'))
        WM_COPYDATA_SendData(HWnd($hwnd_Target), $CmdLineRaw)
        Exit
    EndIf
    AutoItWinSetTitle($GUID_Program)
    Return WinGetHandle($GUID_Program)
EndFunc   ;==>_EnforceSingleInstance

Func WM_COPYDATA($hwnd, $MsgID, $wParam, $lParam)
    ; http://www.autoitscript.com/forum/index....?showtopic=105861&view=findpos
    ; Melba23, based on code from Yashied
    Local $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    Local $s_Buffer = DllStructGetData($tMsg, 1)
    $s_Buffer = _UTF8toUCS2($s_Buffer)
    _CMDLine_Add2Buffer($s_Buffer)
    Return 0
EndFunc   ;==>WM_COPYDATA

Func WM_COPYDATA_SendData($hwnd, $sData)
    If Not IsHWnd($hwnd) Then Return 0
    If $sData = "" Then $sData = " "
    $sData = _UCS2toUTF8($sData)
    Local $tCOPYDATA, $tMsg
    $tMsg = DllStructCreate("char[" & StringLen($sData) + 1 & "]")
    DllStructSetData($tMsg, 1, $sData)
    $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr")
    DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hwnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))
    If (@error) Or ($Ret[0] = -1) Then Return 0
    Return 1
EndFunc   ;==>WM_COPYDATA_SendData

Func _UCS2toUTF8($sString = "", $iFlag = 1)
    ; Convert UTF8 to ANSI to insert into DB

    ; http://www.autoitscript.com/forum/index.php?showtopic=85496&view=findpost&p=614497
    ; ProgAndy
    ; Make ANSI-string representation out of UTF-8

    ; $iFlag
    Local Const $SF_ANSI = 1
    Local Const $SF_UTF16_LE = 2
    Local Const $SF_UTF16_BE = 3
    Local Const $SF_UTF8 = 4

    Return BinaryToString(StringToBinary($sString, $SF_UTF8), $iFlag)
EndFunc   ;==>_UCS2toUTF8

Func _UTF8toUCS2($sString = "", $iFlag = 4)
    ; Extract ANSI and convert to UTF8 to display

    ; http://www.autoitscript.com/forum/index.php?showtopic=85496&view=findpost&p=614497
    ; ProgAndy
    ; convert ANSI-UTF8 representation to ANSI/Unicode

    Local Const $SF_ANSI = 1
    Local Const $SF_UTF16_LE = 2
    Local Const $SF_UTF16_BE = 3
    Local Const $SF_UTF8 = 4
    Return BinaryToString(StringToBinary($sString, $SF_ANSI), $iFlag)
EndFunc   ;==>_UTF8toUCS2

Func _CMDLine_Add2Buffer($sString)
    if not StringLen($sString) then Return
    $oDict_ProcessingBuffer.Add(TimerInit(),$sString)
    $iDict_ProcessingBuffer += 1
EndFunc   ;==>_CMDLine_Add2Buffer

Func _CMDLine_Flush_Queue()
    $oDict_ProcessingBuffer.RemoveAll()
    $iDict_ProcessingBuffer = 0
EndFunc

Func _CMDLine_Process()
    If Not $iDict_ProcessingBuffer Then Return
    Local $sReturn
    For $s_ProcessingBuffer_Key In $oDict_ProcessingBuffer.Keys()
        $sReturn = $oDict_ProcessingBuffer.Item($s_ProcessingBuffer_Key)
        $oDict_ProcessingBuffer.Remove($s_ProcessingBuffer_Key)
        $iDict_ProcessingBuffer -= 1
        ExitLoop
    Next
    Return $s_ProcessingBuffer_Key & "|" & $sReturn
EndFunc
Edited by KaFu

Share this post


Link to post
Share on other sites

Give this one a try...

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=test.exe
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$hwnd_AutoIt = _EnforceSingleInstance('e15ff08b-84ac-472a-89bf-5f92db683165') ; any 'unique' string; created with http://www.guidgen.com/Index.aspx
Opt("TrayIconHide", 1)

Global $oDict_ProcessingBuffer = ObjCreate('Scripting.Dictionary'), $iDict_ProcessingBuffer = 0
If Not IsObj($oDict_ProcessingBuffer) Then
    If MsgBox(4 + 16 + 262144, "Startup Error!", "Creating a ""Scripting.Dictionary"" object failed." & @CRLF & @CRLF & "If you are running XP without SP3, it might be necessary to install the Microsoft ""Windows Script"" for Windows XP redistributable." & @CRLF & @CRLF & "Do you want to search Google for the download?") = 6 Then
        ShellExecute("http://www.google.com/search?q=%22Windows+Script%22+download+microsoft")
    EndIf
    Exit
EndIf

Run(@ComSpec,@ScriptDir)

$hGUI = GUICreate("My GUI " & $hwnd_AutoIt, 300, 300, Default, Default,Default,$WS_EX_TOPMOST) ; will create a dialog box that when displayed is centered
$label = GUICtrlCreateLabel($CmdLineRaw, 10, 10, 300, 100)
GUISetState(@SW_SHOW) ; will display an empty dialog box

ControlSetText($hwnd_AutoIt, '', ControlGetHandle($hwnd_AutoIt, '', 'Edit1'), $hGUI) ; to pass hWnd of main GUI to AutoIt default GUI
GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA")

_CMDLine_Add2Buffer($CmdLineRaw)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch

    if $iDict_ProcessingBuffer Then GUICtrlSetData($label,TimerInit() & @TAB & _CMDLine_Process())

WEnd

_CMDLine_Flush_Queue()
GUIDelete()
Exit

Func _EnforceSingleInstance($GUID_Program = "")
    If $GUID_Program = "" Then Return
    $hwnd = WinGetHandle($GUID_Program)
    If IsHWnd($hwnd) Then
        $hwnd_Target = ControlGetText($hwnd, '', ControlGetHandle($hwnd, '', 'Edit1'))
        WM_COPYDATA_SendData(HWnd($hwnd_Target), $CmdLineRaw)
        Exit
    EndIf
    AutoItWinSetTitle($GUID_Program)
    Return WinGetHandle($GUID_Program)
EndFunc   ;==>_EnforceSingleInstance

Func WM_COPYDATA($hwnd, $MsgID, $wParam, $lParam)
    ; http://www.autoitscript.com/forum/index....?showtopic=105861&view=findpos
    ; Melba23, based on code from Yashied
    Local $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    Local $s_Buffer = DllStructGetData($tMsg, 1)
    $s_Buffer = _UTF8toUCS2($s_Buffer)
    _CMDLine_Add2Buffer($s_Buffer)
    Return 0
EndFunc   ;==>WM_COPYDATA

Func WM_COPYDATA_SendData($hwnd, $sData)
    If Not IsHWnd($hwnd) Then Return 0
    If $sData = "" Then $sData = " "
    $sData = _UCS2toUTF8($sData)
    Local $tCOPYDATA, $tMsg
    $tMsg = DllStructCreate("char[" & StringLen($sData) + 1 & "]")
    DllStructSetData($tMsg, 1, $sData)
    $tCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr")
    DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hwnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))
    If (@error) Or ($Ret[0] = -1) Then Return 0
    Return 1
EndFunc   ;==>WM_COPYDATA_SendData

Func _UCS2toUTF8($sString = "", $iFlag = 1)
    ; Convert UTF8 to ANSI to insert into DB

    ; http://www.autoitscript.com/forum/index.php?showtopic=85496&view=findpost&p=614497
    ; ProgAndy
    ; Make ANSI-string representation out of UTF-8

    ; $iFlag
    Local Const $SF_ANSI = 1
    Local Const $SF_UTF16_LE = 2
    Local Const $SF_UTF16_BE = 3
    Local Const $SF_UTF8 = 4

    Return BinaryToString(StringToBinary($sString, $SF_UTF8), $iFlag)
EndFunc   ;==>_UCS2toUTF8

Func _UTF8toUCS2($sString = "", $iFlag = 4)
    ; Extract ANSI and convert to UTF8 to display

    ; http://www.autoitscript.com/forum/index.php?showtopic=85496&view=findpost&p=614497
    ; ProgAndy
    ; convert ANSI-UTF8 representation to ANSI/Unicode

    Local Const $SF_ANSI = 1
    Local Const $SF_UTF16_LE = 2
    Local Const $SF_UTF16_BE = 3
    Local Const $SF_UTF8 = 4
    Return BinaryToString(StringToBinary($sString, $SF_ANSI), $iFlag)
EndFunc   ;==>_UTF8toUCS2

Func _CMDLine_Add2Buffer($sString)
    if not StringLen($sString) then Return
    $oDict_ProcessingBuffer.Add(TimerInit(),$sString)
    $iDict_ProcessingBuffer += 1
EndFunc   ;==>_CMDLine_Add2Buffer

Func _CMDLine_Flush_Queue()
    $oDict_ProcessingBuffer.RemoveAll()
    $iDict_ProcessingBuffer = 0
EndFunc

Func _CMDLine_Process()
    If Not $iDict_ProcessingBuffer Then Return
    Local $sReturn
    For $s_ProcessingBuffer_Key In $oDict_ProcessingBuffer.Keys()
        $sReturn = $oDict_ProcessingBuffer.Item($s_ProcessingBuffer_Key)
        $oDict_ProcessingBuffer.Remove($s_ProcessingBuffer_Key)
        $iDict_ProcessingBuffer -= 1
        ExitLoop
    Next
    Return $s_ProcessingBuffer_Key & "|" & $sReturn
EndFunc

thanks for your post, just by looking at it, yes that would work (given that your _CMDLine_Add2Buffer() actually gets to execute)

as long as _CMDLine_Add2Buffer() is non blocking it would work

and for me with 2 clients it will probably also work but for n client's I don't know if it will work

I think there is still a design problem with how autoit is retrieving from windows message queue...

your method is basically the same thing i was suggesting in terms of creating a dummy window... and triggering it as a GUIGetMsg and let GUIGetMsg handle the push/pop method you implemented with the Buffer += 1 and when retrieved Buffer -= 1

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  
Followers 0