
bobmcrae
Members-
Posts
19 -
Joined
-
Last visited
Everything posted by bobmcrae
-
I have been testing the stability of using mysqllib.dll & the associated UDF, like this fine one. However, I have run into a problem for which I don't see an elegant solution. Specifically, once the connection to the server is lost (I have only tested when I lose internet connection so far), the DLL becomes non-responsive and then crashes the AutoIT script with an exit code of 3221225477. I will post the simple test below, which is an adaptation of @ProgAndy's test.au3. I added in a response to a lost connection, including a poll until internet connection is re-established. I have tried different versions of the mysqllib.dll, but to no avail. Also, while there are plenty of posts out there on this issue, I have not found a good work-around. #include "mysql.au3" Global $MysqlConn _MySQL_InitLibrary() $MysqlConn = _MySQL_Init() $connected = _MySQL_Real_Connect($MysqlConn,"****","adminuser","****","wellchec", 3306) While True $ping = _MySQL_Ping($MysqlConn) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ping = ' & $ping & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If $ping=1 Then _reconnectDB($MysqlConn) $sleepTime = Random(1000,20000,1) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sleepTime = ' & $sleepTime & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console Sleep($sleepTime) WEnd _MySQL_Close($MysqlConn) _MySQL_EndLibrary() Func _reconnectDB($MysqlConn) _MySQL_Close($MysqlConn) _MySQL_EndLibrary() Do Sleep(1000) Until Ping('google.com') _MySQL_InitLibrary() If @error Then Exit MsgBox(0, '', "") $MysqlConn = _MySQL_Init() _MySQL_Real_Connect($MysqlConn,"****","adminuser","****","wellchec", 3306) EndFunc ; _reconnectDB() Here is the console listing after a run where I disconnect from my wireless network, then reconnect. >Running:(3.3.14.1):C:\Program Files\AutoIt3\autoit3.exe "C:\Users\Public\Desktop\Pt.Data\Reports\mysql(20160710010357)\test.au3" --> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop @@ Debug(19) : $ping = 0 >Error code: 0 @@ Debug(24) : $sleepTime = 15798 >Error code: 0 @@ Debug(19) : $ping = 1 >Error code: 0 @@ Debug(24) : $sleepTime = 5969 >Error code: 0 !>09:33:32 AutoIt3.exe ended.rc:-1073741819 +>09:33:32 AutoIt3Wrapper Finished. >Exit code: 3221225477 Time: 81.51
-
Well, I guess I just needed to "verbalize" the problem...I traced the issue to another UDF include (VirtualFlex.Memory.au3 by @prazetto), which apparently is causing the SIGNIFICANT slow-down. I only use this UDF in one place and could probably do without. So, in the absence of time to investigate, I am going to remove that dependency. In doing so, the BIG script now returns the _getNetworkDrive function in a few milliseconds. I suspect the VirtualFlex.Memory.au3 UDF virtualization causes the slow-down maybe @prazetto could investigate the issue?
-
How weird, I posted the code in the original posting using the <> (code) tool. I'll try again here. Jos, the times I was reporting were from a consolewrite of TimerInit & TimerDiff portions built into the function. Hopefully, you can see that below. Func _getNetworkDrive() $t1 = TimerInit() ; Iterate through the network drives $driveDetails = '\\xxx.brickftp.com@SSL\DavWWWRoot' ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $driveDetails = ' & $driveDetails & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $drives = DriveGetDrive('Network') If UBound($drives)>=2 Then For $i=1 To $drives[0] $drive = $drives[$i] ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $drive = ' & $drive & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If StringInStr(DriveMapGet($drive), $driveDetails) And FileExists($drive) Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : TimerDiff($t1) = ' & TimerDiff($t1) & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console Return $drive EndIf Next EndIf ; No drive found, attempt to map $drive = DriveMapAdd('*', $driveDetails, 1, $sftpCpUser, $sftpCpPass) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : TimerDiff($t1) = ' & TimerDiff($t1) & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If Not $drive Then Return SetError(-1, 0, 'Network drive (' & $driveDetails & ') could not be mapped') EndFunc ; _getNetworkDrive()
-
I have a very simple UDF, which contains a few "helper" functions, like the one below (_getNetworkDrive). I notice that when I call this function from my main script, which is approaching 3000-lines of code (big & some what complex), the performance of the UDF function _getNetworkDrive is very slow as compared to when I call the same function from a simple test script. I do not have any different processing happening (e.g., launching another script) between the BIG script and the small test script. I also confirmed that the CPU & memory are nominal (not significantly different from the test script) when the BIG script is running the _getNetworkDrive function. To quantify the performance hit, I ran several times with the test script and see that the function takes about 30-mSec, with a few peaks near 300-mSec. The same function/UDF called from the BIG script takes anywhere from 1-second (on the low end) to as much as 16-seconds! So, we're talking about 2-3 orders of magnitude difference. The majority of processing time seems to be in the For/Next loop that is iterating through the drives. I suspect that the culprit is the FileExists($drive) conditional check, but I cannot understand why that would be the case when called from a larger script. Any ideas of why the UDF function's performance would suffer when part of a larger script? zc?&R6?73?&?46?FR&WGG?&??B??r?WF??B#?ФgV?2?vWD?WGv?&?G&?fR??Р???FW&FRF?&?Vv?F?R?WGv?&?G&?fW0Р?FG&?fTFWF??2?b33???LJ???'&?6?gG?6??54??Feuuu&??Bb33??Р?FG&?fW2?G&?fTvWDG&?fR?b33???WGv?&?b33???Р??bT&?V?B?FG&?fW2?fwC??"F?V?Р??f?"F??F?FG&?fW5??Р???FG&?fR?FG&?fW5?F??Р????b7G&??t??7G"?G&?fT?vWB?FG&?fR??FG&?fTFWF??2??Bf??TW??7G2?FG&?fR?F?V?Р????&WGW&?FG&?fPР???V?D?`Р???W?@Р?V?D?`РР????G&?fRf?V?B?GFV?BF??Р?FG&?fR?G&?fT?FB?b33???b33???FG&?fTFWF??2??G6gG7W6W"?G6gG772?Р??b??BFG&?fRF?V?&WGW&?6WDW'&?"????b33???WGv?&?G&?fR?b33??f??FG&?fTFWF??2f??b33???6?V?B??B&R?VBb33???РФV?DgV?2??vWD?WGv?&?G&?fR????&S???
-
@Chiitus, it looks like perhaps you did not copy the entire UIAutomation.au3 UDF, as the function _getAeFromHandle is at the bottom of the code above...take another look.
- 12 replies
-
- uiautomation
- simplespy
-
(and 2 more)
Tagged with:
-
Thanks guys. I was really struggling to follow even the simple examples, but after writing the main functionality of populating a form in C#, I was able to understand the Automation class a bit further -- without the abstraction of AutoIT. Then, I turned my attention back to AutoIT and with your guidance above and the C# experience, I wrote a simple UDF for my specific case. Not only do I appreciate the more AutoIT native syntax, the speed is now fully reasonable. The _UAI_SetVar and _UAI_Action methods (using the unaltered UIAWrappers.au3) takes ~4-seconds to enter a user name into a text field. The revised code below populates that field in ~20-milliseconds. Yeah! Thanks again for the guidance. Sample Code: #include "UIAutomation.au3" ; find parent element $hWindow = WinGetHandle('Sunlight MiniOmni') $aeParent = _getAeFromHandle($hWindow) ; find target element $aeTarget = _getAeFromCondition($aeParent, $UIA_AutomationIdPropertyId, 'txtUserName') ; set target element value _setAeValue($aeTarget, 'username here') My Simple UDF (UIAutomation.au3): #include "CUIAutomation2.au3" Global $aInterfaceObj _UIAutomationInit() Func _UIAutomationInit() $aInterfaceObj = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtagIUIAutomation ) Return IsObj($aInterfaceObj) ? $aInterfaceObj : False EndFunc ; _UIAutomationInit() Func _setAeValue($aeTarget, $valueStr) Local $patternPointer If Not IsObj($aeTarget) Then Return False $aeTarget.GetCurrentPattern($UIA_ValuePatternId, $patternPointer) $aePattern = ObjCreateInterface( $patternPointer, $sIID_IUIAutomationValuePattern, $dtagIUIAutomationValuePattern) $aePattern.SetValue($valueStr) EndFunc ;_setAeValue() Func _getAeFromCondition($aeParent, $propType, $propStr) Local $targetPointer, $propCondInterfaceObj If Not IsObj($aInterfaceObj) Then Return False If Not IsObj($aInterfaceObj) Then Return False If Not IsObj($aeParent) Then Return False $aInterfaceObj.createPropertyCondition( $propType, $propStr, $propCondInterfaceObj ) $aeParent.FindFirst( $TreeScope_Descendants, $propCondInterfaceObj, $targetPointer) $ae = ObjCreateInterface( $targetPointer, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) Return IsObj($ae) ? $ae : False EndFunc ; _getAeFromCondition() Func _getAeFromHandle($hWindow) Local $winPointer If Not WinExists($hWindow) Then Return False If Not IsObj($aInterfaceObj) Then Return False $aInterfaceObj.ElementFromHandle( $hWindow, $winPointer ) $ae = ObjCreateInterface( $winPointer, $sIID_IUIAutomationElement, $dtagIUIAutomationElement ) Return IsObj($ae) ? $ae : False EndFunc ; _getAeFromHandle()
- 12 replies
-
- uiautomation
- simplespy
-
(and 2 more)
Tagged with:
-
I am experimenting with UIAWrappers.au3 from junkew to complete an application which presents absolutely no control information using AutoIT Window Info. While I am able to complete the form successfully, I am not happy with the speed. As a benchmark, the simple Send method occurs in far less than 1-second, but the UIAutomation approach takes 3-seconds. I am wondering whether performance gains may be achieved by specifying the controls more precisely; but I am unsure how to do that. I was able to speed things up a bit by setting $UIA_DefaultWaitTime=0. The controls of interest are 5-levels deep, as show in the simplespy output below. It seems I do get faster response by specifying the target/top-level window, as show in the code below. Any ideas? #include "UIAWrappers.au3" _UIA_setVar("Global.Debug", False) _UIA_setVar("Global.Debug.File", False) _UIA_setVar("Global.Highlight", False) _UIA_setVar("DPN","Title:=NC-stat DPNCheck Communicator;controltype:=UIA_WindowControlTypeId;class:=Window") _UIA_action('DPN','setFocus') _UIA_setVar("DPN.firstName","AutomationId:=txtFirstName") _UIA_setVar("DPN.lastName", "AutomationId:=txtLastName") _UIA_Action('DPN.lastName','setvalue','last name') _UIA_setVar("DPN.ID", "AutomationId:=txtSubjectId") _UIA_setVar("DPN.DOB", "AutomationId:=PART_TextBox") _UIA_setVar("DPN.Ft", "AutomationId:=txtSubjectHeight") _UIA_setVar("DPN.In", "AutomationId:=txtSubjectHeight2") _UIA_Action('DPN.firstName','setvalue','first name') _UIA_Action('DPN.ID','setvalue','ID012345') _UIA_Action('DPN.DOB','setvalue','1/31/1932') _UIA_Action('DPN.Ft','setvalue','6') _UIA_Action('DPN.In','setvalue','1') SimpleSpy output: ;~ *** Standard code *** #include "UIAWrappers.au3" AutoItSetOption("MustDeclareVars", 1) Local $oP4=_UIA_getObjectByFindAll($UIA_oDesktop, "Title:=NC-stat DPNCheck Communicator;controltype:=UIA_WindowControlTypeId;class:=Window", $treescope_children) _UIA_Action($oP4,"setfocus") Local $oP3=_UIA_getObjectByFindAll($oP4, "Title:=;controltype:=UIA_PaneControlTypeId;class:=Frame", $treescope_children) Local $oP2=_UIA_getObjectByFindAll($oP3, "Title:=;controltype:=UIA_TabControlTypeId;class:=TabControl", $treescope_children) Local $oP1=_UIA_getObjectByFindAll($oP2, "Title:=Patient;controltype:=UIA_TabItemControlTypeId;class:=TabItem", $treescope_children) Local $oP0=_UIA_getObjectByFindAll($oP1, "Title:=;controltype:=UIA_PaneControlTypeId;class:=Frame", $treescope_children) ;~ First find the object in the parent before you can do something ;~$oUIElement=_UIA_getObjectByFindAll(".mainwindow", "title:=;ControlType:=UIA_EditControlTypeId", $treescope_subtree) Local $oUIElement=_UIA_getObjectByFindAll($oP0, "title:=;ControlType:=UIA_EditControlTypeId", $treescope_subtree) _UIA_action($oUIElement,"click")
- 12 replies
-
- uiautomation
- simplespy
-
(and 2 more)
Tagged with:
-
t0nz: no issues whatsoever. While I have not stress tested it; it's performance has been extraordinary and never have a I noticed a "missed" file event
-
JohnOne, no: it appears the csrss / session 1 correlates ONLY to mouse & keyboard actions. Just startup task manager and watch that process IO Reads without touching the mouse or keyboard. While csrss may have other responsibilities, it seems to correlate almost entirely with keyboard and mouse activity. As an example, I logged into a remote PC I work with and took a snapshot of the IO Reads; 20-minutes later it's exactly the same value. Edit: After ~2-hours the IO Reads remain the same on the PC referenced above.
-
This thread is a bit dated, but I thought I'd add in case anyone needs to find out whether the system is idle. Essentially, you can check the IO Reads from the process csrss.exe, session 1. Global $lastIOReads, $currentIOReads Global $MINUTES = 1000*60 Global $sleepTime = Round(1*$MINUTES,0) pauseIfNotIdle() Func pauseIfNotIdle() if $lastIOReads='' Then ; checks to see if this is the first call of this function $lastIOReads = _getIOReads() ; sets initial value Sleep($sleepTime) ; sleep, to look for idle $currentIOReads = _getIOReads() ; wake & check whether there has been any user input Else $lastIOReads = $currentIOReads ; not the first call, set last IO reads = the most recent $currentIOReads = _getIOReads() ; set IO reads to current EndIf While $lastIOReads<>$currentIOReads ; if there has been a change in the IO reads, do the loop Sleep($sleepTime) $lastIOReads = $currentIOReads ; set last IO reads = the most recent $currentIOReads = _getIOReads() ; set IO reads to current WEnd EndFunc ; pauseIfNotIdle() Func _getIOReads() Local $objWMIService = ObjGet("winmgmts:\root\CIMV2") Local $colItems = $objWMIService.ExecQuery('SELECT * FROM Win32_process where name="csrss.exe" and sessionId=1') ; csrss is the Windows input exe; session 1 is console, which is the active session If IsObj($colItems) then ; csrss will change its IO Reads with input to the keyboard or mouse For $objItem In $colItems Return $objItem.ReadOperationCount ; get IO reads Next Else Return False Endif EndFunc ; getIOReads()
-
Excellent work Sean. This monitoring approach seems to be far superior to the WMI query approach as discussed in this thread:
-
While happy with the solution of controlling the rouge WMI query, I was still not happy with the trade-off between polling frequency and CPU load. So, I just implemented in the same manner (same directory monitored) the approach by seangriffin. WOW! Not only do I get ***instantaneous*** notifications, the CPU load is non-existent. (Of course I checked all other processes as well.) The approach Mr Griffin implements in his UDF is FAR more efficient and comes without the tradeoff of polling frequency & load. Nice work Sean!
-
Folks, After implementing my second file system monitor -- this time an asynchronous one (ExecNotificationQueryAsync), I learned a few VERY important things. First, I was fooled that my script & this method was computationally efficient. When looking at the script run, I was seeing 0-3% CPU utilization, with mostly idle. However, I noticed my PC's overall CPU seemed to spike periodically -- with the frequency of the polling period. In fact, viewing ALL processes, I now see that the ExecNotificationQueryAsync initiates a separate process: WmiPrvSE.exe. As I had my polling frequency set to 1/sec, I would see this process consume about 35% of my CPU during each cycle -- non-trivial! Moreover, and more importantly, once I exited the script cleanly, the WmiPrvSE.exe continued on as if it were still polling. This process would not terminate on its own -- despite what MS indicates in the documentation. So, I came across a method that allows one to terminate/cancel the query. After implementing this single line of code in in my exit function, the WmiPrvSE.exe process CPU went to ZERO and eventually closed all together. In short, when using the ExecNotificationQueryAsync approach, I HIGHLY recommend including the cancel method on the sink after you are done polling ($sink.Cancel()). Partial code below. OnAutoItExitRegister('_exit') _pollQFApp() Func _pollQFApp() $wmiObj = ObjGet("winmgmts:\\localhost\root\CIMV2") $sinkObj = ObjCreate("WbemScripting.SWbemSink") ObjEvent($sinkObj, '_fileMonSink_') $wmiObj.ExecNotificationQueryAsync($sinkObj, "SELECT * FROM __InstanceCreationEvent Within 5 Where TargetInstance ISA 'Cim_DataFile' " & _ "and TargetInstance.Drive= 'C:' and TargetInstance.Path = '\\Users\\Public\\Desktop\\'") While 1 If ProcessExists($qfEXE)=0 Or ProcessExists($parentPID)=0 Then Exit ; terminate if one of the parent apps is terminated Sleep(250) WEnd EndFunc ; _pollQFApp() Func _fileMonSink_OnObjectReady($obj) $fileName = $obj.TargetInstance.Name ; do something EndFunc ;SINK_OnObjectReady() Func _exit() $sinkObj.Cancel() EndFunc ; _exit()
-
Run as Elevated Admin from Standard User Account
bobmcrae replied to AmbientMike's topic in AutoIt General Help and Support
It seems I have struggled with this topic for as long as this thread has been alive. While I have been successful at elevating from a standard user without prompting for the admin password (I know that password) using a technique very similar to what jazzyjeff describes in post #22, I have found that this approach is entirely dependent on the version of AutoIT the elevating script is compiled with. I have found that compiling with AutoIT v3.3.8.1 the elevating script properly elevates, but does NOT elevate when the exact script is compiled with AutoIT v3.3.14.1. I would LOVE to understand why the same VERY SIMPLE code works in the earlier version of AutoIT. Below is an example of what I am doing: Standard User Script: #include <File.au3> #include <dependentFiles\SystemInfo.au3> ; this is where $pw comes from Global $pw, $reEXE = @DocumentsCommonDir & '\runElevated.exe' FileInstall('dependentFiles\runElevated.exe', $reEXE, 1) $CMD = 'time ' & @HOUR +1 & ':' & @MIN ; set the clock forward an hour runElevated($CMD) Sleep(3000) $CMD = 'time ' & @HOUR -1 & ':' & @MIN ; set the clock back an hour runElevated($CMD) Func runElevated($CMD, $wait=False) Local $tmpBAT = _TempFile(@DocumentsCommonDir, Default, '.bat') ;~ A batch file is necesary in order to fully elevate (e.g., move command) FileWrite($tmpBAT,$CMD) If $pw = '' Then $pw = getPW() $pid = RunAs('Admin', @ComputerName, $pw, 0, $reEXE & ' ' & $tmpBAT, @SystemDir, @SW_SHOW, 8) EndFunc ; runElevated() Elevating Script (runElevated.au3): #RequireAdmin #NoTrayIcon RunWait(@ComSpec & ' /c ' & $CmdLineRaw,@SystemDir,@SW_HIDE)System details: Win7 HP; AUC: ConsentPromptBehaviorAdmin=0, ConsentPromptBehaviorUser=3 [I see that this should be =1, but that is mute] -
I have not found any implementation or guidance on the AutoIT forum regarding best practices for passwords in unattended scripts. More specifically, I have a lot of scripts that need access to the local PC Administrator account as well as remote servers, databases, etc. To date, I have basically included the passwords in the scripts, but really don't like doing that. Does anyone have some specific guidance, or -- better yet -- an example of a more secure way of saving these passwords in a more secure manner? I would prefer a truly free, open source or native Windows solution. Thanks in advance.
-
GraphGDIPlus UDF - Create GDI+ line graphs
bobmcrae replied to andybiochem's topic in AutoIt Example Scripts
UEZ: Perfect! I also like the fact that the string is associated with the graph object so its position is relative to the graph. Thanks very much for taking the time to help me with this issue. -
GraphGDIPlus UDF - Create GDI+ line graphs
bobmcrae replied to andybiochem's topic in AutoIt Example Scripts
Thanks for the super-fast reply & suggestion UEZ. I tried using $backbuffer, but that did not work (label did not display). I will troubleshoot some more with this suggestion though. $Graph = _GraphGDIPlus_Create($GUI,.08*$xSize,.06*$ySize,.9*$xSize,.8*$ySize,0xFF000000,0xFF88B3DD) ... _GraphGDIPlus_CreateLabel($Graph[17],'BFI: ' & getBFI($testFile),.93*$xSize,.25*$ySize,$RIGHT) -
GraphGDIPlus UDF - Create GDI+ line graphs
bobmcrae replied to andybiochem's topic in AutoIt Example Scripts
anybiochem, Congratulations on an excellent contribution to the AutoIT community. I have used this UDF for some graphing and it worked very well. I found the need to implement labels on a created graph. After a bit of work, I was able to get labels to display in the proper location and, generally, orientation. However, as the window is re-drawn (due to move, re-size, or losing focus) the labels in the graph area become occluded. You will see from the function I added to your UDF, I am not handling moves or re-sizes. While I have attempted to follow the UDF and realize that I probably need to add these new labels to the $aGraphArray, but unsure how to do that and whether that is even possible. Could you advise? Func _GraphGDIPlus_CreateLabel($hGUI,$text,$xPos,$yPos,$fontStyle=0x0000,$fontSize=14) $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI) _GDIPlus_GraphicsDrawString($hGraphic, $text, $xPos, $yPos,'Arial',$fontSize,$fontStyle) EndFunc