Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/18/2025 in all areas

  1. Hello friends, I haven't used AutoIt for a long time, but I always like these challenges, and I never forget you. Apparently there is some bug in how GUICtrlCreateObj works and I don't have time to look internally at the bug. This way I was able to create the instance of the object. #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Global Const $gATL = DllOpen("ATL.DLL") Global Const $gOleaut32 = DllOpen("oleaut32.dll") Global $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc") _TestOrdoWebView() Func _TestOrdoWebView() ConsoleWrite("AtlAxWinInit: " & AtlAxWinInit() & @CRLF) Local $pProgID = SysAllocString('OrdoWebView2.OrdoWebView') ConsoleWrite("SysAllocString('OrdoWebView2.OrdoWebView'): " & $pProgID & @CRLF) Local $hGUI = GUICreate("OrdoWebView2.OrdoWebView Test", (@DesktopWidth) / 1.2, (@DesktopHeight) / 1.2, Default, Default, BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS, $WS_CLIPCHILDREN)) Local $hResult = AtlAxCreateControl($pProgID, $hGUI) _SysFreeString($pProgID) Local $pIUnkown = AtlAxGetControl($hGUI) ConsoleWrite("AtlAxGetControl: " & $pIUnkown & @CRLF) GUISetState() Local $oOrdoWebView2 = ObjCreateInterface($pIUnkown, "{E54909AA-1705-44A9-8235-B24F74366B3F}") Local $oOrdoWebViewEvents = ObjEvent($oOrdoWebView2, "_OrdoWebView_", "__OrdoWebView") ConsoleWrite("$oOrdoWebView2: " & IsObj($oOrdoWebView2) & @CRLF) ConsoleWrite($oOrdoWebView2.GetWebView2Version() & @CRLF) ConsoleWrite($oOrdoWebView2.GetMostRecentInstallPath() & @CRLF) $oOrdoWebView2.Anchor = True $oOrdoWebView2.Search_URL = "https://search.yahoo.com/search?p=%1" $oOrdoWebView2.HomeURL = "http://www.google.com" $oOrdoWebView2.SearchEngine = 2 $oOrdoWebView2.SearchAuto = True $oOrdoWebView2.Init() While Not $oOrdoWebView2.IsWebViewInit() ;wait initialization otherwise Navigate will fail Sleep(100) WEnd $oOrdoWebView2.Navigate("https://www.autoitscript.com/forum/topic/204362-microsoft-edge-webview2-embed-web-code-in-your-native-application/page/9/#findComment-1542505") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>_TestOrdoWebView Func _OrdoWebView_InitComplete($oIEpDisp) ConsoleWrite("_OrdoWebView_InitComplete" & @CRLF) EndFunc ;==>_OrdoWebView_InitComplete Func AtlAxCreateControl($pProgID, $HWND) Local $aCall = DllCall($gATL, "long", "AtlAxCreateControl", "ptr", $pProgID, "handle", $HWND, "ptr", 0, "ptr", 0) If @error Then Return SetError(1, 0, -1) Return $aCall[0] EndFunc ;==>AtlAxCreateControl Func AtlAxGetControl($HWND) Local $aCall = DllCall($gATL, "long", "AtlAxGetControl", "handle", $HWND, "ptr*", 0) If @error Then Return SetError(1, 0, -1) Return $aCall[2] EndFunc ;==>AtlAxGetControl Func AtlAxWinInit() Local $aCall = DllCall($gATL, "bool", "AtlAxWinInit") If @error Then Return SetError(1, 0, -1) Return $aCall[0] EndFunc ;==>AtlAxWinInit Func _SysFreeString($pBSTR) ; Author: Prog@ndy If Not $pBSTR Then Return SetError(2, 0, 0) DllCall($gOleaut32, "none", "SysFreeString", "ptr", $pBSTR) If @error Then Return SetError(1, 0, 0) EndFunc ;==>_SysFreeString Func SysAllocString($str) ; Author: monoceres Local $aCall = DllCall($gOleaut32, "ptr", "SysAllocString", "wstr", $str) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;==>SysAllocString ; User's COM error function. Will be called if COM error occurs Func _ErrFunc($oError) ; Do anything here. ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_ErrFunc Saludos
    4 points
  2. Ok we're back with a new stuff in post #1. You'll first need to compile "playerDemo_engine.au3", then run "playerDemo.au3". We're still using a modal to block execution in the engine script - wish we could do something nicer, but I guess it'll have to do for now. For comms between processes we're using windows messages (thanks nine for the inspiration!). Look for the $WM_ME* values in the constants file. The WM codes are the same values as those generated by the mediaengine, combined with WM_APP. There's one totally "made up" code - its for MediaEngine to send through its window handle to the UI process ($WM_ME_PLAYBACKWINDOW). Also with the WMs, there's a bit of jiggery pokey in order to pass floating point values over wparam and lparam. I found if you send values as a float or double, they pop out as an integer on the other end - so you lose everything after the decimal point. But sending the values as binary solves this. We just need to ensure we convert our "doubles" to "floats" for x86 so the values fit within wparam/lparam. One last thing... you can still crash the engine by flooding it with messages from the UI, but that's where we're at for now. We could probably fix this by only check incoming messages from within the event handler... Then the problem is the engine won't be contactable when its paused, so you'd need to flick between two modes of checking for messages. And it would also require a total rethink of how to pass comms from the UI back to the engine!
    3 points
  3. pixelsearch, Thanks for the "tip"!! How is this [...greatly simplified...]: ; ----------------------------------------------- #include <File.au3> ; ----------------------------------------------- Opt("MustDeclareVars", 1) ; ----------------------------------------------- BrowseForFolder() ; ----------------------------------------------- Func BrowseForFolder() Local $sSelectedFolderPath = FileSelectFolder("Select an existing folder, or create a new folder.", "E:\Text\Native Instruments\Guitar Rig 5\Presets") Local $iFileExists = FileExists($sSelectedFolderPath) ; ----------------------------------------------- If $iFileExists Then BackupSoundData($sSelectedFolderPath) EndIf EndFunc ;==>BrowseForFolder ; ----------------------------------------------- Func BackupSoundData($sSelectedFolderPath) Local $sSrcPath = "E:\Text\Native Instruments\Guitar Rig 5\Sounds\*.ngrr" ; ----------------- Local $sDstPath = $sSelectedFolderPath ; ----------------- FileCopy($sSrcPath, $sDstPath, $FC_OVERWRITE) EndFunc ;==>BackupSoundData ; ----------------------------------------------- Question, "What do I do if the "Select Folder" option is selected - with no folder previously selected?"
    1 point
  4. TheSaint

    Kobo Cover Fixer

    Latest update now available, see the first post. Sometimes I make myself laugh ... which is probably a good thing. I can be so sure I've come to end of thinking of new additions and changes, and then something else pops into my brain while asleep or during waking. Such happened today, and so we have another update. Basically, as I was waking, I was contemplating how best to approach working with the Kobo device today. I knew the battery was flat, and that it takes around an hour to charge, so I had that window before I then started getting USB connection issues due to the device being fully charged. So I wanted to make the most of it. That was when it occurred to me that some kind of guide via my program would be helpful in speeding things up etc. That meant having controls (buttons) indicate they were the one to click to get started etc. The first approach I thought of, was using a graphic rectangle around a button, that was colored red, and hide or show that as needed. I'd done that before in a couple of programs, but as I recalled it, it could be a bit tricky ... and I couldn't recall what programs I'd done it to, so would either have to spend time searching for one, or attempt to do it all again from scratch. Then I thought that colored text on the buttons could be almost as effective, so did that instead. Of course, you could color the buttons instead, but you can lose the visual of the push effect. Latest Changes Anyway, I did some of that stuff after creating or adding images to my Kobo device. I managed to process over 100 entries today, and about a third of that was done before implementing the new auto NEXT option. Aside from one ebook, which I need to redo, all the others worked a treat. I'm not sure what happened with that one ebook, but I had connected my Kobo device via wifi a couple of times since building my working list, and sometimes missing number sub-folders and images on them get created during a sync, so it could be related to that. I used my newish 'Restore' option to reset for that entry, but not yet redone it because my Kobo was fully charged and the USB connection started playing up again. P.S. At this point I am not sure, if syncing sometimes causes a loss of number sub-folders and thus their contained cover images. In any case, I have been building a record with my program, and so I guess I will see if that ever happens, or is just the result of my device not downloading everything properly from Kobo.
    1 point
  5. Why not simply use the native FileSelectFolder() function to achieve your goal ? Just select any existing folder you like, or create a new folder where you like, all this with a single line code. The full path of the chosen (or created) folder will be returned by the function, unless you cancel the function window.
    1 point
  6. @Danyfirex Thanks a lot 👍 Have A great weekend !
    1 point
  7. @Danyfirex Look really great ! 👍 Can someone attach the OCX to the post please... Because the full installer is +300 Mb and we only need the OCX I guess. Thanks
    1 point
  8. Hi @Danyfirex, thank you so much for this script! Now I have put in the same directory as your script the folder \OrdoRC6 and the file OrdoWebView2.ocx (I also registered OrdoWebView2.ocx with the command "regsvr32 OrdoWebView2.ocx" from an admin prompt) and everything works like a charm. Thanks again for this "Easter gift" I will play with it in the next days. You are great!
    1 point
  9. MattyD

    BYO COM object

    So hopefully there's a better way of doing this, but I was pretty happy when this actually worked! We've been looking at some MediaFoundation stuff recently - and in order to spin up the MFMediaEngine object you must provide an interface to handle callbacks. Basically you are meant to write your own handler with an IMFEventNotify interface, then pass it to the factory. But how do you do this in AutoIt? Well it seems you can dodgy something up! IMFEventNotify object inherits from IUnknown has 1 method of its own - EventNotify . write the 4 methods and throw them into memory with DllCallbackRegister. Grab all the function pointers and pop them into an array. You now have yourself a vtable. The pointer to a vtable is an interface ptr. And that is a COM object! #include <WinAPI.au3> Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}" Global Const $sIID_IMFMediaEngineNotify = "{fee7c112-e776-42b5-9bbf-0048524e2bd5}" Global Const $tag_IMFMediaEngineNotify = "EventNotify hresult(uint; ulong_ptr; uint);" ;The Obj will look like this in memory. ;Only 2 interfaces are supported, IUnknown, and one derived from IUnknown. - They both can coexist in the one place ;for a more complex object we might need to store the locations of multiple vtables, and return the correct one with QueryInterface. ; - pIface -> +- pVtab -> +- pQueryInterface ; | | ; +- iRefCnt +- pAddRef ; | ; +- pRelease ; | ; +- pEventNotify Local $tEventNotify_QI = DllCallbackRegister("IMFEventNotiy_QueryInterface", "long", "ptr;ptr;ptr") Local $tEventNotify_AR = DllCallbackRegister("IMFEventNotiy_AddRef", "long", "ptr") Local $tEventNotify_R = DllCallbackRegister("IMFEventNotiy_Release", "long", "ptr") Local $tEventNotify_EN = DllCallbackRegister("IMFEventNotiy_EventNotify", "long", "ptr;dword;dword_ptr;dword") Local $tIMFMediaEngineNotify_Vtab = DllStructCreate("ptr pQueryInterface;ptr pAddRef;ptr pRelease;ptr pEventNotify") $tIMFMediaEngineNotify_Vtab.pQueryInterface = DllCallbackGetPtr($tEventNotify_QI) $tIMFMediaEngineNotify_Vtab.pAddRef = DllCallbackGetPtr($tEventNotify_AR) $tIMFMediaEngineNotify_Vtab.pRelease = DllCallbackGetPtr($tEventNotify_R) $tIMFMediaEngineNotify_Vtab.pEventNotify = DllCallbackGetPtr($tEventNotify_EN) Local $tIMFMediaEngineNotify = DllStructCreate("ptr pVTab;int iRefCnt") $tIMFMediaEngineNotify.pVtab = DllStructGetPtr($tIMFMediaEngineNotify_Vtab) Func IMFEventNotiy_QueryInterface($pThis, $pIID, $ppObj) ; hResult = oThis.QueryInterface(In pIID, Out pObj*) Local $hResult = $S_OK If Not $ppObj Then Return $E_POINTER Local $tRetObj = DllStructCreate("ptr pObj", $ppObj) ;pObj is ByRef, so ppObj should always be provided. Switch _WinAPI_StringFromGUID($pIID) ;These interfaces are located where we currently are! ;So return ptr to self. Case $sIID_IMFMediaEngineNotify, $sIID_IUnknown $tRetObj.pObj = $pThis IMFEventNotiy_AddRef($pThis) Case Else $tRetObj.pObj = 0 $hResult = $E_NOINTERFACE EndSwitch Return $hResult EndFunc ;==>IMFEventNotiy_QueryInterface Func IMFEventNotiy_AddRef($pThis) ; iRefCnt = oThis.AddRef() Local $tThis = DllStructCreate("ptr VTab;int RefCnt", $pThis) $tThis.RefCnt += 1 Return $tThis.RefCnt EndFunc ;==>IMFEventNotiy_AddRef Func IMFEventNotiy_Release($pThis) ;iRefCnt = oThis.Release() Local $tThis = DllStructCreate("ptr VTab;int RefCnt", $pThis) $tThis.RefCnt -= 1 ;I guess we could probably do some cleanup once RefCnt = 0. ;Not sure how best to do that!. Return $tThis.RefCnt EndFunc ;==>IMFEventNotiy_Release ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Define Event handler. Func IMFEventNotiy_EventNotify($pThis, $iEvent, $iParam1, $iParam2) ConsoleWrite(StringFormat("EventRecieved! Event: %d, Param1: %d, Param2: %d", $iEvent, $iParam1, $iParam2) & @CRLF) EndFunc ;==>IMFEventNotiy_EventNotify ;Ready to go! Local $pIMFMediaEngineNotify = DllStructGetPtr($tIMFMediaEngineNotify) ; Interface ptr (to IMFMediaEngineNotify) IMFEventNotiy_AddRef($pIMFMediaEngineNotify) ;The oject exists in mem, so refCnt should start at 1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Local $oIMFMediaEngineNotify = ObjCreateInterface($pIMFMediaEngineNotify, $sIID_IMFMediaEngineNotify, $tag_IMFMediaEngineNotify) ConsoleWrite("IsObj($oIMFMediaEngineNotify) = " & IsObj($oIMFMediaEngineNotify) & @CRLF & @CRLF) ;Test some methods. - Get IUnknown Iface, then "release" it. ConsoleWrite("QueryInterface Test:" & @CRLF) Local $pIUnknown, $tGUID = _WinAPI_GUIDFromString($sIID_IUnknown) $oIMFMediaEngineNotify.QueryInterface(DllStructGetPtr($tGUID), $pIUnknown) ConsoleWrite(StringFormat("$pIUnknown = %s", Ptr($pIUnknown)) & @CRLF) Local $oIUnknown = ObjCreateInterface($pIUnknown, $sIID_IUnknown, "") ConsoleWrite("RefCnt = " & $oIUnknown.Release() & ", .Release()" & @CRLF & @CRLF) ;Test external Addref call. ConsoleWrite("AddRef Test:" & @CRLF) ConsoleWrite("RefCnt = " & $oIMFMediaEngineNotify.AddRef() & ", .AddRef()" & @CRLF) ConsoleWrite("RefCnt = " & $oIMFMediaEngineNotify.Release() & ", .Release()" & @CRLF & @CRLF) ;Send an event. ConsoleWrite("EventNotify Test:" & @CRLF) $oIMFMediaEngineNotify.EventNotify(1, 2, 3)
    1 point
  10. Hi everyone 👋 , thank you in advance for looking at the little project and for thinking about supporting it (me) 😀 . Introduction I have a small AutoIt + SQLite GitHub project (sqlite-showcase). This serves at 1️⃣. glance to demonstrate how to use SQLite using concrete examples. If questions arise in the English or German forum about SQLite, I can provide direct assistance using the project and its example data. As 2️⃣. perspective, this project is intended as a module for a subsequent project that deals with something more than "just" AutoIt + SQLite - but more on that another time. I deliberately refrain from writing and explaining too many details here, because it is important to me, among other things, that the explanation on GitHub, in the form of a README file, can be handled or whether I need to make improvements there. Testing So far I have been able to test the project under Windows 10 (x64), with AutoIt v3.3.16.1 and with SQLite v3.49.0. Due to the support of the german AutoIt forum member(s), I could also test with Windows 11. Now I would be very happy if someone among you (several people are welcome) 🤗 would test other system configurations. See the following table: The test consists of the following parts: Read the README, understand what to do ==> If there are already problems understanding this, then I have to make improvements. Setting up the project (getting started) ==> Is the explanation in the README sufficient? You can test it on Windows 10 x86? Then please, great. Do you have an old version of AutoIt that you can test with? That's exactly what I need ==> Thanks. You want to try a different SQLite version? Why not, I appreciate it. Are the few SQLite functions running correctly or are there any errors? They shouldn't, but if they do, please let me know. Preconditions You don't need Git or GitHub, although Git is an advantage. A simple download of the project (zip) is completely sufficient (see README). Just a little time, curiosity, interest in learning something new or putting my approach to the test 😅 . 🔥 CHANGELOG can be found here. --------------------------------- Thank you very much for your interest and for your support. If you have any questions, please let me know. Thanks. Best regards Sven Update: Testing complete.
    1 point
  11. MattyD

    WinRT Object Libraries

    Hi folks, Attached below is one way of attacking WinRT Objects. These are essentially COM objects, however they don't have an IDispatch interface so ObjCreate() cannot be used. It is possible to expose them using ObjCreateInterface though. Alternately, DllCallAddress() may be used to access an object's functions directly from memory. I'm using the latter mainly because that's the path I started down first! To make sense of whats in the attachment... WinRT.au3 - Core high level functions that sit on top of interface libraries Includes Async and Collection implementations etc. So basic high level functionality. WinRTCore.au3 - Internal helper functions for interface libraries Interface Folder - Interface libraries (there are over 850 of these!). Essentially these wrap the functions in an interface's vtable Includes tags which may be used with ObjCreateInterface Enums Folder - Contains map datatypes that can be used to convert enumeration strings to their numeric type, or vice versa Classes Folder - doesn't actually contain code - A class file includes interface and enum files that belong to a class. Namespaces Folder - doesn't actually contain code - A namespace file includes classes that are related. Bonus: I've also uploaded a rudimentary WinRT Class Explorer if it happens to be useful to anyone. Bonus2: I've added a tool that installs/removes calltips for interface libraries. Original post: WinRT Libraries - Latest ClassExplorer.zip
    1 point
  12. $PropertyConditionFlags_MatchSubstring It's true that wildcards aren't supported. On the other hand, it's possible to search for substrings in string properties through the Windows 10 1809 update: ; enum PropertyConditionFlags Global Const $PropertyConditionFlags_None = 0 Global Const $PropertyConditionFlags_IgnoreCase = 1 Global Const $PropertyConditionFlags_MatchSubstring = 2 ; Windows 10-1809 To use the $PropertyConditionFlags_MatchSubstring constant, it's necessary to use a version of the UIA code that includes this Windows update. To do this, select the correct Windows Mode in UIASpy: Now the code generated automatically by UIASpy will look like this: #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 ;#AutoIt3Wrapper_UseX64=n ; If target application is running as 32 bit code ;#AutoIt3Wrapper_UseX64=y ; If target application is running as 64 bit code #include "UIA_Constants.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Functions.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_SafeArray.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Variant.au3" ; Can be copied from UIASpy Includes folder Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation8, $sIID_IUIAutomation6, $dtag_IUIAutomation6 ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement9, $dtag_IUIAutomationElement9 ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) EndFunc ; --- Find window/control --- ConsoleWrite( "--- Find window/control ---" & @CRLF ) Local $pCondition0 $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "Notepad", $pCondition0 ) If Not $pCondition0 Then Return ConsoleWrite( "$pCondition0 ERR" & @CRLF ) ConsoleWrite( "$pCondition0 OK" & @CRLF ) Local $pWindow1, $oWindow1 $oDesktop.FindFirst( $TreeScope_Children, $pCondition0, $pWindow1 ) $oWindow1 = ObjCreateInterface( $pWindow1, $sIID_IUIAutomationElement9, $dtag_IUIAutomationElement9 ) If Not IsObj( $oWindow1 ) Then Return ConsoleWrite( "$oWindow1 ERR" & @CRLF ) ConsoleWrite( "$oWindow1 OK" & @CRLF ) ; --- Element Properties --- ConsoleWrite( "--- Element Properties ---" & @CRLF ) Local $sName1 $oWindow1.GetCurrentPropertyValue( $UIA_NamePropertyId, $sName1 ) ConsoleWrite( "$sName1 = " & $sName1 & @CRLF ) In UIASpy, you generate the above code as follows: Sample code menu | Initial code | Complete code Click Notepad window in treeview to switch to info listview Right-click the $UIA_ClassNamePropertyId line | Create sample code Sample code menu | Properties ... | Right-click the $UIA_NamePropertyId line | Create sample code Right click code listview | Copy all items Paste the code into your editor Edit the code to make it runnable. And replace CreatePropertyCondition() with CreatePropertyConditionEx() to apply PropertyConditionFlags: #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 ;#AutoIt3Wrapper_UseX64=n ; If target application is running as 32 bit code ;#AutoIt3Wrapper_UseX64=y ; If target application is running as 64 bit code #include "UIA_Constants.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Functions.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_SafeArray.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Variant.au3" ; Can be copied from UIASpy Includes folder Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation8, $sIID_IUIAutomation6, $dtag_IUIAutomation6 ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement9, $dtag_IUIAutomationElement9 ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) ; --- Find window/control --- ConsoleWrite( "--- Find window/control ---" & @CRLF ) Local $pCondition0 ;$oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "Notepad", $pCondition0 ) $oUIAutomation.CreatePropertyConditionEx( $UIA_ClassNamePropertyId, "Note", $PropertyConditionFlags_MatchSubstring, $pCondition0 ) If Not $pCondition0 Then Return ConsoleWrite( "$pCondition0 ERR" & @CRLF ) ConsoleWrite( "$pCondition0 OK" & @CRLF ) Local $pWindow1, $oWindow1 $oDesktop.FindFirst( $TreeScope_Children, $pCondition0, $pWindow1 ) $oWindow1 = ObjCreateInterface( $pWindow1, $sIID_IUIAutomationElement9, $dtag_IUIAutomationElement9 ) If Not IsObj( $oWindow1 ) Then Return ConsoleWrite( "$oWindow1 ERR" & @CRLF ) ConsoleWrite( "$oWindow1 OK" & @CRLF ) ; --- Element Properties --- ConsoleWrite( "--- Element Properties ---" & @CRLF ) Local $sName1 $oWindow1.GetCurrentPropertyValue( $UIA_NamePropertyId, $sName1 ) ConsoleWrite( "$sName1 = " & $sName1 & @CRLF ) EndFunc SciTE output: $oUIAutomation OK $oDesktop OK --- Find window/control --- $pCondition0 OK $oWindow1 OK --- Element Properties --- $sName1 = Untitled - Notepad Example 16 Example 16 includes the original CUIAutomation2.au3 created by junkew, which contains all the Windows 7 constants. In newer versions of the UIA code I use UIA_Constants.au3 which contains all Windows 7 constants as well as all constants added in Windows 8, 8.1 and 10. The reason for the error in your code is that both CUIAutomation2.au3 and UIA_Constants.au3 is included. Only UIA_Constants.au3 should be included. Example 16 is an old example from March 9, 2019. Unfortunately, it's not possible for me to update all examples every time I update the UIA code. And the Windows 7 code still works, unless you need the newer code added in later Windows versions. To close a window with UIA code, use the Close method of the IUIAutomationWindowPattern interface. See examples 2 and 3 in Patterns (actions). Note that these are also old examples from March 9, 2019. If the Close method doesn't work, you can e.g. try using the UIA_MouseClick() function, which almost always works. UIA_MouseClick() is found in two different UDFs: UIA_Functions.au3, which is the new version based on UIA_Constants.au3, and UIA_Functions-a.au3, which is the old version based on CUIAutomation2.au3. Use the new version. An obvious error in your code is that you use the UIA_MouseClick() function with a pattern (action) object as input parameter. The correct input parameter is a window or control (a UIA element) object. Only UIA elements can be clicked. Not patterns (actions).
    1 point
  13. An obvious use of ROT objects is in connection with tasks such as inter-process communication (IPC). The advantage of using ROT objects for these tasks is partly that you can handle large amounts of data and partly that you can handle the vast majority of AutoIt data types. This thread implements a UDF for inter-process communication between two AutoIt scripts based on ROT objects. Simple exampleExamples\0) Sample\ is a simple example. There are 4 files in the folder: Sender.au3: #include "..\..\Includes\IPCROT_Sender.au3" Example() Func Example() ; Create array Local $aArray[1000][10] For $i = 0 To 1000 - 1 For $j = 0 To 9 $aArray[$i][$j] = $i & "/" & $j Next Next ; Send array IPCROT_Sender( "Example", $aArray ) MsgBox( 0, "Sender", "@error = " & @error & ", @extended = " & @extended & @CRLF ) $aArray = 0 EndFunc Receiver.au3: #include <Array.au3> #include "..\..\Includes\IPCROT_Receiver.au3" Example() Func Example() ; Get array Local $aArray IPCROT_Receiver( "Example", $aArray ) MsgBox( 0, "Receiver", "@error = " & @error & ", @extended = " & @extended & @CRLF ) _ArrayDisplay( $aArray, "Receiver" ) $aArray = 0 EndFunc Start1.au3: Run( @AutoItExe & " /AutoIt3ExecuteScript Sender.au3", "" ) Run( @AutoItExe & " /AutoIt3ExecuteScript Receiver.au3", "" ) Start2.au3: Run( @AutoItExe & " /AutoIt3ExecuteScript Receiver.au3", "" ) Run( @AutoItExe & " /AutoIt3ExecuteScript Sender.au3", "" ) Start1.au3 and Start2.au3 shows that it doesn't matter if you start Sender.au3 first or Receiver.au3 first. Another way to start the programs is to double-click Receiver.au3 and then double-click Sender.au3 within 10 seconds. Or double-click Sender.au3 and then double-click Receiver.au3 within 10 seconds. 10 seconds because the default timeout for both IPCROT_Sender() and IPCROT_Receiver() functions is 10 seconds. Timeout can be set via a parameter. Debug exampleExamples\1) Debug\ is a debug example. There are 3 files in the folder: Sender.au3: #include "..\..\Includes\IPCROT_SenderDebug.au3" Example() Func Example() ; Create array Local $aArray[1000][10] For $i = 0 To 1000 - 1 For $j = 0 To 9 $aArray[$i][$j] = $i & "/" & $j Next Next ; Send array Local $hDebug IPCROT_Sender( $hDebug, "Debug", $aArray ) MsgBox( 0, "Sender", "@error = " & @error & ", @extended = " & @extended & @CRLF ) EndFunc Receiver.au3: #include <Array.au3> #include "..\..\Includes\IPCROT_ReceiverDebug.au3" Example() Func Example() ; Get array Local $aArray, $hDebug IPCROT_Receiver( $hDebug, "Debug", $aArray ) MsgBox( 0, "Receiver", "@error = " & @error & ", @extended = " & @extended & @CRLF ) _ArrayDisplay( $aArray, "Receiver" ) $aArray = 0 EndFunc Start.au3: Run( @AutoItExe & " /AutoIt3ExecuteScript Sender.au3", "" ) Run( @AutoItExe & " /AutoIt3ExecuteScript Receiver.au3", "" ) The difference between the debug and non-debug versions is the include files and the way the IPCROT_Sender() and IPCROT_Receiver() functions are called. The debug functions must be called with an initial $hDebug parameter that is a reference to the debug window. The Debug window contains an Edit control to display debug information. If you run Start.au3, debug information is generated in this way: Sender Debug output: Establish communication with Receiver() function Info - Check that the (hidden) window "DebugIPCROT_SenderGui" doesn't exist Checking... Info - The (hidden) window "DebugIPCROT_SenderGui" doesn't exist Checked OK Info - Create window to establish communication between Sender and Receiver Creating... Info - "DebugIPCROT_SenderGui" to establish communication is created 0x002003BE Info - Get $hReceiverGui from "DebugIPCROT_ReceiverGui" window Get $hReceiverGui... Info - Got $hReceiverGui from "DebugIPCROT_ReceiverGui" window 0x000503B8 Info - Verify communication with Receiver by sending $hSenderGui to Receiver Verifying... Info - Communication with Receiver has been verified so far Verified OK Info - Sender has been running for a total of (milliseconds) 340.758703766091 Pass data from Sender() to Receiver() through ROT object Info - Register ROT object: $sROTNameId = Debug-{43EDDFE3-7803-402A-AC63-A122164C1853} Info - ROT object is registered: $sROTNameId = Debug-{43EDDFE3-7803-402A-AC63-A122164C1853} Info - Copy $sROTNameId to Receiver Copying... Info - $sROTNameId is copied to Receiver Copied OK Info - Get the ROT object Get ROT object... Info - Got the ROT object ROT object OK Info - Store data in ROT object, may be time consuming for large amounts of data Store data... Info - Data is stored in ROT object, the storing time is (milliseconds) 8.8428446044186 Info - Send "Data is ready message" to Receiver Data ready... Info - "Data is ready message" is send to Receiver Data ready OK Info - Idle loop until data is received by Receiver or an error has occurred Waiting (max 100 sec)... Info - Informed by Receiver that data is received Data received OK Info - Removing ROT object Removed OK Info - Sender has been running for a total of (milliseconds) 550.850650732295 Receiver Debug output: Establish communication with Sender() function Info - Check that the (hidden) window "DebugIPCROT_ReceiverGui" doesn't exist Checking... Info - The (hidden) window "DebugIPCROT_ReceiverGui" doesn't exist Checked OK Info - Create window to establish communication between Sender and Receiver Creating... Info - "DebugIPCROT_ReceiverGui" to establish communication is created 0x000503B8 Info - Get $hSenderGui from "DebugIPCROT_SenderGui" window Get $hSenderGui... Info - Got $hSenderGui from "DebugIPCROT_SenderGui" window 0x002003BE Info - Verify communication with Sender by sending $hReceiverGui to Sender Verifying... Info - Communication with Sender has been verified so far Verified OK Info - Receiver has been running for a total of (milliseconds) 342.119567626512 Receive data from Sender() through ROT object Info - Idle loop until data is ready for Receiver or an error has occurred Waiting (max 100 sec)... Info - $sROTNameId is received: $sROTNameId = Debug-{43EDDFE3-7803-402A-AC63-A122164C1853} Info - Received "Data is ready message" from Sender Data ready OK Info - Get the ROT object Get ROT object... Info - Got the ROT object ROT object OK Info - Load data from ROT object Load data... Info - Data is loaded from ROT object, the loading time is (milliseconds) 36.1543184155466 Info - Inform Sender that data has been received Data received OK Info - Receiver has been running for a total of (milliseconds) 508.463010656406 Note that there is no message loop in the debug windows. It's the MsgBoxes that keeps the debug windows open. When you close the Receiver MsgBox, the array received from the Sender() function is displayed with _ArrayDisplay(). Now, the _ArrayDisplay() function keeps the Receiver debug window open. When you close the _ArrayDisplay() window, the Receiver debug window also closes. When you close the Sender() MsgBox, the Sender debug window also closes. If you double-click Sender.au3 and wait for 10 seconds until timeout, you'll see this information. Sender Debug output: Establish communication with Receiver() function Info - Check that the (hidden) window "DebugIPCROT_SenderGui" doesn't exist Checking... Info - The (hidden) window "DebugIPCROT_SenderGui" doesn't exist Checked OK Info - Create window to establish communication between Sender and Receiver Creating... Info - "DebugIPCROT_SenderGui" to establish communication is created 0x0005039C Info - Get $hReceiverGui from "DebugIPCROT_ReceiverGui" window Get $hReceiverGui... Error - Couldn't get $hReceiverGui from "DebugIPCROT_ReceiverGui" window @error = 2, @extended = 0 Error - Sender has been trying until timeout after 10 seconds If you double-click Receiver.au3 and wait for 10 seconds until timeout, you'll see this information. Receiver Debug output: Establish communication with Sender() function Info - Check that the (hidden) window "DebugIPCROT_ReceiverGui" doesn't exist Checking... Info - The (hidden) window "DebugIPCROT_ReceiverGui" doesn't exist Checked OK Info - Create window to establish communication between Sender and Receiver Creating... Info - "DebugIPCROT_ReceiverGui" to establish communication is created 0x000603A6 Info - Get $hSenderGui from "DebugIPCROT_SenderGui" window Get $hSenderGui... Error - Couldn't get $hSenderGui from "DebugIPCROT_SenderGui" window @error = 2, @extended = 0 Error - Receiver has been trying until timeout after 10 seconds How does it work?From the debug information it should be possible to get an impression of how the code works. The code in both the IPCROT_Sender() and IPCROT_Receiver() functions is divided into two sections. The first section is about establishing communication with the other function. The second section is about the actual data transfer. Function header for IPCROT_Sender(): ; Success: Returns 1 ; Failure: Returns 0 ; Sets @error and @extended ; @error = 1: SenderGui error ; @error = 2: $hReceiverGui error ; @error = 3: Communication with Receiver cannot be verified ; @error = 4: ROT_RegisterObject error ; @error = 5: IPCROT_SendCopyData error ; @error = 6: Get the ROT object error ; @error = 7: Data is ready message error ; @error = 8: Error occured in Receiver() function ; @error = 9: Idle loop timeout, most likely an error ; @extended = zero based error occurrence Func IPCROT_Sender( _ ; Pass data (usually an array or object) from Sender to Receiver through ROT object. $sNameId, _ ; $sNameId is a unique identifier to secure multiple concurrent data communications. $vData, _ ; $vData is the data to be sent from Sender to Receiver, usually an array or object. $iTimeOut = 10 ) ; Time window to establish communication between Sender() and Receiver() functions. ; Does not include time for the actual data transfer. Time setting in seconds. Function header for IPCROT_Receiver(): ; Success: Returns 1 ; Failure: Returns 0 ; Sets @error and @extended ; @error = 1: ReceiverGui error ; @error = 2: $hSenderGui error ; @error = 3: Communication with Sender cannot be verified ; @error = 4: Error occured in Sender() function ; @error = 5: Get the ROT object error ; @error = 6: Idle loop timeout, most likely an error ; @extended = zero based error occurrence Func IPCROT_Receiver( _ ; Pass data (usually an array or object) from Sender to Receiver through ROT object. $sNameId, _ ; $sNameId is a unique identifier to secure multiple concurrent data communications. ByRef $vData, _ ; $vData is the data to be sent from Sender to Receiver, usually an array or object. $iTimeOut = 10 ) ; Time window to establish communication between Sender() and Receiver() functions. ; Does not include time for the actual data transfer. Time setting in seconds. Note that the debug versions of the functions have an additional $hDebug parameter as the first parameter. It's a reference to the debug window. Establish communication Sender-Receiver communication is established through simple Window automation. IPCROT_Sender() creates a (hidden) window titled $sNameId & "IPCROT_SenderGui". IPCROT_Receiver() creates a (hidden) window titled $sNameId & "IPCROT_ReceiverGui". The other function establishes communication by identifying this window. To establish communication between multiple Sender-Receiver pairs at once, $sNameId must be unique for each Sender-Receiver pair. And both the Sender and Receiver window must be opened within the timeout period. Data transfer When communication is established, it's the Sender who plays the role of server. Sender creates the ROT object, sends $sROTNameId to Receiver via a WM_COPYDATA message, stores data in the ROT object and sends a "Data is ready message" to the Receiver. $sROTNameId is created uniquely in this way: $sROTNameId = $sNameId & ROT_CreateGUID(). The Receiver plays the role of client. Once the Receiver has received the "Data is ready message", the Receiver accesses the ROT object with ObjGet() and retrieves the data. Receiver informs Sender that data has been received, which terminates the communication. Internal communication Information in the form of integers sent via WM_USER messages controls the internal communication between Sender and Receiver. IPCROT_Messages.au3: #include-once ; WM_USER messages Global Const $IPCROTMSG_iMsgToSender = 0x7FFF Global Const $IPCROTMSG_iMsgToReceiver = $IPCROTMSG_iMsgToSender - 1 ; Messages to Sender from Receiver Global Const $IPCROTMSG_iReceiverHandle = 1 Global Const $IPCROTMSG_iReceiverDataReceived = 2 Global Const $IPCROTMSG_iReceiverError = 3 Global $IPCROTMSG_iReceiverErrorValue = 4 Global Const $IPCROTMSG_iCommnError = 1 ; ReceiverErrorValue Global Const $IPCROTMSG_iGetROTobject = 4 ; Messages to Receiver from Sender ; $WM_COPYDATA to send $sROTNameId Global Const $IPCROTMSG_iSenderHandle = 5 Global Const $IPCROTMSG_iDataIsReady = 6 Global Const $IPCROTMSG_iSenderError = 7 Global $IPCROTMSG_iSenderErrorValue = 8 ;Global Const $IPCROTMSG_iCommnError = 1 ; SenderErrorValues Global Const $IPCROTMSG_iRegisterROTobject = 2 Global Const $IPCROTMSG_iCopyROTNameId = 3 ;Global Const $IPCROTMSG_iGetROTobject = 4 ; Sender/Receiver errors Global Const $IPCROTMSG_aErrorValues = [ _ "RegisterROTobject", _ "CopyROTNameId", _ "GetROTobject" ] Data typesExamples\2) Data types\ is about data types. The example is based on the example for the VarGetType() function in the help file. DataTypes.au3 is a slightly modified version of this example. Note that all remaining examples run in debug mode so it's possible to see what's going on. In Sender.au3, the various data types are stored in a dictionary object and sent in this way: Local $oDict = ObjCreate( "Scripting.Dictionary" ) $oDict( "$aArray" ) = $aArray $oDict( "$dBinary" ) = $dBinary $oDict( "$bBoolean" ) = $bBoolean $oDict( "$pPtr" ) = $pPtr $oDict( "$hWnd" ) = $hWnd $oDict( "$iInt" ) = $iInt $oDict( "$fFloat" ) = $fFloat $oDict( "$oObject" ) = $oObject $oDict( "$sString" ) = $sString $oDict( "$tStruct" ) = $tStruct $oDict( "$vKeyword" ) = $vKeyword $oDict( "$fuMsgBox" ) = $fuMsgBox $oDict( "$fuFunc" ) = $fuFunc $oDict( "$fuUserFunc" ) = $fuUserFunc ; Send $oDict Local $hDebug IPCROT_Sender( $hDebug, "DataTypes", $oDict ) Receiver.au3: #include "..\..\Includes\IPCROT_ReceiverDebug.au3" Example() Func Example() ; Get $oDict Local $oDict, $hDebug IPCROT_Receiver( $hDebug, "DataTypes", $oDict ) MsgBox( 0, "Receiver: Variable Types", _ "$aArray : " & @TAB & @TAB & VarGetType( $oDict( "$aArray" ) ) & " variable type." & @CRLF & _ "$dBinary : " & @TAB & @TAB & VarGetType( $oDict( "$dBinary" ) ) & " variable type." & @CRLF & _ "$bBoolean : " & @TAB & VarGetType( $oDict( "$bBoolean" ) ) & " variable type." & @CRLF & _ "$pPtr : " & @TAB & @TAB & VarGetType( $oDict( "$pPtr" ) ) & " variable type." & @CRLF & _ "$hWnd : " & @TAB & @TAB & VarGetType( $oDict( "$hWnd" ) ) & " variable type." & @CRLF & _ "$iInt : " & @TAB & @TAB & VarGetType( $oDict( "$iInt" ) ) & " variable type." & @CRLF & _ "$fFloat : " & @TAB & @TAB & VarGetType( $oDict( "$fFloat" ) ) & " variable type." & @CRLF & _ "$oObject : " & @TAB & VarGetType( $oDict( "$oObject" ) ) & " variable type." & @CRLF & _ "$sString : " & @TAB & @TAB & VarGetType( $oDict( "$sString" ) ) & " variable type." & @CRLF & _ "$tStruct : " & @TAB & @TAB & "Not recognized as a valid variable type." & @CRLF & _ "$vKeyword : " & @TAB & VarGetType( $oDict( "$vKeyword" ) ) & " variable type." & @CRLF & _ "fuMsgBox : " & @TAB & "Not recognized as a valid variable type." & @CRLF & _ "$fuFunc : " & @TAB & @TAB & "Not recognized as a valid variable type." & @CRLF & _ "$fuUserFunc : " & @TAB & "Not recognized as a valid variable type." ) EndFunc And this is the text in the Receiver MsgBox: $aArray : Array variable type. $dBinary : Binary variable type. $bBoolean : Bool variable type. $pPtr : Int32 variable type. $hWnd : Int32 variable type. $iInt : Int32 variable type. $fFloat : Double variable type. $oObject : Object variable type. $sString : String variable type. $tStruct : Not recognized as a valid variable type. $vKeyword : Keyword variable type. fuMsgBox : Not recognized as a valid variable type. $fuFunc : Not recognized as a valid variable type. $fuUserFunc : Not recognized as a valid variable type. Only the $tStruct and the function data types are not received correctly by the Receiver function. The Int32 types for $pPtr and $hWnd can easily be converted to pointer and window handles with the Ptr() and HWnd() functions. DllStructThe DllStruct data type ($tStruct in the example above) isn't a COM compatible data type and is therefore not received correctly by the Receiver function. But the Binary data type is received correctly. One way to handle the DllStruct is to convert it to a Binary before it's sent by the Sender() function. And then convert the Binary back to a DllStruct after it's received by the Receiver() function. Examples\3) DllStruct\ is about the DllStruct data type. Binary data What is Binary data and how is Binary data stored in internal AutoIt code? in Accessing AutoIt Variables in Tests\Examples\1) Simple variables\Example3.au3 all the data types in the example for the VarGetType() function are examined. This is the result for the Binary data type: $dBinary Type = Binary ptr = 0x009C59A0 ($pVariant) vt = 0x2011 (VT_ARRAY+VT_UI1, array of 1 byte unsigned integers) data = 0x009DABF8 This means that Binary data is stored internally as a safearray of bytes (also known as a bytearray). When Binary data is passed to a COM method as a parameter, the pointer to this safearray is passed in a variant. Sender and Receiver Sender.au3: #include "AccVars.au3" #include "..\..\Includes\IPCROT_SenderDebug.au3" Example() Func Example() Local Const $tagStruct = "struct;int var1;byte var2;uint var3;char var4[128];endstruct" Local $tStruct1 = DllStructCreate( $tagStruct ) DllStructSetData( $tStruct1, "var1", -1 ) DllStructSetData( $tStruct1, "var2", 255 ) DllStructSetData( $tStruct1, "var3", -1 ) ; The -1 (signed int) will be typecasted to unsigned int. DllStructSetData( $tStruct1, "var4", "Hello" ) ; Change data of element var4 (char) in $tStruct1, DllStructSetData( $tStruct1, "var4", Asc( "h" ), 1 ) ; at the index 1 of the char array (1 based index). Local $dBinary AccVars_DllStructToBinary( $tStruct1, $dBinary ) ; Convert DllStruct to Binary Local $oDict = ObjCreate( "Scripting.Dictionary" ) $oDict( "$tagStruct" ) = $tagStruct $oDict( "$dBinary" ) = $dBinary ; Send $oDict Local $hDebug IPCROT_Sender( $hDebug, "DllStruct", $oDict ) Local $iError = @error, $iExtended = @extended If $iError Then MsgBox( 0, "Sender", "@error = " & $iError & ", @extended = " & $iExtended & @CRLF ) Return EndIf MsgBox( 0, "Sender: $tStruct1", _ "Struct Size: " & DllStructGetSize( $tStruct1 ) & @CRLF & _ "Struct pointer: " & DllStructGetPtr( $tStruct1 ) & @CRLF & _ "Data:" & @CRLF & _ " " & DllStructGetData( $tStruct1, "var1" ) & @CRLF & _ " " & DllStructGetData( $tStruct1, "var2" ) & @CRLF & _ " " & DllStructGetData( $tStruct1, "var3" ) & @CRLF & _ " " & DllStructGetData( $tStruct1, "var4" ) ) EndFunc The DllStruct is copied from the example for the DllStructCreate() function in the help file. AccVars_DllStructToBinary() converts the DllStruct to Binary using the techniques from Accessing AutoIt Variables. The function is discussed below. $tagStruct and $dBinary are stored in a dictionary object and sent using the Sender() function. The original data in $tStruct1 looks like this in a MsgBox: Struct Size: 140 Struct pointer: 0x00B64EA8 Data: -1 255 4294967295 hello Receiver.au3: #include "..\..\Includes\IPCROT_ReceiverDebug.au3" Example() Func Example() ; Get $oDict Local $oDict, $hDebug IPCROT_Receiver( $hDebug, "DllStruct", $oDict ) Local $iError = @error, $iExtended = @extended If $iError Then MsgBox( 0, "Receiver", "@error = " & $iError & ", @extended = " & $iExtended & @CRLF ) Return EndIf Local $tagStruct = $oDict( "$tagStruct" ) Local $dBinary = $oDict( "$dBinary" ) ; Convert Binary to DllStruct Local $iSize = BinaryLen( $dBinary ) Local $tBytes = DllStructCreate( "byte[" & $iSize & "]" ) DllStructSetData( $tBytes, 1, $dBinary ) Local $tStruct2 = DllStructCreate( $tagStruct, DllStructGetPtr( $tBytes ) ) MsgBox( 0, "Receiver: $tStruct2", _ "Struct Size: " & DllStructGetSize( $tStruct2 ) & @CRLF & _ "Struct pointer: " & DllStructGetPtr( $tStruct2 ) & @CRLF & _ "Data:" & @CRLF & _ " " & DllStructGetData( $tStruct2, "var1" ) & @CRLF & _ " " & DllStructGetData( $tStruct2, "var2" ) & @CRLF & _ " " & DllStructGetData( $tStruct2, "var3" ) & @CRLF & _ " " & DllStructGetData( $tStruct2, "var4" ) ) EndFunc The dictionary object is received by the Receiver() function and $tagStruct and $dBinary are extracted. Converting the Binary data back to a DllStruct is straightforward. The received data in $tStruct2 looks like this in a MsgBox: Struct Size: 140 Struct pointer: 0x00C80510 Data: -1 255 4294967295 hello AccVars_DllStructToBinary() AccVars_DllStructToBinary() is included in AccVars.au3, which is a mini version of Accessing AutoIt Variables UDF. The function is used to convert a DllStruct to Binary. Func AccVars_DllStructToBinary( ByRef $tStruct, ByRef $dBinary ) ; Convert $tStruct to a DllStruct of bytes Local $iSize = DllStructGetSize( $tStruct ) Local $tByteArray = DllStructCreate( "byte[" & $iSize & "]", DllStructGetPtr( $tStruct ) ) ; Create a safearray to store the $tByteArray struct Local $tsaBound = DllStructCreate( $tagSAFEARRAYBOUND ) DllStructSetData( $tsaBound, "cElements", $iSize ) ; Size of safearray = size of $tByteArray struct DllStructSetData( $tsaBound, "lLbound", 0 ) Local $pSafeArray = SafeArrayCreate( $VT_UI1, 1, $tsaBound ) ; $VT_UI1 = safearray of bytes ; Get access to safearray data Local $pArrayData, $tArrayData SafeArrayAccessData( $pSafeArray, $pArrayData ) ; Get access to safearray data through an AutoIt DllStruct $tArrayData = DllStructCreate( "byte[" & $iSize & "]", $pArrayData ) ; Store $tByteArray in the safearray data area DllStructSetData( $tArrayData, 1, DllStructGetData( $tByteArray, 1 ) ) ; Unaccess safearray data SafeArrayUnaccessData( $pSafeArray ) ; Convert the safearray to the native AutoIt binary data type AccessVariables02( AccVars_ByteArrayToBinary, $pSafeArray, $dBinary ) EndFunc Func AccVars_ByteArrayToBinary( $pvSafeArray, $pvBinary ) ; $pvSafeArray is a variant that contains a pointer to a safearray Local $pSafeArray = DllStructGetData( DllStructCreate( "ptr", $pvSafeArray + 8 ), 1 ) ; Set $pvBinary to match a standard COM bytearray. A standard ; COM bytearray is a safearray of bytes stored inside a variant. ; Set vt element to $VT_ARRAY + $VT_UI1 (safearray of bytes) DllStructSetData( DllStructCreate( "word", $pvBinary ), 1, $VT_ARRAY + $VT_UI1 ) ; Set data element to safearray pointer DllStructSetData( DllStructCreate( "ptr", $pvBinary + 8 ), 1, $pSafeArray ) ; On function exit, the standard COM bytearray is converted to the native AutoIt binary data type ; This conversion is performed by internal AutoIt functions implemented as compiled C/C++ code EndFunc AccessVariables02() is defined in AccVars.au3. The whole purpose of using the techniques of Accessing AutoIt Variables is to exploit the internal COM conversions implemented in compiled C/C++ code to do all the hard work. Alternatively, it's possible to make the same conversions in a loop in (slow) interpreted AutoIt code. The Variant and Safearray UDFs are copied directly from Variants and Safearrays. Large array In Examples\4) Large array\, an array of 250,000 rows and 10 columns is created and sent from Sender to Receiver. In the debug windows you can see how long each sub-task takes. At the Receiver, the array is displayed in a virtual ArrayDisplay. The array is created with the functions of Fast Array Sorting and Management Functions UDF. Although this example is mostly about compiled code, most functions are also implemented in pure AutoIt code. One of these functions, FAS_Random2DArrayAu3(), is used to create the array. The function is found in Examples\Data Display\Resources\. A few code lines have been added to generate progress bar information. Examples\8) Two concurrent data transfers\ is also about large arrays. Other examples5) Array of arrays\ and 6) Array of objects\ is about arrays with embedded data. You can also create an array of embedded DllStructs. But then the DllStructs must be converted to Binary before the array is sent from Sender to Receiver. Arrays in the examples are 1D and 2D arrays. But it can also be 3D and 4D arrays. All valid AutoIt arrays are likely to work. 7) Two way data transfer\ demonstrates how to implement two-way data transfer. 7z-fileThe 7z-file contains source code for the UDF and examples. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. IPCviaROTobjects.7z
    1 point
×
×
  • Create New...