
DangerousDan
Active Members-
Posts
43 -
Joined
-
Last visited
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
DangerousDan's Achievements

Seeker (1/7)
2
Reputation
-
Rhidlor reacted to a post in a topic: AS400 PCOMM session objects
-
Dale, You don't need to use IEAttach at all... create the object, assign it theatre mode, full screen, and hide the status bar if you need to. So far I have found that the embedded object doesn't automatically take the focus when you selet the GUI title bar, so I added an "if winactive then winactivate" line in my main program loop. I'm sure there is a better solution, but I'm still not exactly an expert with GUI's... more like a seasoned amatuer:) Also of note: the vertical scroll bars do not redraw every time the window is resized, the GUI background color is shown until you mouseover the scroll bars or an element in the webpage that changes with the mouseover (button that emboldens, for example). I'm using _WinAPI_MoveWindow to move the embedded object when the parent moves, and have even tried manually redrawing the window after the move, hiding and unhiding it... many unconventional things as well as everything I could search for that was within my capabilities at this point, all to no avail. I worked around this by turning the scroll bars off and then back on any time the window is resized. It's a little messy visually, but it works. I'm using autoit to scrape customer account numbers, as they are viewed by sales in our AS400, to pull up in Salesforce.com. Most of our sales people are on thin clients. I had to find a way of getting the object without using the collections method in the IEAttach function... for some reason this part of the function always gets stuck in an endless loop on our thin clients.Took me forever to figure out that was the issue, and then quite awhile to figure out a way around it. The above methods work perfectly on a PC, but my solution works in our very restrictive thin client environment and appears to be more efficient in my limited experience. Your posts have been instrumental in my own coding, thank you for your posts and any criticism you may be wiling (anyone for that matter) to give on my code below. Have a good day, Dan #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPI.au3> #include <Constants.au3> #include <IE.au3> Func IECreatePseudoEmbedded($i_Left, $i_Top, $i_Width, $i_Height, $h_Parent) Local $o_IE, $h_HWND $o_IE = ObjCreate("InternetExplorer.Application") $o_IE.theatermode = True $o_IE.fullscreen = True $o_IE.statusbar = False $h_HWND = _IEPropertyGet($o_IE, "hwnd") _WinAPI_SetParent($h_HWND, $h_Parent) _WinAPI_MoveWindow($h_HWND, $i_Left, $i_Top, $i_Width, $i_Height, False) _WinAPI_SetWindowLong($h_HWND, $GWL_STYLE, $WS_POPUP + $WS_VISIBLE) Return $o_IE EndFunc ;==>IECreatePseudoEmbedded
-
Hello, I've been working on a script for work and have run into a brick wall trying to manage tabs in IE8. I've searched around and it seems there is no easy solution, or rather no solution that is within my current capabilities because DaleHomn referenced a lengthy workaround I couldn't quite grasp along with some very valuable information... so I created my own lengthy workaround For my specific requirement the script is going to initiate the instance of IE that I will manipulate, so the hwnd will be known. As long as the user doesn't change the order of the tabs manually after they are opened I can resolve the correct control key to use. If they decide they want to see google as the first tab even though they opened yahoo in the first tab I have no way of knowing based on the method below... does anyone have any ideas??? To test, just open a bunch of tabs, or even multiple IE windows with multiple tabs, and run the code then reorder your tabs manually and run again... note that the msgbox text refers to the original order, not what is currently displayed. Thanks in advance for any input. #include <IE.au3> Local $aIE[1][4], $oIE_Prev_hwnd, $oIE, $oIE_hwnd, $i_TabCTRLNum, $oIE_LocationName, $i_IENum $aIE[0][0] = 0 Local $i_Tabs = 1 While 1 $oIE = _IEAttach("", "instance", $i_Tabs) ; attach to each TAB in each open instance of IE If @error = $_IEStatus_NoMatch Then ExitLoop ; if there are no more tabs remaining to loop through $oIE_hwnd = _IEPropertyGet($oIE,"hwnd") ; get hwnd of the window corresponding to this tab If $oIE_hwnd <> $oIE_Prev_hwnd Then ; determine if the hwnd/window is different from the last tab $i_TabCTRLNum = 1 ; used to determine what control key to use in the control send function, if hwnd changed this is reset $i_IENum += 1 $oIE_Prev_hwnd = $oIE_hwnd EndIf $oIE_LocationName = _IEPropertyGet($oIE,"LocationName") ; this array should be dimmed to size according to your needs. for the purpose of this demo I'm using LocationName ReDim $aIE[$i_Tabs + 1][4] $aIE[$i_Tabs][0] = $oIE $aIE[$i_Tabs][1] = $oIE_hwnd $aIE[$i_Tabs][2] = $oIE_LocationName $aIE[$i_Tabs][3] = '"^'&$i_TabCTRLNum&'"' ; for use in the controlsend function to select a specific tab in a specific instance of IE $aIE[0][0] = $i_Tabs ; the number of open TABS $aIE[0][1] = $i_IENum ; the number of instances of IE $i_Tabs += 1 ; open tab counter $i_TabCTRLNum += 1 ; tab control number counter WEnd For $i = 1 To UBound ($aIE) - 1 WinActivate($aIE[$i][1]) ; activates a specific instance of IE WinWaitActive($aIE[$i][1]) WinActivate($aIE[$i][1]) ; I added this because with 10 tabs mixed HTTP and HTTPS open across 5 instances of IE ;sometimes the window wouldn't take focus even though the winwaitactive released the script ControlSend($aIE[$i][1],"","DirectUIHWND1",$aIE[$i][3]) ; selects a specific tab in a specific instance of IE MsgBox(0,"","the "&$aIE[$i][2]&" window should now be in focus") Next ; **Please Note ** if the tabs are reordered the control keys correspond to the new order but the order of ;windows returned by _IEAttach is still the original order, the script is broken by manually reordering tabs
-
I use IBM's AS400 Client Access software for work and over the last year or so have figured out how to connect to the session itself. This greatly simplifies sending and getting text as controlsend and clipget functions are not necessary. This will obviously be a little confusing to users who do not currently automate their AS400 tasks, but trust me it's much easier and infinitely more reliable using this method to send/get text. The below code is very rudimentary, I have offered it up so that someone else may not have to do quite as much reading/research to connect using only AutoIt. It was much easier finding VBA code to do this. I'm in sales, not software development, so my code is not going to be all that impressive to some of you. Please feel free to make any and all types of suggestions/comments/criticisms, I consider this one of the best ways to learn. Enough of my long winded explanations... on to the details. I use $Ps and $Oia as Globals so any/all functions can utilize them. The function sendtosession simply adds the "waitforinputready" ($Oia.InputInhibited) functionality to the default SendKeys function. This waits for the session to allow key presses so they don't all go to the buffer before the AS400 can accept your keys. In most instances the keys can be buffered with no ill effects, but I have run into some errors so I use it. I am not sure the autECLConnMgr is needed. I'm going to try commenting it out the next time I run one of my scripts, but perhaps someone else has some knowledge to add to this? Global $Ps, $Oia ;$Ps is the part you interact with, $Oia is the current message in the status bar $Session = "A" ; can be any session letter ;or you can use string functions to parse it from the active window as below(my typical usage as I use multiple monitors and sessions) $window = WinGetTitle("") $AS400hwnd = WinGetHandle($window) $Session = StringMid(WinGetTitle($AS400hwnd), 9, 1) $Obj_ConnMgr = ObjCreate("PCOMM.autECLConnMgr") ; Maybe this is not needed? Anyone know what it is for? $OBJ_EmulSession = ObjCreate("PCOMM.autECLSession") ; getting closer $OBJ_EmulSession.SetConnectionByName($Session) ; now you are connected to the session $Ps = $OBJ_EmulSession.autECLPS ; Object for the user interface $Oia = $OBJ_EmulSession.autECLOIA ; Object for the message interface (terminology... remember I'm in sales;) ) Func sendtosession($keys, $rownum = 1, $colnum = 1, $inhibit = 1) $Ps.SendKeys($keys, $rownum, $colnum) ; actual usage for AS400 macros too if $inhibit = 1 Then While $Oia.InputInhibited <> 0 WEnd EndIf EndFunc $Ps.GetText("Row","Col","Length") ; actual usage for AS400 macros too Again, I'm not trying to provide a working example with the above, I'm just passing the information along. Below is a simple script I created to update contract prices for over 400 items (manually it took hours, now it takes only minutes) you can run this code, but it will not do anything unless you have the data and the AS400 session. You get the gist of it though, I'm sure. Hopefully this helps someone else out there. Dan #include <GUIConstantsEx.au3> #include <Excel_CPU.au3> #include <array.au3> #include <WindowsConstants.au3> #include <C:\Documents and Settings\r060091\My Documents\Requires Backup\send to as400 session.au3> ;sendtosession($keys, $rownum = 1, $colnum = 1, $inhibit = 1) Opt("guioneventmode", 1) Opt("mustdeclarevars", 1) Opt("trayicondebug", 1) ;********************************** set contract expiration date Global $Expiration_Date = "013111";** ;********************************** Global Const $Col_Price = 12 Global Const $Col_Item = 1 Global Const $Col_Cust = 1 Global Const $Col_UOM = "" Global Const $District = 12 Global $Obj_ConnMgr, $OBJ_EmulSession, $Ps, $Oia, $OBJ_Excel, $AS400hwnd, $GUI_hwnd, $Array_Excel_Price_Sheet, $Screen_ID Create_Helper_GUI() Func SET_AS400() Local $window, $Session $window = WinGetTitle("") $AS400hwnd = WinGetHandle($window) $Session = StringMid(WinGetTitle($AS400hwnd), 9, 1) $Obj_ConnMgr = ObjCreate("PCOMM.autECLConnMgr") $OBJ_EmulSession = ObjCreate("PCOMM.autECLSession") $OBJ_EmulSession.SetConnectionByName($Session) $Ps = $OBJ_EmulSession.autECLPS $Oia = $OBJ_EmulSession.autECLOIA EndFunc ;==>SET_AS400 Func SET_Excel() GUISetState(@SW_HIDE) HotKeySet("^1") Local $exwindow $exwindow = WinGetTitle("") $OBJ_Excel = _ExcelBookAttach($exwindow, "Title") $Array_Excel_Price_Sheet = _ExcelReadSheetToArray($OBJ_Excel, 2, 1) ;~ _ArrayDisplay($Array_Excel_Price_Sheet) GUISetState(@SW_SHOW) EndFunc ;==>SET_Excel Func Change_Prices() GUIDelete($GUI_hwnd) Local $Price, $UOM, $Customer, $Item, $Cust_Item, $Delimiter For $COUNTER_Row = 1 To UBound($Array_Excel_Price_Sheet) - 1 $Price = Round($Array_Excel_Price_Sheet[$COUNTER_Row][$Col_Price], 3) If $Col_UOM <> "" Then $UOM = $Array_Excel_Price_Sheet[$COUNTER_Row][$Col_UOM] If $Col_Cust <> $Col_Item Then $Customer = $Array_Excel_Price_Sheet[$COUNTER_Row][$Col_Cust] $Item = $Array_Excel_Price_Sheet[$COUNTER_Row][$Col_Item] Else $Cust_Item = $Array_Excel_Price_Sheet[$COUNTER_Row][$Col_Cust] $Delimiter = StringInStr($Cust_Item, "-") $Customer = StringMid($Cust_Item, $Delimiter + 1) $Item = StringLeft($Cust_Item, $Delimiter - 1) EndIf sendtosession($District & $Customer, 10, 45) sendtosession($Item, 12, 45) sendtosession("[eraseeof]", 12, StringLen($Item) + 45) sendtosession("[PF11]") $Screen_ID = $Ps.GetText(2, 1, 8) If $Screen_ID = "PM413-01" Then Switch $Ps.GetText(24, 2, 7) Case "INV0010" $OBJ_Excel.Application.Cells($COUNTER_Row + 1, $Col_Item).Interior.ColorIndex = 6 MsgBox(0, "Error", "No item code available; the affected cell has been highlighted yellow. Click OK to continue." & @CRLF & @CRLF & "This message closes automatically after ~30 seconds.", 30) ContinueLoop Case "INV0011" $OBJ_Excel.Application.Cells($COUNTER_Row + 1, $Col_Item).Interior.ColorIndex = 3 MsgBox(0, "Error", "The item code appears to be invalid; the affected cell has been highlighted red. Click OK to continue." & @CRLF & @CRLF & "This message closes automatically after ~30 seconds.", 30) ContinueLoop Case "AR00002" $OBJ_Excel.Application.Cells($COUNTER_Row + 1, $Col_Cust).Interior.ColorIndex = 3 MsgBox(0, "Error", "The Customer number appears to be invalid; the affected cell has been highlighted red. Click OK to continue." & @CRLF & @CRLF & "This message closes automatically after ~30 seconds.", 30) ContinueLoop Case "AR00062" sendtosession("[PF10]") Case "CNS0003" sendtosession("[PF5]") While $Ps.GetText(2, 1, 8) <> "PM413-02" WEnd sendtosession("Y", 21, 46) sendtosession("[enter]") sendtosession("[PF11]") EndSwitch EndIf While $Ps.GetText(2, 1, 8) <> "PM413-02" WEnd sendtosession($Price, 10, 48) sendtosession("[eraseeof]", 10, StringLen($Price) + 48) If $Col_UOM <> "" Then sendtosession($UOM, 11, 48) If $Col_UOM <> "" Then sendtosession("[eraseeof]", 11, StringLen($UOM) + 48) sendtosession($Expiration_Date, 12, 48) sendtosession("[Enter]") While $Ps.GetText(2, 1, 8) <> "PM413-01" WEnd Switch $Ps.GetText(24, 2, 7) Case "CNS0008" $OBJ_Excel.Application.Cells($COUNTER_Row + 1, $Col_Item).Interior.ColorIndex = 6 MsgBox(0, "Error", "For some reason this item was not accepted; the affected cell has been highlighted yellow. Click OK to continue." & @CRLF & @CRLF & "This message closes automatically after ~30 seconds.", 30) ContinueLoop Case "CNS0005" ContinueLoop Case "CNS0074" ContinueLoop Case "CNS0004" ContinueLoop Case Else $OBJ_Excel.Application.Cells($COUNTER_Row + 1, $Col_Item).Interior.ColorIndex = 7 MsgBox(0, "Error", "An unknown error has occured. The affected cell has been highlighted pink. Click OK to continue." & @CRLF & @CRLF & "This message closes automatically after ~30 seconds.", 30) ContinueLoop EndSwitch Next MsgBox(0, "", "Success!") Exit EndFunc ;==>Change_Prices Func Create_Helper_GUI() Local $GUI_Instruct_Label, $GUI_Window_Label, $Last_Title, $Contract_Expires, $Change_Prices_Button $GUI_hwnd = GUICreate("AS400 Contract Maintenance Tool", 600, 75, -1, -1, $GUI_SS_DEFAULT_GUI, $WS_EX_TOPMOST) GUISetState(@SW_SHOW) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents", $GUI_hwnd) $GUI_Instruct_Label = GUICtrlCreateLabel("Activate the AS400 session you would like to use to update the contract prices, then press CTRL-1.", 10, 10, 580) $GUI_Window_Label = GUICtrlCreateLabel("Current Window: " & WinGetTitle("[active]"), 10, 30, 580) HotKeySet("^1", "SET_AS400") While $AS400hwnd = "" If WinGetTitle("[active]") <> $Last_Title Then GUICtrlSetData($GUI_Window_Label, "Current Window: " & WinGetTitle("[active]")) $Last_Title = WinGetTitle("[active]") EndIf WEnd HotKeySet("^1") GUICtrlSetData($GUI_Instruct_Label, "OK, now activate the Excel document that contains your contract prices and press CTRL-1") HotKeySet("^1", "SET_EXCEL") While Not IsObj($OBJ_Excel) If WinGetTitle("[active]") <> $Last_Title Then GUICtrlSetData($GUI_Window_Label, "Current Window: " & WinGetTitle("[active]")) $Last_Title = WinGetTitle("[active]") EndIf WEnd HotKeySet("^1") ;~ GUICtrlSetData($GUI_Instruct_Label, "What is the contract expiration date?") GUICtrlSetData($GUI_Window_Label, "") GUICtrlDelete($GUI_Window_Label) ;~ $Contract_Expires = GUICtrlCreateDate("Expires:", 10, 30, 250, 25) $Change_Prices_Button = GUICtrlCreateButton("Change Prices", 410, 30) GUICtrlSetOnEvent($Change_Prices_Button, "change_prices") While 1 WEnd EndFunc ;==>Create_Helper_GUI Func SpecialEvents() Exit EndFunc ;==>SpecialEvents
-
see the controlsend help documentation also... Send("hello world{!}")
-
How to truncate text in a variable
DangerousDan replied to ScriptNoob's topic in AutoIt General Help and Support
you mean you didn't like my example? -
How to truncate text in a variable
DangerousDan replied to ScriptNoob's topic in AutoIt General Help and Support
I've had a lot of practice with the string functions anyone do this in stringregexp yet? I quit reading when it went way over my head, does scripting experience help you understand that crap any better ? $string = "CN=Last\, First,OU=Accounts,OU=Corporate,OU=FSGN,DC=fsgn,DC=net" ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $string = ' & $string & @crlf & '>Error code: ' & @error & @crlf);### Debug Console $newstring=stringtrimright(StringTrimLeft($string,StringInStr($string,",",2,3)),(stringlen($string)-stringinstr($string,",",2,-3)+1)) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $newstring = ' & $newstring & @crlf & '>Error code: ' & @error & @crlf);### Debug Console -
iniread and network drives
DangerousDan replied to DangerousDan's topic in AutoIt General Help and Support
That's fantastic, actually Thanks a ton! I recognize your screen name too, thanks for helping me by helping others. edit: that couldn't have been simpler. it tool me all of two minutes to make the necessary changes to the script, thanks again ResNullius -
iniread and network drives
DangerousDan replied to DangerousDan's topic in AutoIt General Help and Support
that is a step in the right direction then. however, I do not currently have the knowledge to use SQL_lite functions. I will have to read more, it would appear, unless someone wants to modify the script in the linked post for me If this method ends up working out I'd like to be able to load the ini to memory when certain functions are called from my program, that way the data is updated before it is used but it doesn't read from the network each time the data is used in the function. The data is only used for short periods at a time, so loading to memory at the beginning of the function is the best way to keep it up to date. It's looking more and more like I'd need to use an array; either way I am going to have to modify some major code. at least with the array method I'll be modifying my code and making sure I don't make the same programming mistake twice thanks for the help everyone, and unless someone has the free time to modify the SQL_lite DB ini code for my use I will call this resolved -
iniread and network drives
DangerousDan replied to DangerousDan's topic in AutoIt General Help and Support
opposite of what he suggested. not overwriting original file here, he's suggesting copy file locally and use it, the filedelete is after execution cleanup. main issue here is there are currently ~20 users; could be as many as 1000 users company wide using this file, and all log on at different times (three working shifts; four apps written into program spanning three departments) -
iniread and network drives
DangerousDan replied to DangerousDan's topic in AutoIt General Help and Support
it's a "live" system, copying the file locally at startup will only partially solve my problem. any user can add or modify keys (keys are inventory control item codes, the value is the customer part number for cross reference) but no users can delete keys. if I add a key at 10am I need the user who opened the program at 9AM to be able to use this new key. I know I can use the array method with inireadsection to speed up the individual function operations (the program goes very slow when each line on the AS400 emulator causes the ini file to be read with iniread consecutively) but since the code will need moderate changes to run in this method I was looking to see the ini file loaded to memory. does anyone else have another method aside from the two suggested so far? both methods will work, but don't accomplish my goal. thanks again guys. -
iniread and network drives
DangerousDan replied to DangerousDan's topic in AutoIt General Help and Support
The main issue is I want all users to be able to add to the ini file. I suppose an array would work, I had hoped to not modify the script though. easy to do in an array, but more difficult than iniread calls. the variable method would be harder to do, I must be able to search for the key and return the value; also the number of values will be unknown as the user can add keys. I'll most likely leave it on the network drive and use iniread if there is no way to load to memory and use iniread... thanks for your help so far -
I am using an ini file on a network drive to store customer information. The script I have written polls the ini file occasionally, and I have Tooltips to indicate to the user that a network drive is being used and it will take a second, but the script is real slow sometimes due to other network activity. I have no way to store the ini file locally. I "could" copy it locally each time the program is started, but don't want to if I don't have to. The program is loaded from the network, and anything I need from the network is loaded into memory at that time as well, so startup is expected to take a minute. is there any way to load the ini file to memory and then use the iniread functionality on the file in memory, similar to fileopen? AutoIt n00b, please be gentle
-
Screen Resolution Changing UDF
DangerousDan replied to PartyPooper's topic in AutoIt Example Scripts
in response to the script not exiting/remaining in system tray. comment out lines 62 and 63 ;~ DllCall($dll, "int", "SendMessage", "hwnd", $HWND_BROADCAST, "int", $WM_DISPLAYCHANGE, _ ;~ "int", $i_BitsPP, "int", $i_Height * 2 ^ 16 + $i_Width) that's what was making the function hang for me on Vista SP1. on another note: for some reason Vista constantly resets my screen res to 1024x768 after it resumes from suspend mode... I wrote a script to keep in the quick launch bar until I can figure it out lol. -
can you increment the "current" bar during a file operation (filecopy) depending on how much of the operation has progressed or will it increment in a certain period of time? I'm still not sure how these work...
-
not sure how to use progress bars yet, but will this help? can you make the bar increment from the right? that would be another minor change to this example to make it closer to what you say you want. #include <GUIConstantsEx.au3> #include <ProgressConstants.au3> #include <WindowsConstants.au3> $count=1 $x=0 $increment=0 $Form1 = GUICreate("Form1", 321, 239, 193, 125) $Progress1 = GUICtrlCreateProgress(48, 48, 209, 33) $Progress2 = GUICtrlCreateProgress(48, 96, 209, 41) GUISetState(@SW_SHOW) while $increment<1000 if $count=1 then $x += 1 if $x>99 then $count=2 if $count=2 then $x -= 1 if $x<1 then $count=1 GUICtrlSetData($Progress1,$x) GUICtrlSetData($Progress2,$increment/10) sleep(50) $increment += 1 ;need to increment second loop with your file operations WEnd GUIDelete($form1) msgbox(0,"","Done")